mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-31 15:48:22 +00:00
Raise syntax error for unparenthesized generator expr in multi-argument call (#12445)
## Summary This PR fixes a bug to raise a syntax error when an unparenthesized generator expression is used as an argument to a call when there are more than one argument. For reference, the grammar is: ``` primary: | ... | primary genexp | primary '(' [arguments] ')' | ... genexp: | '(' ( assignment_expression | expression !':=') for_if_clauses ')' ``` The `genexp` requires the parenthesis as mentioned in the grammar. So, the grammar for a call expression is either a name followed by a generator expression or a name followed by a list of argument. In the former case, the parenthesis are excluded because the generator expression provides them while in the later case, the parenthesis are explicitly provided for a list of arguments which means that the generator expression requires it's own parenthesis. This was discovered in https://github.com/astral-sh/ruff/issues/12420. ## Test Plan Add test cases for valid and invalid syntax. Make sure that the parser from CPython also raises this at the parsing step: ```console $ python3.13 -m ast parser/_.py File "parser/_.py", line 1 total(1, 2, x for x in range(5), 6) ^^^^^^^^^^^^^^^^^^^ SyntaxError: Generator expression must be parenthesized $ python3.13 -m ast parser/_.py File "parser/_.py", line 1 sum(x for x in range(10), 10) ^^^^^^^^^^^^^^^^^^^^ SyntaxError: Generator expression must be parenthesized ```
This commit is contained in:
parent
f8735e1ee8
commit
978909fcf4
7 changed files with 336 additions and 4 deletions
|
@ -2272,9 +2272,10 @@ impl<'src> Parser<'src> {
|
|||
command
|
||||
}
|
||||
|
||||
/// Validate that the given arguments doesn't have any duplicate keyword argument.
|
||||
///
|
||||
/// Report errors for all the duplicate names found.
|
||||
/// Performs the following validations on the function call arguments:
|
||||
/// 1. There aren't any duplicate keyword argument
|
||||
/// 2. If there are more than one argument (positional or keyword), all generator expressions
|
||||
/// present should be parenthesized.
|
||||
fn validate_arguments(&mut self, arguments: &ast::Arguments) {
|
||||
let mut all_arg_names =
|
||||
FxHashSet::with_capacity_and_hasher(arguments.keywords.len(), FxBuildHasher);
|
||||
|
@ -2292,6 +2293,25 @@ impl<'src> Parser<'src> {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
if arguments.len() > 1 {
|
||||
for arg in arguments.args.iter() {
|
||||
if let Some(ast::ExprGenerator {
|
||||
range,
|
||||
parenthesized: false,
|
||||
..
|
||||
}) = arg.as_generator_expr()
|
||||
{
|
||||
// test_ok args_unparenthesized_generator
|
||||
// sum(x for x in range(10))
|
||||
|
||||
// test_err args_unparenthesized_generator
|
||||
// sum(x for x in range(10), 5)
|
||||
// total(1, 2, x for x in range(5), 6)
|
||||
self.add_error(ParseErrorType::UnparenthesizedGeneratorExpression, range);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue