]> git.madduck.net Git - etc/vim.git/commitdiff

madduck's git repository

Every one of the projects in this repository is available at the canonical URL git://git.madduck.net/madduck/pub/<projectpath> — see each project's metadata for the exact URL.

All patches and comments are welcome. Please squash your changes to logical commits before using git-format-patch and git-send-email to patches@git.madduck.net. If you'd read over the Git project's submission guidelines and adhered to them, I'd be especially grateful.

SSH access, as well as push access can be individually arranged.

If you use my repositories frequently, consider adding the following snippet to ~/.gitconfig and using the third clone URL listed for each project:

[url "git://git.madduck.net/madduck/"]
  insteadOf = madduck:

Fix unstable formatting involving unwrapping multiple parentheses (#836) (#961)
authorJoe Antonakakis <jma353@cornell.edu>
Fri, 23 Aug 2019 14:51:29 +0000 (07:51 -0700)
committerZsolt Dollenstein <zsol.zsol@gmail.com>
Fri, 23 Aug 2019 14:51:29 +0000 (15:51 +0100)
This change also unwraps all unnecessary parentheses.

black.py
tests/data/remove_parens.py

index 391039243f5d17b0d5063a6e0f69e3b1a9882d48..f178aceb4dc9820d8b3562a29b2c2295de1341af 100644 (file)
--- a/black.py
+++ b/black.py
@@ -2882,7 +2882,15 @@ def normalize_invisible_parens(node: Node, parens_after: Set[str]) -> None:
             if is_walrus_assignment(child):
                 continue
             if child.type == syms.atom:
             if is_walrus_assignment(child):
                 continue
             if child.type == syms.atom:
-                if maybe_make_parens_invisible_in_atom(child, parent=node):
+                # Determines if the underlying atom should be surrounded with
+                # invisible params - also makes parens invisible recursively
+                # within the atom and removes repeated invisible parens within
+                # the atom
+                should_surround_with_parens = maybe_make_parens_invisible_in_atom(
+                    child, parent=node
+                )
+
+                if should_surround_with_parens:
                     lpar = Leaf(token.LPAR, "")
                     rpar = Leaf(token.RPAR, "")
                     index = child.remove() or 0
                     lpar = Leaf(token.LPAR, "")
                     rpar = Leaf(token.RPAR, "")
                     index = child.remove() or 0
@@ -2999,6 +3007,8 @@ def generate_ignored_nodes(leaf: Leaf) -> Iterator[LN]:
 
 def maybe_make_parens_invisible_in_atom(node: LN, parent: LN) -> bool:
     """If it's safe, make the parens in the atom `node` invisible, recursively.
 
 def maybe_make_parens_invisible_in_atom(node: LN, parent: LN) -> bool:
     """If it's safe, make the parens in the atom `node` invisible, recursively.
+    Additionally, remove repeated, adjacent invisible parens from the atom `node`
+    as they are redundant.
 
     Returns whether the node should itself be wrapped in invisible parentheses.
 
 
     Returns whether the node should itself be wrapped in invisible parentheses.
 
@@ -3015,15 +3025,40 @@ def maybe_make_parens_invisible_in_atom(node: LN, parent: LN) -> bool:
     first = node.children[0]
     last = node.children[-1]
     if first.type == token.LPAR and last.type == token.RPAR:
     first = node.children[0]
     last = node.children[-1]
     if first.type == token.LPAR and last.type == token.RPAR:
+        middle = node.children[1]
         # make parentheses invisible
         first.value = ""  # type: ignore
         last.value = ""  # type: ignore
         # make parentheses invisible
         first.value = ""  # type: ignore
         last.value = ""  # type: ignore
-        maybe_make_parens_invisible_in_atom(node.children[1], parent=parent)
+        maybe_make_parens_invisible_in_atom(middle, parent=parent)
+
+        if is_atom_with_invisible_parens(middle):
+            # Strip the invisible parens from `middle` by replacing
+            # it with the child in-between the invisible parens
+            middle.replace(middle.children[1])
+
         return False
 
     return True
 
 
         return False
 
     return True
 
 
+def is_atom_with_invisible_parens(node: LN) -> bool:
+    """Given a `LN`, determines whether it's an atom `node` with invisible
+    parens. Useful in dedupe-ing and normalizing parens.
+    """
+    if isinstance(node, Leaf) or node.type != syms.atom:
+        return False
+
+    first, last = node.children[0], node.children[-1]
+    return (
+        isinstance(first, Leaf)
+        and first.type == token.LPAR
+        and first.value == ""
+        and isinstance(last, Leaf)
+        and last.type == token.RPAR
+        and last.value == ""
+    )
+
+
 def is_empty_tuple(node: LN) -> bool:
     """Return True if `node` holds an empty tuple."""
     return (
 def is_empty_tuple(node: LN) -> bool:
     """Return True if `node` holds an empty tuple."""
     return (
index f08f91a8af54f12f0269d84df3c3e4d284a1825f..e128f59518a78ef8e91f5d3d5826616cccc75a1a 100644 (file)
@@ -3,8 +3,118 @@ x = (1)
 x = (1.2)
 (x) = (3)
 
 x = (1.2)
 (x) = (3)
 
+
+def example():
+    return (("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"))
+
+
+def example1():
+    return ((1111111111111111111111111111111111111111111111111111111111111111111111111111111111111))
+
+
+def example1point5():
+    return ((((((1111111111111111111111111111111111111111111111111111111111111111111111111111111111111))))))
+
+
+def example2():
+    return (("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"))
+
+
+def example3():
+    return ((1111111111111111111111111111111111111111111111111111111111111111111111111111111))
+
+
+def example4():
+    return ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((True))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
+
+
+def example5():
+    return ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((()))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
+
+
+def example6():
+    return ((((((((({a:a for a in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]})))))))))
+
+
+def example7():
+    return ((((((((({a:a for a in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20000000000000000000]})))))))))
+
+
+def example8():
+    return (((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((None)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
+
+
 # output
 print(1)
 x = 1
 x = 1.2
 x = 3
 # output
 print(1)
 x = 1
 x = 1.2
 x = 3
+
+
+def example():
+    return "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+
+
+def example1():
+    return 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111
+
+
+def example1point5():
+    return 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111
+
+
+def example2():
+    return (
+        "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+    )
+
+
+def example3():
+    return (
+        1111111111111111111111111111111111111111111111111111111111111111111111111111111
+    )
+
+
+def example4():
+    return True
+
+
+def example5():
+    return ()
+
+
+def example6():
+    return {a: a for a in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]}
+
+
+def example7():
+    return {
+        a: a
+        for a in [
+            1,
+            2,
+            3,
+            4,
+            5,
+            6,
+            7,
+            8,
+            9,
+            10,
+            11,
+            12,
+            13,
+            14,
+            15,
+            16,
+            17,
+            18,
+            19,
+            20000000000000000000,
+        ]
+    }
+
+
+def example8():
+    return None
+