[syntax-errors] Improve error message and range for pre-PEP-614 decorator syntax errors (#16581)

## Summary

A small followup to https://github.com/astral-sh/ruff/pull/16386. We now
tell the user exactly what it was about their decorator that constituted
invalid syntax on Python <3.9, and the range now highlights the specific
sub-expression that is invalid rather than highlighting the whole
decorator

## Test Plan

Inline snapshots are updated, and new ones are added.
This commit is contained in:
Alex Waygood
2025-03-17 11:17:27 +00:00
committed by GitHub
parent 4da6936ec4
commit 38bfda94ce
15 changed files with 574 additions and 19 deletions

View File

@@ -2705,17 +2705,45 @@ impl<'src> Parser<'src> {
// # parse_options: { "target-version": "3.7" }
// @(x := lambda x: x)(foo)
// def bar(): ...
let allowed_decorator = match &parsed_expr.expr {
// test_err decorator_dict_literal_py38
// # parse_options: { "target-version": "3.8" }
// @{3: 3}
// def bar(): ...
// test_err decorator_float_literal_py38
// # parse_options: { "target-version": "3.8" }
// @3.14
// def bar(): ...
// test_ok decorator_await_expression_py39
// # parse_options: { "target-version": "3.9" }
// async def foo():
// @await bar
// def baz(): ...
// test_err decorator_await_expression_py38
// # parse_options: { "target-version": "3.8" }
// async def foo():
// @await bar
// def baz(): ...
// test_err decorator_non_toplevel_call_expression_py38
// # parse_options: { "target-version": "3.8" }
// @foo().bar()
// def baz(): ...
let relaxed_decorator_error = match &parsed_expr.expr {
Expr::Call(expr_call) => {
helpers::is_name_or_attribute_expression(&expr_call.func)
helpers::detect_invalid_pre_py39_decorator_node(&expr_call.func)
}
expr => helpers::is_name_or_attribute_expression(expr),
expr => helpers::detect_invalid_pre_py39_decorator_node(expr),
};
if !allowed_decorator {
if let Some((error, range)) = relaxed_decorator_error {
self.add_unsupported_syntax_error(
UnsupportedSyntaxErrorKind::RelaxedDecorator,
parsed_expr.range(),
UnsupportedSyntaxErrorKind::RelaxedDecorator(error),
range,
);
}
}