Consider : to terminate parenthesized with items (#11775)

## Summary

This PR is a follow-up to this discussion
(https://github.com/astral-sh/ruff/pull/11770#discussion_r1628917209)
which adds the `:` token in the terminator set for parenthesized with
items.

The main motivation is to avoid parsing too much in speculative mode.
This is evident with the following _before_ and _after_ parsed with
items list for the following code:

```py
with (item1, item2:
    foo
```

<table>
  <tr>
    <th>Before (3 items)</th>
    <th>After (2 items)</th>
  </tr>
  <tr>
    <td>
<pre>
parsed_with_items: [
    ParsedWithItem {
        item: WithItem {
            range: 6..11,
            context_expr: Name(
                ExprName {
                    range: 6..11,
                    id: "item1",
                    ctx: Load,
                },
            ),
            optional_vars: None,
        },
        is_parenthesized: false,
    },
    ParsedWithItem {
        item: WithItem {
            range: 13..18,
            context_expr: Name(
                ExprName {
                    range: 13..18,
                    id: "item2",
                    ctx: Load,
                },
            ),
            optional_vars: None,
        },
        is_parenthesized: false,
    },
    ParsedWithItem {
        item: WithItem {
            range: 24..27,
            context_expr: Name(
                ExprName {
                    range: 24..27,
                    id: "foo",
                    ctx: Load,
                },
            ),
            optional_vars: None,
        },
        is_parenthesized: false,
    },
]
</pre>
	</td>
    <td>
<pre>
parsed_with_items: [
    ParsedWithItem {
        item: WithItem {
            range: 6..11,
            context_expr: Name(
                ExprName {
                    range: 6..11,
                    id: "item1",
                    ctx: Load,
                },
            ),
            optional_vars: None,
        },
        is_parenthesized: false,
    },
    ParsedWithItem {
        item: WithItem {
            range: 13..18,
            context_expr: Name(
                ExprName {
                    range: 13..18,
                    id: "item2",
                    ctx: Load,
                },
            ),
            optional_vars: None,
        },
        is_parenthesized: false,
    },
]
</pre>
	</td>
  </tr>
</table>

## Test Plan

`cargo insta test`
This commit is contained in:
Dhruv Manilawala 2024-06-06 18:40:44 +05:30 committed by GitHub
parent fcaa62f0d9
commit 1b7d08c2c9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -718,16 +718,6 @@ enum WithItemKind {
}
impl WithItemKind {
/// Returns the token that terminates a list of `with` items.
const fn list_terminator(self) -> TokenKind {
match self {
WithItemKind::Parenthesized => TokenKind::Rpar,
WithItemKind::Unparenthesized | WithItemKind::ParenthesizedExpression => {
TokenKind::Colon
}
}
}
/// Returns `true` if the with items are parenthesized.
const fn is_parenthesized(self) -> bool {
matches!(self, WithItemKind::Parenthesized)
@ -958,9 +948,14 @@ impl RecoveryContextKind {
|| p.at(TokenKind::Rarrow)
|| p.at_compound_stmt()
}
RecoveryContextKind::WithItems(with_item_kind) => {
p.at(with_item_kind.list_terminator())
}
RecoveryContextKind::WithItems(with_item_kind) => match with_item_kind {
WithItemKind::Parenthesized => {
matches!(p.current_token_kind(), TokenKind::Rpar | TokenKind::Colon)
}
WithItemKind::Unparenthesized | WithItemKind::ParenthesizedExpression => {
p.at(TokenKind::Colon)
}
},
RecoveryContextKind::FStringElements => {
// Tokens other than `FStringEnd` and `}` are for better error recovery
p.at_ts(TokenSet::new([