Rules: indentation: Rewrite stack generation

"Indentation stack" generation was not done properly, hence did not work
in all cases. This commit does a cleaner rewriting.
pull/4/head
Adrien Vergé 9 years ago
parent 3f264806b9
commit 8d38d349ac

@ -154,7 +154,7 @@ CONF = {'spaces': int,
'indent-sequences': (True, False, 'whatever'), 'indent-sequences': (True, False, 'whatever'),
'check-multi-line-strings': bool} 'check-multi-line-strings': bool}
ROOT, MAP, B_SEQ, F_SEQ, B_ENT, KEY, VAL = range(7) ROOT, B_MAP, F_MAP, B_SEQ, F_SEQ, B_ENT, KEY, VAL = range(8)
class Parent(object): class Parent(object):
@ -163,6 +163,7 @@ class Parent(object):
self.indent = indent self.indent = indent
self.line_indent = line_indent self.line_indent = line_indent
self.explicit_key = False self.explicit_key = False
self.implicit_block_seq = False
def check_scalar_indentation(conf, token, context): def check_scalar_indentation(conf, token, context):
@ -276,9 +277,6 @@ def check(conf, token, prev, next, context):
# Step 2.b: Update state # Step 2.b: Update state
if context['stack'][-1].type == B_ENT:
context['stack'].pop()
if isinstance(token, yaml.BlockMappingStartToken): if isinstance(token, yaml.BlockMappingStartToken):
assert isinstance(next, yaml.KeyToken) assert isinstance(next, yaml.KeyToken)
if next.start_mark.line == token.start_mark.line: if next.start_mark.line == token.start_mark.line:
@ -294,7 +292,7 @@ def check(conf, token, prev, next, context):
# : 1 # : 1
indent = token.start_mark.column + conf['spaces'] indent = token.start_mark.column + conf['spaces']
context['stack'].append(Parent(MAP, indent)) context['stack'].append(Parent(B_MAP, indent))
elif isinstance(token, yaml.FlowMappingStartToken): elif isinstance(token, yaml.FlowMappingStartToken):
if next.start_mark.line == token.start_mark.line: if next.start_mark.line == token.start_mark.line:
@ -306,7 +304,7 @@ def check(conf, token, prev, next, context):
# } # }
indent = context['cur_line_indent'] + conf['spaces'] indent = context['cur_line_indent'] + conf['spaces']
context['stack'].append(Parent(MAP, indent, context['stack'].append(Parent(F_MAP, indent,
line_indent=context['cur_line_indent'])) line_indent=context['cur_line_indent']))
elif isinstance(token, yaml.BlockSequenceStartToken): elif isinstance(token, yaml.BlockSequenceStartToken):
@ -322,6 +320,12 @@ def check(conf, token, prev, next, context):
elif (isinstance(token, yaml.BlockEntryToken) and elif (isinstance(token, yaml.BlockEntryToken) and
# in case of an empty entry # in case of an empty entry
not isinstance(next, (yaml.BlockEntryToken, yaml.BlockEndToken))): not isinstance(next, (yaml.BlockEntryToken, yaml.BlockEndToken))):
# It looks like pyyaml doesn't issue BlockSequenceStartTokens when the
# list is not indented. We need to compensate that.
if context['stack'][-1].type != B_SEQ:
context['stack'].append(Parent(B_SEQ, token.start_mark.column))
context['stack'][-1].implicit_block_seq = True
if next.start_mark.line == token.end_mark.line: if next.start_mark.line == token.end_mark.line:
# - item 1 # - item 1
# - item 2 # - item 2
@ -349,12 +353,6 @@ def check(conf, token, prev, next, context):
context['stack'].append(Parent(F_SEQ, indent, context['stack'].append(Parent(F_SEQ, indent,
line_indent=context['cur_line_indent'])) line_indent=context['cur_line_indent']))
elif isinstance(token, (yaml.BlockEndToken,
yaml.FlowMappingEndToken,
yaml.FlowSequenceEndToken)):
assert context['stack'][-1].type in (MAP, B_SEQ, F_SEQ)
context['stack'].pop()
elif isinstance(token, yaml.KeyToken): elif isinstance(token, yaml.KeyToken):
indent = context['stack'][-1].indent indent = context['stack'][-1].indent
@ -362,21 +360,14 @@ def check(conf, token, prev, next, context):
context['stack'][-1].explicit_key = is_explicit_key(token) context['stack'][-1].explicit_key = is_explicit_key(token)
if context['stack'][-1].type == VAL:
context['stack'].pop()
assert context['stack'][-1].type == KEY
context['stack'].pop()
elif isinstance(token, yaml.ValueToken): elif isinstance(token, yaml.ValueToken):
assert context['stack'][-1].type == KEY assert context['stack'][-1].type == KEY
# Discard empty values # Only if value is not empty
if isinstance(next, (yaml.BlockEndToken, if not isinstance(next, (yaml.BlockEndToken,
yaml.FlowMappingEndToken, yaml.FlowMappingEndToken,
yaml.FlowSequenceEndToken, yaml.FlowSequenceEndToken,
yaml.KeyToken)): yaml.KeyToken)):
context['stack'].pop()
else:
if context['stack'][-1].explicit_key: if context['stack'][-1].explicit_key:
# ? k # ? k
# : value # : value
@ -417,11 +408,49 @@ def check(conf, token, prev, next, context):
context['stack'].append(Parent(VAL, indent)) context['stack'].append(Parent(VAL, indent))
if (context['stack'][-1].type == KEY and consumed_current_token = False
isinstance(next, (yaml.BlockEndToken, while True:
yaml.FlowMappingEndToken, if (context['stack'][-1].type == F_SEQ and
yaml.FlowSequenceEndToken, isinstance(token, yaml.FlowSequenceEndToken)):
yaml.KeyToken))): context['stack'].pop()
# A key without a value: it's part of a set. Let's drop this key
# and leave room for the next one. elif (context['stack'][-1].type == F_MAP and
context['stack'].pop() isinstance(token, yaml.FlowMappingEndToken)):
context['stack'].pop()
elif (context['stack'][-1].type in (B_MAP, B_SEQ) and
isinstance(token, yaml.BlockEndToken) and
not context['stack'][-1].implicit_block_seq and
not consumed_current_token):
context['stack'].pop()
consumed_current_token = True
elif (context['stack'][-1].type == B_ENT and
not isinstance(token, yaml.BlockEntryToken) and
context['stack'][-2].implicit_block_seq and
not isinstance(next, yaml.ScalarToken)):
# isinstance(next, yaml.KeyToken)):
context['stack'].pop()
context['stack'].pop()
elif (context['stack'][-1].type == B_ENT and
isinstance(next, (yaml.BlockEntryToken, yaml.BlockEndToken))):
context['stack'].pop()
elif (context['stack'][-1].type == VAL and
not isinstance(token, yaml.ValueToken)):
assert context['stack'][-2].type == KEY
context['stack'].pop()
context['stack'].pop()
elif (context['stack'][-1].type == KEY and
isinstance(next, (yaml.BlockEndToken,
yaml.FlowMappingEndToken,
yaml.FlowSequenceEndToken,
yaml.KeyToken))):
# A key without a value: it's part of a set. Let's drop this key
# and leave room for the next one.
context['stack'].pop()
else:
break

Loading…
Cancel
Save