mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-03 18:28:56 +00:00
[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:
parent
4da6936ec4
commit
38bfda94ce
15 changed files with 574 additions and 19 deletions
|
@ -0,0 +1,96 @@
|
|||
---
|
||||
source: crates/ruff_python_parser/tests/fixtures.rs
|
||||
input_file: crates/ruff_python_parser/resources/inline/err/decorator_await_expression_py38.py
|
||||
---
|
||||
## AST
|
||||
|
||||
```
|
||||
Module(
|
||||
ModModule {
|
||||
range: 0..96,
|
||||
body: [
|
||||
FunctionDef(
|
||||
StmtFunctionDef {
|
||||
range: 45..95,
|
||||
is_async: true,
|
||||
decorator_list: [],
|
||||
name: Identifier {
|
||||
id: Name("foo"),
|
||||
range: 55..58,
|
||||
},
|
||||
type_params: None,
|
||||
parameters: Parameters {
|
||||
range: 58..60,
|
||||
posonlyargs: [],
|
||||
args: [],
|
||||
vararg: None,
|
||||
kwonlyargs: [],
|
||||
kwarg: None,
|
||||
},
|
||||
returns: None,
|
||||
body: [
|
||||
FunctionDef(
|
||||
StmtFunctionDef {
|
||||
range: 66..95,
|
||||
is_async: false,
|
||||
decorator_list: [
|
||||
Decorator {
|
||||
range: 66..76,
|
||||
expression: Await(
|
||||
ExprAwait {
|
||||
range: 67..76,
|
||||
value: Name(
|
||||
ExprName {
|
||||
range: 73..76,
|
||||
id: Name("bar"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
],
|
||||
name: Identifier {
|
||||
id: Name("baz"),
|
||||
range: 85..88,
|
||||
},
|
||||
type_params: None,
|
||||
parameters: Parameters {
|
||||
range: 88..90,
|
||||
posonlyargs: [],
|
||||
args: [],
|
||||
vararg: None,
|
||||
kwonlyargs: [],
|
||||
kwarg: None,
|
||||
},
|
||||
returns: None,
|
||||
body: [
|
||||
Expr(
|
||||
StmtExpr {
|
||||
range: 92..95,
|
||||
value: EllipsisLiteral(
|
||||
ExprEllipsisLiteral {
|
||||
range: 92..95,
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
)
|
||||
```
|
||||
## Unsupported Syntax Errors
|
||||
|
||||
|
|
||||
1 | # parse_options: { "target-version": "3.8" }
|
||||
2 | async def foo():
|
||||
3 | @await bar
|
||||
| ^^^^^^^^^ Syntax Error: Cannot use `await` expression outside function call arguments in a decorator on Python 3.8 (syntax was added in Python 3.9)
|
||||
4 | def baz(): ...
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
---
|
||||
source: crates/ruff_python_parser/tests/fixtures.rs
|
||||
input_file: crates/ruff_python_parser/resources/inline/err/decorator_dict_literal_py38.py
|
||||
---
|
||||
## AST
|
||||
|
||||
```
|
||||
Module(
|
||||
ModModule {
|
||||
range: 0..68,
|
||||
body: [
|
||||
FunctionDef(
|
||||
StmtFunctionDef {
|
||||
range: 45..67,
|
||||
is_async: false,
|
||||
decorator_list: [
|
||||
Decorator {
|
||||
range: 45..52,
|
||||
expression: Dict(
|
||||
ExprDict {
|
||||
range: 46..52,
|
||||
items: [
|
||||
DictItem {
|
||||
key: Some(
|
||||
NumberLiteral(
|
||||
ExprNumberLiteral {
|
||||
range: 47..48,
|
||||
value: Int(
|
||||
3,
|
||||
),
|
||||
},
|
||||
),
|
||||
),
|
||||
value: NumberLiteral(
|
||||
ExprNumberLiteral {
|
||||
range: 50..51,
|
||||
value: Int(
|
||||
3,
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
),
|
||||
},
|
||||
],
|
||||
name: Identifier {
|
||||
id: Name("bar"),
|
||||
range: 57..60,
|
||||
},
|
||||
type_params: None,
|
||||
parameters: Parameters {
|
||||
range: 60..62,
|
||||
posonlyargs: [],
|
||||
args: [],
|
||||
vararg: None,
|
||||
kwonlyargs: [],
|
||||
kwarg: None,
|
||||
},
|
||||
returns: None,
|
||||
body: [
|
||||
Expr(
|
||||
StmtExpr {
|
||||
range: 64..67,
|
||||
value: EllipsisLiteral(
|
||||
ExprEllipsisLiteral {
|
||||
range: 64..67,
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
)
|
||||
```
|
||||
## Unsupported Syntax Errors
|
||||
|
||||
|
|
||||
1 | # parse_options: { "target-version": "3.8" }
|
||||
2 | @{3: 3}
|
||||
| ^^^^^^ Syntax Error: Cannot use a dict literal outside function call arguments in a decorator on Python 3.8 (syntax was added in Python 3.9)
|
||||
3 | def bar(): ...
|
||||
|
|
|
@ -96,6 +96,6 @@ Module(
|
|||
|
|
||||
1 | # parse_options: { "target-version": "3.8" }
|
||||
2 | @buttons[0].clicked.connect
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ Syntax Error: Unsupported expression in decorators on Python 3.8 (syntax was added in Python 3.9)
|
||||
| ^^^^^^^^^^ Syntax Error: Cannot use subscript expression outside function call arguments in a decorator on Python 3.8 (syntax was added in Python 3.9)
|
||||
3 | def spam(): ...
|
||||
|
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
---
|
||||
source: crates/ruff_python_parser/tests/fixtures.rs
|
||||
input_file: crates/ruff_python_parser/resources/inline/err/decorator_float_literal_py38.py
|
||||
---
|
||||
## AST
|
||||
|
||||
```
|
||||
Module(
|
||||
ModModule {
|
||||
range: 0..66,
|
||||
body: [
|
||||
FunctionDef(
|
||||
StmtFunctionDef {
|
||||
range: 45..65,
|
||||
is_async: false,
|
||||
decorator_list: [
|
||||
Decorator {
|
||||
range: 45..50,
|
||||
expression: NumberLiteral(
|
||||
ExprNumberLiteral {
|
||||
range: 46..50,
|
||||
value: Float(
|
||||
3.14,
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
],
|
||||
name: Identifier {
|
||||
id: Name("bar"),
|
||||
range: 55..58,
|
||||
},
|
||||
type_params: None,
|
||||
parameters: Parameters {
|
||||
range: 58..60,
|
||||
posonlyargs: [],
|
||||
args: [],
|
||||
vararg: None,
|
||||
kwonlyargs: [],
|
||||
kwarg: None,
|
||||
},
|
||||
returns: None,
|
||||
body: [
|
||||
Expr(
|
||||
StmtExpr {
|
||||
range: 62..65,
|
||||
value: EllipsisLiteral(
|
||||
ExprEllipsisLiteral {
|
||||
range: 62..65,
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
)
|
||||
```
|
||||
## Unsupported Syntax Errors
|
||||
|
||||
|
|
||||
1 | # parse_options: { "target-version": "3.8" }
|
||||
2 | @3.14
|
||||
| ^^^^ Syntax Error: Cannot use a float literal outside function call arguments in a decorator on Python 3.8 (syntax was added in Python 3.9)
|
||||
3 | def bar(): ...
|
||||
|
|
|
@ -128,6 +128,6 @@ Module(
|
|||
|
|
||||
1 | # parse_options: { "target-version": "3.7" }
|
||||
2 | @(x := lambda x: x)(foo)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ Syntax Error: Unsupported expression in decorators on Python 3.7 (syntax was added in Python 3.9)
|
||||
| ^^^^^^^^^^^^^^^^ Syntax Error: Cannot use assignment expression outside function call arguments in a decorator on Python 3.7 (syntax was added in Python 3.9)
|
||||
3 | def bar(): ...
|
||||
|
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
---
|
||||
source: crates/ruff_python_parser/tests/fixtures.rs
|
||||
input_file: crates/ruff_python_parser/resources/inline/err/decorator_non_toplevel_call_expression_py38.py
|
||||
---
|
||||
## AST
|
||||
|
||||
```
|
||||
Module(
|
||||
ModModule {
|
||||
range: 0..73,
|
||||
body: [
|
||||
FunctionDef(
|
||||
StmtFunctionDef {
|
||||
range: 45..72,
|
||||
is_async: false,
|
||||
decorator_list: [
|
||||
Decorator {
|
||||
range: 45..57,
|
||||
expression: Call(
|
||||
ExprCall {
|
||||
range: 46..57,
|
||||
func: Attribute(
|
||||
ExprAttribute {
|
||||
range: 46..55,
|
||||
value: Call(
|
||||
ExprCall {
|
||||
range: 46..51,
|
||||
func: Name(
|
||||
ExprName {
|
||||
range: 46..49,
|
||||
id: Name("foo"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
arguments: Arguments {
|
||||
range: 49..51,
|
||||
args: [],
|
||||
keywords: [],
|
||||
},
|
||||
},
|
||||
),
|
||||
attr: Identifier {
|
||||
id: Name("bar"),
|
||||
range: 52..55,
|
||||
},
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
arguments: Arguments {
|
||||
range: 55..57,
|
||||
args: [],
|
||||
keywords: [],
|
||||
},
|
||||
},
|
||||
),
|
||||
},
|
||||
],
|
||||
name: Identifier {
|
||||
id: Name("baz"),
|
||||
range: 62..65,
|
||||
},
|
||||
type_params: None,
|
||||
parameters: Parameters {
|
||||
range: 65..67,
|
||||
posonlyargs: [],
|
||||
args: [],
|
||||
vararg: None,
|
||||
kwonlyargs: [],
|
||||
kwarg: None,
|
||||
},
|
||||
returns: None,
|
||||
body: [
|
||||
Expr(
|
||||
StmtExpr {
|
||||
range: 69..72,
|
||||
value: EllipsisLiteral(
|
||||
ExprEllipsisLiteral {
|
||||
range: 69..72,
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
)
|
||||
```
|
||||
## Unsupported Syntax Errors
|
||||
|
||||
|
|
||||
1 | # parse_options: { "target-version": "3.8" }
|
||||
2 | @foo().bar()
|
||||
| ^^^^^ Syntax Error: Cannot use a call expression in a decorator on Python 3.8 unless it is the top-level expression or it occurs in the argument list of a top-level call expression (relaxed decorator syntax was added in Python 3.9)
|
||||
3 | def baz(): ...
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
---
|
||||
source: crates/ruff_python_parser/tests/fixtures.rs
|
||||
input_file: crates/ruff_python_parser/resources/inline/ok/decorator_await_expression_py39.py
|
||||
---
|
||||
## AST
|
||||
|
||||
```
|
||||
Module(
|
||||
ModModule {
|
||||
range: 0..96,
|
||||
body: [
|
||||
FunctionDef(
|
||||
StmtFunctionDef {
|
||||
range: 45..95,
|
||||
is_async: true,
|
||||
decorator_list: [],
|
||||
name: Identifier {
|
||||
id: Name("foo"),
|
||||
range: 55..58,
|
||||
},
|
||||
type_params: None,
|
||||
parameters: Parameters {
|
||||
range: 58..60,
|
||||
posonlyargs: [],
|
||||
args: [],
|
||||
vararg: None,
|
||||
kwonlyargs: [],
|
||||
kwarg: None,
|
||||
},
|
||||
returns: None,
|
||||
body: [
|
||||
FunctionDef(
|
||||
StmtFunctionDef {
|
||||
range: 66..95,
|
||||
is_async: false,
|
||||
decorator_list: [
|
||||
Decorator {
|
||||
range: 66..76,
|
||||
expression: Await(
|
||||
ExprAwait {
|
||||
range: 67..76,
|
||||
value: Name(
|
||||
ExprName {
|
||||
range: 73..76,
|
||||
id: Name("bar"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
],
|
||||
name: Identifier {
|
||||
id: Name("baz"),
|
||||
range: 85..88,
|
||||
},
|
||||
type_params: None,
|
||||
parameters: Parameters {
|
||||
range: 88..90,
|
||||
posonlyargs: [],
|
||||
args: [],
|
||||
vararg: None,
|
||||
kwonlyargs: [],
|
||||
kwarg: None,
|
||||
},
|
||||
returns: None,
|
||||
body: [
|
||||
Expr(
|
||||
StmtExpr {
|
||||
range: 92..95,
|
||||
value: EllipsisLiteral(
|
||||
ExprEllipsisLiteral {
|
||||
range: 92..95,
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
)
|
||||
```
|
Loading…
Add table
Add a link
Reference in a new issue