Parses a parameter list for the given function kind. See:
(&mut self, function_kind: FunctionKind)
| 3294 | /// |
| 3295 | /// See: <https://docs.python.org/3/reference/compound_stmts.html#grammar-token-python-grammar-parameter_list> |
| 3296 | pub(super) fn parse_parameters(&mut self, function_kind: FunctionKind) -> ast::Parameters { |
| 3297 | let start = self.node_start(); |
| 3298 | |
| 3299 | if matches!(function_kind, FunctionKind::FunctionDef) { |
| 3300 | self.expect(TokenKind::Lpar); |
| 3301 | } |
| 3302 | |
| 3303 | // TODO(dhruvmanila): This has the same problem as `parse_match_pattern_mapping` |
| 3304 | // has where if there are multiple kwarg or vararg, the last one will win and |
| 3305 | // the parser will drop the previous ones. Another thing is the vararg and kwarg |
| 3306 | // uses `Parameter` (not `ParameterWithDefault`) which means that the parser cannot |
| 3307 | // recover well from `*args=(1, 2)`. |
| 3308 | let mut parameters = ast::Parameters::default(); |
| 3309 | let parameters_snapshot = self.parameter_scratch.snapshot(); |
| 3310 | let mut args_snapshot = None; |
| 3311 | let mut kwonlyargs_snapshot = None; |
| 3312 | |
| 3313 | let mut seen_default_param = false; // `a=10` |
| 3314 | let mut seen_positional_only_separator = false; // `/` |
| 3315 | let mut seen_keyword_only_separator = false; // `*` |
| 3316 | let mut seen_keyword_only_param_after_separator = false; |
| 3317 | |
| 3318 | // Range of the keyword only separator if it's the last parameter in the list. |
| 3319 | let mut last_keyword_only_separator_range = None; |
| 3320 | |
| 3321 | self.parse_comma_separated_list(RecoveryContextKind::Parameters(function_kind), |parser| { |
| 3322 | let param_start = parser.node_start(); |
| 3323 | |
| 3324 | if parameters.kwarg.is_some() { |
| 3325 | // test_err params_follows_var_keyword_param |
| 3326 | // def foo(**kwargs, a, /, b=10, *, *args): ... |
| 3327 | parser.add_error( |
| 3328 | ParseErrorType::ParamAfterVarKeywordParam, |
| 3329 | parser.current_token_range(), |
| 3330 | ); |
| 3331 | } |
| 3332 | |
| 3333 | match parser.current_token_kind() { |
| 3334 | TokenKind::Star => { |
| 3335 | let star_range = parser.current_token_range(); |
| 3336 | parser.bump(TokenKind::Star); |
| 3337 | |
| 3338 | kwonlyargs_snapshot.get_or_insert_with(|| parser.parameter_scratch.snapshot()); |
| 3339 | |
| 3340 | if parser.at_name_or_soft_keyword() { |
| 3341 | let param = parser.parse_parameter( |
| 3342 | param_start, |
| 3343 | function_kind, |
| 3344 | AllowStarAnnotation::Yes, |
| 3345 | ); |
| 3346 | let param_star_range = parser.node_range(star_range.start()); |
| 3347 | |
| 3348 | if parser.at(TokenKind::Equal) { |
| 3349 | // test_err params_var_positional_with_default |
| 3350 | // def foo(a, *args=(1, 2)): ... |
| 3351 | parser.add_error( |
| 3352 | ParseErrorType::VarParameterWithDefault, |
| 3353 | parser.current_token_range(), |
no test coverage detected