Trying to rework the indentation stack.

This commit is contained in:
Dave Halter
2017-06-12 23:52:27 +02:00
parent 5f14382103
commit 7981a309d1
2 changed files with 64 additions and 38 deletions

View File

@@ -64,11 +64,20 @@ class WhitespaceInfo(object):
self.comment_whitespace = [] self.comment_whitespace = []
class BracketNode(object): class IndentationNode(object):
SAME_INDENT_TYPE = object() SAME_INDENT_TYPE = object()
NEWLINE_TYPE = object() NEWLINE_TYPE = object()
BACKSLASH_TYPE = object()
SUITE_TYPE = object()
def __init__(self, config, indentation_level, leaf): type = SUITE_TYPE
def __init__(self, config, indentation_level):
self.indentation = config.indentation * indentation_level
class BracketNode(IndentationNode):
def __init__(self, config, parent_indentation, leaf):
next_leaf = leaf.get_next_leaf() next_leaf = leaf.get_next_leaf()
if '\n' in next_leaf.prefix: if '\n' in next_leaf.prefix:
# This implies code like: # This implies code like:
@@ -76,8 +85,8 @@ class BracketNode(object):
# a, # a,
# b, # b,
# ) # )
self.bracket_indentation = config.indentation * indentation_level self.bracket_indentation = parent_indentation
self.item_indentation = self.bracket_indentation + config.indentation self.indentation = parent_indentation + config.indentation
self.type = self.NEWLINE_TYPE self.type = self.NEWLINE_TYPE
else: else:
# Implies code like: # Implies code like:
@@ -87,19 +96,18 @@ class BracketNode(object):
# ) # )
self.expected_end_indent = leaf.end_pos[1] self.expected_end_indent = leaf.end_pos[1]
if '\t' in config.indentation: if '\t' in config.indentation:
self.bracket_indentation = None self.indentation = None
else: else:
self.bracket_indentation = ' ' * self.expected_end_indent self.indentation = ' ' * self.expected_end_indent
self.item_indentation = self.bracket_indentation self.bracket_indentation = self.indentation
self.type = self.SAME_INDENT_TYPE self.type = self.SAME_INDENT_TYPE
class BackslashNode(object): class BackslashNode(IndentationNode):
BACKSLASH_TYPE = object() type = IndentationNode.BACKSLASH_TYPE
def __init__(self, indentation_level):
self.bracket_indentation = self.item_indentation = \ def __init__(self, config, parent_indentation):
config.indentation * indentation_level self.indentation = parent_indentation + config.indentation
self.type = self.NEWLINE_TYPE
def _is_magic_name(name): def _is_magic_name(name):
@@ -109,10 +117,9 @@ def _is_magic_name(name):
class PEP8Normalizer(Normalizer): class PEP8Normalizer(Normalizer):
def __init__(self, config): def __init__(self, config):
super(PEP8Normalizer, self).__init__(config) super(PEP8Normalizer, self).__init__(config)
self._indentation_level = 0
self._last_indentation_level = 0 self._last_indentation_level = 0
self._on_newline = True self._on_newline = True
self._bracket_stack = [] self._indentation_stack = [IndentationNode(config, indentation_level=0)]
if ' ' in config.indentation: if ' ' in config.indentation:
self._indentation_type = 'spaces' self._indentation_type = 'spaces'
@@ -182,10 +189,13 @@ class PEP8Normalizer(Normalizer):
break break
if typ == 'suite': if typ == 'suite':
self._indentation_level += 1 self._indentation_stack.append(
IndentationNode(self._config, len(self._indentation_stack))
)
yield yield
if typ == 'suite': if typ == 'suite':
self._indentation_level -= 1 assert self._indentation_stack[-1].type == IndentationNode.SUITE_TYPE
self._indentation_stack.pop()
def _check_tabs_spaces(self, leaf, indentation): def _check_tabs_spaces(self, leaf, indentation):
if self._wrong_indentation_char in indentation: if self._wrong_indentation_char in indentation:
@@ -196,25 +206,25 @@ class PEP8Normalizer(Normalizer):
def normalize(self, leaf): def normalize(self, leaf):
value = leaf.value value = leaf.value
info = WhitespaceInfo(leaf) info = WhitespaceInfo(leaf)
should_be_indenation = self._indentation_level * self._config.indentation should_be_indentation = self._indentation_stack[-1].indentation
if self._on_newline: if self._on_newline:
if self._bracket_stack and \ if self._indentation_stack and \
self._bracket_stack[-1].type == BackslashNode.BACKSLASH_TYPE: self._indentation_stack[-1].type == BackslashNode.BACKSLASH_TYPE:
self._bracket_stack.pop() self._indentation_stack.pop()
if info.indentation != should_be_indenation: if info.indentation != should_be_indentation:
if not self._check_tabs_spaces(info.indentation_part, info.indentation): if not self._check_tabs_spaces(info.indentation_part, info.indentation):
s = '%s %s' % (len(self._config.indentation), self._indentation_type) s = '%s %s' % (len(self._config.indentation), self._indentation_type)
self.add_issue(111, 'Indentation is not a multiple of ' + s, leaf) self.add_issue(111, 'Indentation is not a multiple of ' + s, leaf)
elif info.newline_count: elif info.newline_count:
if self._bracket_stack: if self._indentation_stack[-1]:
node = self._bracket_stack[-1] node = self._indentation_stack[-1]
if value in '])}': if value in '])}':
should_be_indenation = node.bracket_indentation should_be_indentation = node.bracket_indentation
else: else:
should_be_indenation = node.item_indentation should_be_indentation = node.indentation
if info.indentation != should_be_indenation: if info.indentation != should_be_indentation:
if not self._check_tabs_spaces(info.indentation_part, info.indentation): if not self._check_tabs_spaces(info.indentation_part, info.indentation):
if len(info.indentation) < len(should_be_indenation): if len(info.indentation) < len(should_be_indentation):
if value in '])}': if value in '])}':
self.add_issue(124, "Closing bracket does not match visual indentation", leaf) self.add_issue(124, "Closing bracket does not match visual indentation", leaf)
else: else:
@@ -232,10 +242,15 @@ class PEP8Normalizer(Normalizer):
self.add_issue(126, 'Continuation line over-indented for hanging indent', leaf) self.add_issue(126, 'Continuation line over-indented for hanging indent', leaf)
if info.has_backslash: if info.has_backslash:
if self._bracket_stack: if self._indentation_stack[-1].type != IndentationNode.SUITE_TYPE:
self.add_issue(502, 'The backslash is redundant between brackets', leaf) self.add_issue(502, 'The backslash is redundant between brackets', leaf)
else: else:
self._bracket_stack.append(BackslashNode(self._indentation_level)) self._indentation_stack.append(
BackslashNode(
self._config,
self._indentation_stack[-1].indentation
)
)
first = True first = True
for comment in info.comments: for comment in info.comments:
@@ -245,14 +260,14 @@ class PEP8Normalizer(Normalizer):
actual_len = len(comment.indentation) actual_len = len(comment.indentation)
# Comments can be dedented. So we have to care for that. # Comments can be dedented. So we have to care for that.
for i in range(self._last_indentation_level, self._indentation_level - 1, -1): for i in range(self._last_indentation_level, len(self._indentation_stack) - 2, -1):
should_be_indenation = i * self._config.indentation should_be_indentation = i * self._config.indentation
should_len = len(should_be_indenation) should_len = len(should_be_indentation)
if actual_len >= should_len: if actual_len >= should_len:
break break
if comment.indentation == should_be_indenation: if comment.indentation == should_be_indentation:
self._last_indentation_level = i self._last_indentation_level = i
else: else:
if not self._check_tabs_spaces(comment.indentation_part, comment.indentation): if not self._check_tabs_spaces(comment.indentation_part, comment.indentation):
@@ -271,13 +286,21 @@ class PEP8Normalizer(Normalizer):
if value and value in '()[]{}' and leaf.type != 'error_leaf' \ if value and value in '()[]{}' and leaf.type != 'error_leaf' \
and leaf.parent.type != 'error_node': and leaf.parent.type != 'error_node':
if value in '([{': if value in '([{':
node = BracketNode(self._config, self._indentation_level, leaf) self._indentation_stack.append(
self._bracket_stack.append(node) BracketNode(
self._config, self._indentation_stack[-1].indentation,
leaf
)
)
else: else:
self._bracket_stack.pop() self._indentation_stack.pop()
self._on_newline = leaf.type == 'newline' self._on_newline = leaf.type == 'newline'
self._last_indentation_level = self._indentation_level # TODO does this work? with brackets and stuff?
self._last_indentation_level = len(self._indentation_stack)
if self._on_newline and \
self._indentation_stack[-1].type == IndentationNode.BACKSLASH_TYPE:
self._indentation_stack.pop()
return value return value

View File

@@ -30,12 +30,15 @@ class TestP4Poller(unittest.TestCase):
if True: if True:
#: E101:0 #: E101:0
foo(1, foo(1,
#: E101:0
2) 2)
def test_keys(self): def test_keys(self):
"""areas.json - All regions are accounted for.""" """areas.json - All regions are accounted for."""
expected = set([ expected = set([
#: E101:0
u'Norrbotten', u'Norrbotten',
#: E101:0
u'V\xe4sterbotten', u'V\xe4sterbotten',
]) ])
if True: if True: