mirror of
https://github.com/davidhalter/parso.git
synced 2025-12-24 05:01:44 +08:00
Trying to rework the indentation stack.
This commit is contained in:
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
Reference in New Issue
Block a user