"""
String transformers that can split and merge strings.
"""
+import re
+import sys
from abc import ABC, abstractmethod
from collections import defaultdict
from dataclasses import dataclass
-import re
from typing import (
Any,
Callable,
TypeVar,
Union,
)
-import sys
if sys.version_info < (3, 8):
- from typing_extensions import Literal, Final
+ from typing_extensions import Final, Literal
else:
from typing import Literal, Final
from mypy_extensions import trait
-from black.rusty import Result, Ok, Err
-
-from black.mode import Feature
-from black.nodes import syms, replace_child, parent_type
-from black.nodes import is_empty_par, is_empty_lpar, is_empty_rpar
-from black.nodes import OPENING_BRACKETS, CLOSING_BRACKETS, STANDALONE_COMMENT
-from black.lines import Line, append_leaves
from black.brackets import BracketMatchError
from black.comments import contains_pragma_comment
-from black.strings import has_triple_quotes, get_string_prefix, assert_is_leaf_string
-from black.strings import normalize_string_quotes
-
-from blib2to3.pytree import Leaf, Node
+from black.lines import Line, append_leaves
+from black.mode import Feature
+from black.nodes import (
+ CLOSING_BRACKETS,
+ OPENING_BRACKETS,
+ STANDALONE_COMMENT,
+ is_empty_lpar,
+ is_empty_par,
+ is_empty_rpar,
+ parent_type,
+ replace_child,
+ syms,
+)
+from black.rusty import Err, Ok, Result
+from black.strings import (
+ assert_is_leaf_string,
+ get_string_prefix,
+ has_triple_quotes,
+ normalize_string_quotes,
+)
from blib2to3.pgen2 import token
+from blib2to3.pytree import Leaf, Node
class CannotTransform(Exception):
return False
- leaves: List[Leaf] = []
+ new_line = line.clone()
should_hug = False
for idx, leaf in enumerate(line.leaves):
new_leaf = leaf.clone()
if should_hug:
new_leaf.prefix = ""
- leaves.append(new_leaf)
-
- yield Line(
- mode=line.mode,
- depth=line.depth,
- leaves=leaves,
- comments=line.comments,
- bracket_tracker=line.bracket_tracker,
- inside_brackets=line.inside_brackets,
- should_split_rhs=line.should_split_rhs,
- magic_trailing_comma=line.magic_trailing_comma,
- )
+ # We have to be careful to make a new line properly:
+ # - bracket related metadata must be maintained (handled by Line.append)
+ # - comments need to copied over, updating the leaf IDs they're attached to
+ new_line.append(new_leaf, preformatted=True)
+ for comment_leaf in line.comments_after(leaf):
+ new_line.append(comment_leaf, preformatted=True)
+
+ yield new_line
class StringTransformer(ABC):
next_str_idx += 1
+ # Take a note on the index of the non-STRING leaf.
+ non_string_idx = next_str_idx
+
S_leaf = Leaf(token.STRING, S)
if self.normalize_strings:
S_leaf.value = normalize_string_quotes(S_leaf.value)
string_leaf = Leaf(token.STRING, S_leaf.value.replace(BREAK_MARK, ""))
if atom_node is not None:
- replace_child(atom_node, string_leaf)
+ # If not all children of the atom node are merged (this can happen
+ # when there is a standalone comment in the middle) ...
+ if non_string_idx - string_idx < len(atom_node.children):
+ # We need to replace the old STRING leaves with the new string leaf.
+ first_child_idx = LL[string_idx].remove()
+ for idx in range(string_idx + 1, non_string_idx):
+ LL[idx].remove()
+ if first_child_idx is not None:
+ atom_node.insert_child(first_child_idx, string_leaf)
+ else:
+ # Else replace the atom node with the new string leaf.
+ replace_child(atom_node, string_leaf)
# Build the final line ('new_line') that this method will later return.
new_line = line.clone()