Decided how to indent stuff after keyword arguments and in dict literals.

This commit is contained in:
Dave Halter
2017-06-21 09:47:24 +02:00
parent c11dd6b5aa
commit 9081cf55fb

View File

@@ -6,6 +6,7 @@ _IMPORT_TYPES = ('import_name', 'import_from')
_SUITE_INTRODUCERS = ('classdef', 'funcdef', 'if_stmt', 'while_stmt', _SUITE_INTRODUCERS = ('classdef', 'funcdef', 'if_stmt', 'while_stmt',
'for_stmt', 'try_stmt', 'with_stmt') 'for_stmt', 'try_stmt', 'with_stmt')
_OPENING_BRACKETS = '([{' _OPENING_BRACKETS = '([{'
_IMPLICIT_INDENTATION_TYPES = ('dictorsetmaker', 'argument')
class CompressNormalizer(Normalizer): class CompressNormalizer(Normalizer):
""" """
@@ -68,22 +69,27 @@ class WhitespaceInfo(object):
self.comment_whitespace = [] self.comment_whitespace = []
class IndentationNode(object): class IndentationTypes(object):
SAME_INDENT_TYPE = object() VERTICAL_BRACKET = object()
NEWLINE_TYPE = object() HANGING_BRACKET = object()
BACKSLASH_TYPE = object() BACKSLASH = object()
SUITE_TYPE = object() SUITE = object()
IMPLICIT = object()
type = SUITE_TYPE class IndentationNode(object):
type = IndentationTypes.SUITE
def __init__(self, config, indentation_level): def __init__(self, config, indentation_level):
self.bracket_indentation = self.indentation = config.indentation * indentation_level self.bracket_indentation = self.indentation = config.indentation * indentation_level
def __repr__(self):
return '<%s>' % self.__class__.__name__
class IndentationStack(list): class IndentationStack(list):
def get_latest_suite_node(self): def get_latest_suite_node(self):
for node in reversed(self): for node in reversed(self):
if node.type == IndentationNode.SUITE_TYPE: if node.type == IndentationTypes.SUITE:
return node return node
@@ -98,9 +104,10 @@ class BracketNode(IndentationNode):
# a, # a,
# b, # b,
# ) # )
self.bracket_indentation = parent_indentation self.bracket_indentation = parent_indentation \
+ config.closing_bracket_hanging_indentation
self.indentation = parent_indentation + config.indentation self.indentation = parent_indentation + config.indentation
self.type = self.NEWLINE_TYPE self.type = IndentationTypes.HANGING_BRACKET
else: else:
# Implies code like: # Implies code like:
# foobarbaz( # foobarbaz(
@@ -113,11 +120,25 @@ class BracketNode(IndentationNode):
else: else:
self.indentation = ' ' * self.expected_end_indent self.indentation = ' ' * self.expected_end_indent
self.bracket_indentation = self.indentation self.bracket_indentation = self.indentation
self.type = self.SAME_INDENT_TYPE self.type = IndentationTypes.VERTICAL_BRACKET
class ImplicitNode(BracketNode):
"""
Implicit indentation after keyword arguments, default arguments,
annotations and dict values.
"""
def __init__(self, config, parent_indentation, leaf):
super(ImplicitNode, self).__init__(config, parent_indentation, leaf)
self.type = IndentationTypes.IMPLICIT
next_leaf = leaf.get_next_leaf()
if leaf == ':' and '\n' not in next_leaf.prefix:
self.indentation += ' '
class BackslashNode(IndentationNode): class BackslashNode(IndentationNode):
type = IndentationNode.BACKSLASH_TYPE type = IndentationTypes.BACKSLASH
def __init__(self, config, parent_indentation): def __init__(self, config, parent_indentation):
self.bracket_indentation = self.indentation = parent_indentation + config.indentation self.bracket_indentation = self.indentation = parent_indentation + config.indentation
@@ -132,6 +153,7 @@ class PEP8Normalizer(Normalizer):
super(PEP8Normalizer, self).__init__(config) super(PEP8Normalizer, self).__init__(config)
self._last_indentation_level = 0 self._last_indentation_level = 0
self._on_newline = True self._on_newline = True
self._implicit_indentation_possible = False
self._indentation_stack = IndentationStack( self._indentation_stack = IndentationStack(
[IndentationNode(config, indentation_level=0)] [IndentationNode(config, indentation_level=0)]
) )
@@ -204,23 +226,28 @@ class PEP8Normalizer(Normalizer):
continue continue
break break
implicit_indentation_possible = typ in _IMPLICIT_INDENTATION_TYPES
in_introducer = typ in _SUITE_INTRODUCERS in_introducer = typ in _SUITE_INTRODUCERS
if in_introducer: if in_introducer:
self._in_suite_introducer = True self._in_suite_introducer = True
elif typ == 'suite':
if typ == 'suite': if self._indentation_stack[-1].type == IndentationTypes.BACKSLASH:
if self._indentation_stack[-1].type == IndentationNode.BACKSLASH_TYPE:
self._indentation_stack.pop() self._indentation_stack.pop()
self._indentation_stack.append( self._indentation_stack.append(
IndentationNode(self._config, len(self._indentation_stack)) IndentationNode(self._config, len(self._indentation_stack))
) )
elif implicit_indentation_possible:
self._implicit_indentation_possible = True
yield yield
if typ == 'suite': if typ == 'suite':
assert self._indentation_stack[-1].type == IndentationNode.SUITE_TYPE assert self._indentation_stack[-1].type == IndentationTypes.SUITE
self._indentation_stack.pop() self._indentation_stack.pop()
elif implicit_indentation_possible:
if in_introducer: self._implicit_indentation_possible = False
if self._indentation_stack[-1].type == IndentationTypes.IMPLICIT:
self._indentation_stack.pop()
elif in_introducer:
self._in_suite_introducer = False self._in_suite_introducer = False
def _check_tabs_spaces(self, leaf, indentation): def _check_tabs_spaces(self, leaf, indentation):
@@ -233,21 +260,28 @@ class PEP8Normalizer(Normalizer):
value = leaf.value value = leaf.value
info = WhitespaceInfo(leaf) info = WhitespaceInfo(leaf)
if value == ',' and leaf.parent.type == 'dictorsetmaker':
self._indentation_stack.pop()
node = self._indentation_stack[-1] node = self._indentation_stack[-1]
if info.has_backslash and node.type != IndentationNode.BACKSLASH_TYPE:
if node.type != IndentationNode.SUITE_TYPE: if info.has_backslash and node.type != IndentationTypes.BACKSLASH:
if node.type != IndentationTypes.SUITE:
self.add_issue(502, 'The backslash is redundant between brackets', leaf) self.add_issue(502, 'The backslash is redundant between brackets', leaf)
else: else:
indentation = node.indentation
if self._in_suite_introducer and node.type == IndentationTypes.SUITE:
indentation += self._config.indentation
node = BackslashNode( node = BackslashNode(
self._config, self._config,
self._indentation_stack[-1].indentation indentation
) )
self._indentation_stack.append(node) self._indentation_stack.append(node)
if self._on_newline: if self._on_newline:
if self._indentation_stack and \ if node.type == IndentationTypes.BACKSLASH:
self._indentation_stack[-1].type == BackslashNode.BACKSLASH_TYPE:
self._indentation_stack.pop() self._indentation_stack.pop()
if info.indentation != node.indentation: if info.indentation != node.indentation:
if not self._check_tabs_spaces(info.indentation_part, info.indentation): if not self._check_tabs_spaces(info.indentation_part, info.indentation):
@@ -266,21 +300,25 @@ class PEP8Normalizer(Normalizer):
elif info.indentation != should_be_indentation: elif 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 value in '])}': if value in '])}':
if node.type == IndentationNode.SAME_INDENT_TYPE: if node.type == IndentationTypes.VERTICAL_BRACKET:
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:
self.add_issue(123, "Losing bracket does not match indentation of opening bracket's line", leaf) self.add_issue(123, "Losing bracket does not match indentation of opening bracket's line", leaf)
else: else:
if len(info.indentation) < len(should_be_indentation): if len(info.indentation) < len(should_be_indentation):
if node.type == IndentationNode.SAME_INDENT_TYPE: if node.type == IndentationTypes.VERTICAL_BRACKET:
self.add_issue(128, 'Continuation line under-indented for visual indent', leaf) self.add_issue(128, 'Continuation line under-indented for visual indent', leaf)
elif node.type == IndentationNode.BACKSLASH_TYPE: elif node.type == IndentationTypes.BACKSLASH:
self.add_issue(122, 'Continuation line missing indentation or outdented', leaf) self.add_issue(122, 'Continuation line missing indentation or outdented', leaf)
elif node.type == IndentationTypes.IMPLICIT:
self.add_issue(135, 'xxx', leaf)
else: else:
self.add_issue(121, 'Continuation line under-indented for hanging indent', leaf) self.add_issue(121, 'Continuation line under-indented for hanging indent', leaf)
else: else:
if node.type == IndentationNode.SAME_INDENT_TYPE: if node.type == IndentationTypes.VERTICAL_BRACKET:
self.add_issue(127, 'Continuation line over-indented for visual indent', leaf) self.add_issue(127, 'Continuation line over-indented for visual indent', leaf)
elif node.type == IndentationTypes.IMPLICIT:
self.add_issue(136, 'xxx', leaf)
else: else:
self.add_issue(126, 'Continuation line over-indented for hanging indent', leaf) self.add_issue(126, 'Continuation line over-indented for hanging indent', leaf)
@@ -332,7 +370,7 @@ class PEP8Normalizer(Normalizer):
break break
index += 1 index += 1
indentation = self._indentation_stack[-index].indentation indentation = self._indentation_stack[-index].indentation
if self._in_suite_introducer and node.type == node.SUITE_TYPE: if self._in_suite_introducer and node.type == IndentationTypes.SUITE:
indentation += self._config.indentation indentation += self._config.indentation
self._indentation_stack.append( self._indentation_stack.append(
@@ -342,13 +380,20 @@ class PEP8Normalizer(Normalizer):
) )
) )
else: else:
assert node.type != IndentationTypes.IMPLICIT
self._indentation_stack.pop() self._indentation_stack.pop()
elif value in ('=', ':') and self._implicit_indentation_possible \
and leaf.parent.type in _IMPLICIT_INDENTATION_TYPES:
indentation = node.indentation
self._indentation_stack.append(
ImplicitNode(self._config, indentation, leaf)
)
self._on_newline = leaf.type == 'newline' self._on_newline = leaf.type == 'newline'
# TODO does this work? with brackets and stuff? # TODO does this work? with brackets and stuff?
self._last_indentation_level = len(self._indentation_stack) self._last_indentation_level = len(self._indentation_stack)
if self._on_newline and \ if self._on_newline and \
self._indentation_stack[-1].type == IndentationNode.BACKSLASH_TYPE: self._indentation_stack[-1].type == IndentationTypes.BACKSLASH:
self._indentation_stack.pop() self._indentation_stack.pop()
if value == ':' and leaf.parent.type in _SUITE_INTRODUCERS: if value == ':' and leaf.parent.type in _SUITE_INTRODUCERS:
@@ -431,6 +476,8 @@ class PEP8NormalizerConfig(NormalizerConfig):
if hanging_indentation is None: if hanging_indentation is None:
hanging_indentation = indentation hanging_indentation = indentation
self.hanging_indentation = hanging_indentation self.hanging_indentation = hanging_indentation
self.closing_bracket_hanging_indentation = ''
self.break_after_binary = False
@PEP8NormalizerConfig.register_rule @PEP8NormalizerConfig.register_rule