예제 #1
0
파일: linegen.py 프로젝트: psf/black
def maybe_make_parens_invisible_in_atom(
    node: LN,
    parent: LN,
    remove_brackets_around_comma: bool = False,
) -> 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.
    """
    if (
        node.type != syms.atom
        or is_empty_tuple(node)
        or is_one_tuple(node)
        or (is_yield(node) and parent.type != syms.expr_stmt)
        or (
            # This condition tries to prevent removing non-optional brackets
            # around a tuple, however, can be a bit overzealous so we provide
            # and option to skip this check for `for` and `with` statements.
            not remove_brackets_around_comma
            and max_delimiter_priority_in_atom(node) >= COMMA_PRIORITY
        )
    ):
        return False

    if is_walrus_assignment(node):
        if parent.type in [
            syms.annassign,
            syms.expr_stmt,
            syms.assert_stmt,
            syms.return_stmt,
            # these ones aren't useful to end users, but they do please fuzzers
            syms.for_stmt,
            syms.del_stmt,
        ]:
            return False

    first = node.children[0]
    last = node.children[-1]
    if is_lpar_token(first) and is_rpar_token(last):
        middle = node.children[1]
        # make parentheses invisible
        first.value = ""
        last.value = ""
        maybe_make_parens_invisible_in_atom(
            middle,
            parent=parent,
            remove_brackets_around_comma=remove_brackets_around_comma,
        )

        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
예제 #2
0
파일: linegen.py 프로젝트: jleclanche/tan
def maybe_make_parens_invisible_in_atom(
    node: LN,
    parent: LN,
    preview: bool = False,
) -> 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.

    """
    if (preview and parent.type == syms.for_stmt
            and isinstance(node.prev_sibling, Leaf)
            and node.prev_sibling.type == token.NAME
            and node.prev_sibling.value == "for"):
        for_stmt_check = False
    else:
        for_stmt_check = True

    if (node.type != syms.atom or is_empty_tuple(node) or is_one_tuple(node)
            or (is_yield(node) and parent.type != syms.expr_stmt)
            or (max_delimiter_priority_in_atom(node) >= COMMA_PRIORITY
                and for_stmt_check)):
        return False

    if is_walrus_assignment(node):
        if parent.type in [
                syms.annassign,
                syms.expr_stmt,
                syms.assert_stmt,
                syms.return_stmt,
                # these ones aren't useful to end users, but they do please fuzzers
                syms.for_stmt,
                syms.del_stmt,
        ]:
            return False

    first = node.children[0]
    last = node.children[-1]
    if is_lpar_token(first) and is_rpar_token(last):
        middle = node.children[1]
        # make parentheses invisible
        first.value = ""
        last.value = ""
        maybe_make_parens_invisible_in_atom(middle,
                                            parent=parent,
                                            preview=preview)

        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
예제 #3
0
파일: linegen.py 프로젝트: jleclanche/tan
def normalize_invisible_parens(node: Node, parens_after: Set[str], *,
                               preview: bool) -> None:
    """Make existing optional parentheses invisible or create new ones.

    `parens_after` is a set of string leaf values immediately after which parens
    should be put.

    Standardizes on visible parentheses for single-element tuples, and keeps
    existing visible parentheses for other tuples and generator expressions.
    """
    for pc in list_comments(node.prefix, is_endmarker=False, preview=preview):
        if pc.value in FMT_OFF:
            # This `node` has a prefix with `# fmt: off`, don't mess with parens.
            return
    check_lpar = False
    for index, child in enumerate(list(node.children)):
        # Fixes a bug where invisible parens are not properly stripped from
        # assignment statements that contain type annotations.
        if isinstance(child, Node) and child.type == syms.annassign:
            normalize_invisible_parens(child,
                                       parens_after=parens_after,
                                       preview=preview)

        # Add parentheses around long tuple unpacking in assignments.
        if (index == 0 and isinstance(child, Node)
                and child.type == syms.testlist_star_expr):
            check_lpar = True

        if check_lpar:
            if child.type == syms.atom:
                if maybe_make_parens_invisible_in_atom(
                        child,
                        parent=node,
                        preview=preview,
                ):
                    wrap_in_parentheses(node, child, visible=False)
            elif is_one_tuple(child):
                wrap_in_parentheses(node, child, visible=True)
            elif node.type == syms.import_from:
                # "import from" nodes store parentheses directly as part of
                # the statement
                if is_lpar_token(child):
                    assert is_rpar_token(node.children[-1])
                    # make parentheses invisible
                    child.value = ""
                    node.children[-1].value = ""
                elif child.type != token.STAR:
                    # insert invisible parentheses
                    node.insert_child(index, Leaf(token.LPAR, ""))
                    node.append_child(Leaf(token.RPAR, ""))
                break

            elif not (isinstance(child, Leaf) and is_multiline_string(child)):
                wrap_in_parentheses(node, child, visible=False)

        check_lpar = isinstance(child, Leaf) and child.value in parens_after