Fix arithmetic stability issue (#2817)
It turns out "simple_stmt" isn't that simple: it can contain multiple statements separated by semicolons. Invisible parenthesis logic for arithmetic expressions only looked at the first child of simple_stmt. This causes instability in the presence of semicolons, since the next run through the statement following the semicolon will be the first child of another simple_stmt. I believe this along with #2572 fix the known stability issues.
This commit is contained in:
parent
df0aeeeee0
commit
95e77cb559
@ -24,6 +24,7 @@ and the first release covered by our new stability policy.
|
|||||||
- Don't add whitespace for attribute access on hexadecimal, binary, octal, and complex
|
- Don't add whitespace for attribute access on hexadecimal, binary, octal, and complex
|
||||||
literals (#2799)
|
literals (#2799)
|
||||||
- Treat blank lines in stubs the same inside top-level `if` statements (#2820)
|
- Treat blank lines in stubs the same inside top-level `if` statements (#2820)
|
||||||
|
- Fix unstable formatting with semicolons and arithmetic expressions (#2817)
|
||||||
|
|
||||||
### Parser
|
### Parser
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
from black.nodes import WHITESPACE, RARROW, STATEMENT, STANDALONE_COMMENT
|
from black.nodes import WHITESPACE, RARROW, STATEMENT, STANDALONE_COMMENT
|
||||||
from black.nodes import ASSIGNMENTS, OPENING_BRACKETS, CLOSING_BRACKETS
|
from black.nodes import ASSIGNMENTS, OPENING_BRACKETS, CLOSING_BRACKETS
|
||||||
from black.nodes import Visitor, syms, first_child_is_arith, ensure_visible
|
from black.nodes import Visitor, syms, is_arith_like, ensure_visible
|
||||||
from black.nodes import is_docstring, is_empty_tuple, is_one_tuple, is_one_tuple_between
|
from black.nodes import is_docstring, is_empty_tuple, is_one_tuple, is_one_tuple_between
|
||||||
from black.nodes import is_name_token, is_lpar_token, is_rpar_token
|
from black.nodes import is_name_token, is_lpar_token, is_rpar_token
|
||||||
from black.nodes import is_walrus_assignment, is_yield, is_vararg, is_multiline_string
|
from black.nodes import is_walrus_assignment, is_yield, is_vararg, is_multiline_string
|
||||||
@ -156,8 +156,12 @@ def visit_suite(self, node: Node) -> Iterator[Line]:
|
|||||||
|
|
||||||
def visit_simple_stmt(self, node: Node) -> Iterator[Line]:
|
def visit_simple_stmt(self, node: Node) -> Iterator[Line]:
|
||||||
"""Visit a statement without nested statements."""
|
"""Visit a statement without nested statements."""
|
||||||
if first_child_is_arith(node):
|
prev_type: Optional[int] = None
|
||||||
wrap_in_parentheses(node, node.children[0], visible=False)
|
for child in node.children:
|
||||||
|
if (prev_type is None or prev_type == token.SEMI) and is_arith_like(child):
|
||||||
|
wrap_in_parentheses(node, child, visible=False)
|
||||||
|
prev_type = child.type
|
||||||
|
|
||||||
is_suite_like = node.parent and node.parent.type in STATEMENT
|
is_suite_like = node.parent and node.parent.type in STATEMENT
|
||||||
if is_suite_like:
|
if is_suite_like:
|
||||||
if self.mode.is_pyi and is_stub_body(node):
|
if self.mode.is_pyi and is_stub_body(node):
|
||||||
|
@ -531,15 +531,14 @@ def first_leaf_column(node: Node) -> Optional[int]:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def first_child_is_arith(node: Node) -> bool:
|
def is_arith_like(node: LN) -> bool:
|
||||||
"""Whether first child is an arithmetic or a binary arithmetic expression"""
|
"""Whether node is an arithmetic or a binary arithmetic expression"""
|
||||||
expr_types = {
|
return node.type in {
|
||||||
syms.arith_expr,
|
syms.arith_expr,
|
||||||
syms.shift_expr,
|
syms.shift_expr,
|
||||||
syms.xor_expr,
|
syms.xor_expr,
|
||||||
syms.and_expr,
|
syms.and_expr,
|
||||||
}
|
}
|
||||||
return bool(node.children and node.children[0].type in expr_types)
|
|
||||||
|
|
||||||
|
|
||||||
def is_docstring(leaf: Leaf) -> bool:
|
def is_docstring(leaf: Leaf) -> bool:
|
||||||
|
Loading…
Reference in New Issue
Block a user