Repository: astral-sh/ruff
File: crates/ruff_python_parser/src/parser/statement.rs (Rust)

Code before:
                // with (x)[0] if True else y: ...

                // test_ok ambiguous_lpar_with_items_binary_expr
                // # It doesn't matter what's inside the parentheses, these tests need to make sure
                // # all binary expressions parses correctly.
                // with (a) and b: ...
                // with (a) is not b: ...
                // # Make sure precedence works
                // with (a) or b and c: ...
                // with (a) and b or c: ...
                // with (a | b) << c | d: ...
                // # Postfix should still be parsed first
                // with (a)[0] + b * c: ...
                self.parse_comma_separated_list_into_vec(
                    RecoveryContextKind::WithItems(WithItemKind::ParenthesizedExpression),
                    |p| p.parse_with_item(WithItemParsingState::Regular).item,
                )
            }
        } else {
            // test_err ipython_escape_command_in_with_statement
            // # parse_options: {"mode": "ipython"}
            // with a,?b
            //     pass
            // with a,?b
            //     x = 1
            //     y = 2
            self.parse_comma_separated_list_into_vec(
                RecoveryContextKind::WithItems(WithItemKind::Unparenthesized),
                |p| p.parse_with_item(WithItemParsingState::Regular).item,
            )
        }
    }

    /// Try parsing with-items coming after an ambiguous `(` token.
    ///
    /// To understand the ambiguity, consider the following example:
    ///
    /// ```python
    /// with (item1, item2): ...       # Parenthesized with items
    /// with (item1, item2) as f: ...  # Parenthesized expression
    /// ```
    ///
    /// When the parser is at the `(` token after the `with` keyword, it doesn't know if `(` is
    /// used to parenthesize the with items or if it's part of a parenthesized expression of the
    /// first with item. The challenge here is that until the parser sees the matching `)` token,
    /// it can't resolve the ambiguity.
    ///
    /// This method resolves the ambiguity using speculative parsing. It starts with an assumption
    /// that it's a parenthesized with items. Then, once it finds the matching `)`, it checks if
    /// the assumption still holds true. If the initial assumption was correct, this will return
    /// the parsed with items. Otherwise, rewind the parser back to the starting `(` token,

Review comment (suggestion):
We should add some test cases that contains parentheses like the ones that I've mentioned in my comment

Code after:
                // with (x)[0] if True else y: ...

                // test_ok ambiguous_lpar_with_items_binary_expr
                // # It doesn't matter what's inside the parentheses, these tests need to make sure
                // # all binary expressions parses correctly.
                // with (a) and b: ...
                // with (a) is not b: ...
                // # Make sure precedence works
                // with (a) or b and c: ...
                // with (a) and b or c: ...
                // with (a | b) << c | d: ...
                // # Postfix should still be parsed first
                // with (a)[0] + b * c: ...
                self.parse_comma_separated_list_into_vec(
                    RecoveryContextKind::WithItems(WithItemKind::ParenthesizedExpression),
                    |p| p.parse_with_item(WithItemParsingState::Regular).item,
                )
            }
        } else {
            self.parse_comma_separated_list_into_vec(
                RecoveryContextKind::WithItems(WithItemKind::Unparenthesized),
                |p| p.parse_with_item(WithItemParsingState::Regular).item,
            )
        }
    }

    /// Try parsing with-items coming after an ambiguous `(` token.
    ///
    /// To understand the ambiguity, consider the following example:
    ///
    /// ```python
    /// with (item1, item2): ...       # Parenthesized with items
    /// with (item1, item2) as f: ...  # Parenthesized expression
    /// ```
    ///
    /// When the parser is at the `(` token after the `with` keyword, it doesn't know if `(` is
    /// used to parenthesize the with items or if it's part of a parenthesized expression of the
    /// first with item. The challenge here is that until the parser sees the matching `)` token,
    /// it can't resolve the ambiguity.
    ///
    /// This method resolves the ambiguity using speculative parsing. It starts with an assumption
    /// that it's a parenthesized with items. Then, once it finds the matching `)`, it checks if
    /// the assumption still holds true. If the initial assumption was correct, this will return
    /// the parsed with items. Otherwise, rewind the parser back to the starting `(` token,
    /// returning [`None`].
    ///
    /// # Panics
    ///
    /// If the parser isn't positioned at a `(` token.
    ///
    /// See: <https://docs.python.org/3/reference/compound_stmts.html#grammar-token-python-grammar-with_stmt_contents>