mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-24 19:12:44 +00:00
[syntax-errors] Check annotations in annotated assignments (#17283)
Summary -- This PR extends the checks in #17101 and #17282 to annotated assignments after Python 3.13. Currently stacked on #17282 to include `await`. Test Plan -- New inline tests. These are simpler than the other cases because there's no place to put generics.
This commit is contained in:
parent
127a45622f
commit
0891689d2f
5 changed files with 433 additions and 0 deletions
|
@ -0,0 +1,7 @@
|
||||||
|
# parse_options: {"target-version": "3.14"}
|
||||||
|
a: (x := 1)
|
||||||
|
def outer():
|
||||||
|
b: (yield 1)
|
||||||
|
c: (yield from 1)
|
||||||
|
async def outer():
|
||||||
|
d: (await 1)
|
|
@ -0,0 +1,7 @@
|
||||||
|
# parse_options: {"target-version": "3.13"}
|
||||||
|
a: (x := 1)
|
||||||
|
def outer():
|
||||||
|
b: (yield 1)
|
||||||
|
c: (yield from 1)
|
||||||
|
async def outer():
|
||||||
|
d: (await 1)
|
|
@ -119,6 +119,32 @@ impl SemanticSyntaxChecker {
|
||||||
|
|
||||||
fn check_annotation<Ctx: SemanticSyntaxContext>(stmt: &ast::Stmt, ctx: &Ctx) {
|
fn check_annotation<Ctx: SemanticSyntaxContext>(stmt: &ast::Stmt, ctx: &Ctx) {
|
||||||
match stmt {
|
match stmt {
|
||||||
|
Stmt::AnnAssign(ast::StmtAnnAssign { annotation, .. }) => {
|
||||||
|
if ctx.python_version() > PythonVersion::PY313 {
|
||||||
|
// test_ok valid_annotation_py313
|
||||||
|
// # parse_options: {"target-version": "3.13"}
|
||||||
|
// a: (x := 1)
|
||||||
|
// def outer():
|
||||||
|
// b: (yield 1)
|
||||||
|
// c: (yield from 1)
|
||||||
|
// async def outer():
|
||||||
|
// d: (await 1)
|
||||||
|
|
||||||
|
// test_err invalid_annotation_py314
|
||||||
|
// # parse_options: {"target-version": "3.14"}
|
||||||
|
// a: (x := 1)
|
||||||
|
// def outer():
|
||||||
|
// b: (yield 1)
|
||||||
|
// c: (yield from 1)
|
||||||
|
// async def outer():
|
||||||
|
// d: (await 1)
|
||||||
|
let mut visitor = InvalidExpressionVisitor {
|
||||||
|
position: InvalidExpressionPosition::TypeAnnotation,
|
||||||
|
ctx,
|
||||||
|
};
|
||||||
|
visitor.visit_expr(annotation);
|
||||||
|
}
|
||||||
|
}
|
||||||
Stmt::FunctionDef(ast::StmtFunctionDef {
|
Stmt::FunctionDef(ast::StmtFunctionDef {
|
||||||
type_params,
|
type_params,
|
||||||
parameters,
|
parameters,
|
||||||
|
|
|
@ -0,0 +1,215 @@
|
||||||
|
---
|
||||||
|
source: crates/ruff_python_parser/tests/fixtures.rs
|
||||||
|
input_file: crates/ruff_python_parser/resources/inline/err/invalid_annotation_py314.py
|
||||||
|
---
|
||||||
|
## AST
|
||||||
|
|
||||||
|
```
|
||||||
|
Module(
|
||||||
|
ModModule {
|
||||||
|
range: 0..144,
|
||||||
|
body: [
|
||||||
|
AnnAssign(
|
||||||
|
StmtAnnAssign {
|
||||||
|
range: 44..55,
|
||||||
|
target: Name(
|
||||||
|
ExprName {
|
||||||
|
range: 44..45,
|
||||||
|
id: Name("a"),
|
||||||
|
ctx: Store,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
annotation: Named(
|
||||||
|
ExprNamed {
|
||||||
|
range: 48..54,
|
||||||
|
target: Name(
|
||||||
|
ExprName {
|
||||||
|
range: 48..49,
|
||||||
|
id: Name("x"),
|
||||||
|
ctx: Store,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
value: NumberLiteral(
|
||||||
|
ExprNumberLiteral {
|
||||||
|
range: 53..54,
|
||||||
|
value: Int(
|
||||||
|
1,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
value: None,
|
||||||
|
simple: true,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
FunctionDef(
|
||||||
|
StmtFunctionDef {
|
||||||
|
range: 56..107,
|
||||||
|
is_async: false,
|
||||||
|
decorator_list: [],
|
||||||
|
name: Identifier {
|
||||||
|
id: Name("outer"),
|
||||||
|
range: 60..65,
|
||||||
|
},
|
||||||
|
type_params: None,
|
||||||
|
parameters: Parameters {
|
||||||
|
range: 65..67,
|
||||||
|
posonlyargs: [],
|
||||||
|
args: [],
|
||||||
|
vararg: None,
|
||||||
|
kwonlyargs: [],
|
||||||
|
kwarg: None,
|
||||||
|
},
|
||||||
|
returns: None,
|
||||||
|
body: [
|
||||||
|
AnnAssign(
|
||||||
|
StmtAnnAssign {
|
||||||
|
range: 73..85,
|
||||||
|
target: Name(
|
||||||
|
ExprName {
|
||||||
|
range: 73..74,
|
||||||
|
id: Name("b"),
|
||||||
|
ctx: Store,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
annotation: Yield(
|
||||||
|
ExprYield {
|
||||||
|
range: 77..84,
|
||||||
|
value: Some(
|
||||||
|
NumberLiteral(
|
||||||
|
ExprNumberLiteral {
|
||||||
|
range: 83..84,
|
||||||
|
value: Int(
|
||||||
|
1,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
value: None,
|
||||||
|
simple: true,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
AnnAssign(
|
||||||
|
StmtAnnAssign {
|
||||||
|
range: 90..107,
|
||||||
|
target: Name(
|
||||||
|
ExprName {
|
||||||
|
range: 90..91,
|
||||||
|
id: Name("c"),
|
||||||
|
ctx: Store,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
annotation: YieldFrom(
|
||||||
|
ExprYieldFrom {
|
||||||
|
range: 94..106,
|
||||||
|
value: NumberLiteral(
|
||||||
|
ExprNumberLiteral {
|
||||||
|
range: 105..106,
|
||||||
|
value: Int(
|
||||||
|
1,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
value: None,
|
||||||
|
simple: true,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
FunctionDef(
|
||||||
|
StmtFunctionDef {
|
||||||
|
range: 108..143,
|
||||||
|
is_async: true,
|
||||||
|
decorator_list: [],
|
||||||
|
name: Identifier {
|
||||||
|
id: Name("outer"),
|
||||||
|
range: 118..123,
|
||||||
|
},
|
||||||
|
type_params: None,
|
||||||
|
parameters: Parameters {
|
||||||
|
range: 123..125,
|
||||||
|
posonlyargs: [],
|
||||||
|
args: [],
|
||||||
|
vararg: None,
|
||||||
|
kwonlyargs: [],
|
||||||
|
kwarg: None,
|
||||||
|
},
|
||||||
|
returns: None,
|
||||||
|
body: [
|
||||||
|
AnnAssign(
|
||||||
|
StmtAnnAssign {
|
||||||
|
range: 131..143,
|
||||||
|
target: Name(
|
||||||
|
ExprName {
|
||||||
|
range: 131..132,
|
||||||
|
id: Name("d"),
|
||||||
|
ctx: Store,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
annotation: Await(
|
||||||
|
ExprAwait {
|
||||||
|
range: 135..142,
|
||||||
|
value: NumberLiteral(
|
||||||
|
ExprNumberLiteral {
|
||||||
|
range: 141..142,
|
||||||
|
value: Int(
|
||||||
|
1,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
value: None,
|
||||||
|
simple: true,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
)
|
||||||
|
```
|
||||||
|
## Semantic Syntax Errors
|
||||||
|
|
||||||
|
|
|
||||||
|
1 | # parse_options: {"target-version": "3.14"}
|
||||||
|
2 | a: (x := 1)
|
||||||
|
| ^^^^^^ Syntax Error: named expression cannot be used within a type annotation
|
||||||
|
3 | def outer():
|
||||||
|
4 | b: (yield 1)
|
||||||
|
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
2 | a: (x := 1)
|
||||||
|
3 | def outer():
|
||||||
|
4 | b: (yield 1)
|
||||||
|
| ^^^^^^^ Syntax Error: yield expression cannot be used within a type annotation
|
||||||
|
5 | c: (yield from 1)
|
||||||
|
6 | async def outer():
|
||||||
|
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
3 | def outer():
|
||||||
|
4 | b: (yield 1)
|
||||||
|
5 | c: (yield from 1)
|
||||||
|
| ^^^^^^^^^^^^ Syntax Error: yield expression cannot be used within a type annotation
|
||||||
|
6 | async def outer():
|
||||||
|
7 | d: (await 1)
|
||||||
|
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
5 | c: (yield from 1)
|
||||||
|
6 | async def outer():
|
||||||
|
7 | d: (await 1)
|
||||||
|
| ^^^^^^^ Syntax Error: await expression cannot be used within a type annotation
|
||||||
|
|
|
|
@ -0,0 +1,178 @@
|
||||||
|
---
|
||||||
|
source: crates/ruff_python_parser/tests/fixtures.rs
|
||||||
|
input_file: crates/ruff_python_parser/resources/inline/ok/valid_annotation_py313.py
|
||||||
|
---
|
||||||
|
## AST
|
||||||
|
|
||||||
|
```
|
||||||
|
Module(
|
||||||
|
ModModule {
|
||||||
|
range: 0..144,
|
||||||
|
body: [
|
||||||
|
AnnAssign(
|
||||||
|
StmtAnnAssign {
|
||||||
|
range: 44..55,
|
||||||
|
target: Name(
|
||||||
|
ExprName {
|
||||||
|
range: 44..45,
|
||||||
|
id: Name("a"),
|
||||||
|
ctx: Store,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
annotation: Named(
|
||||||
|
ExprNamed {
|
||||||
|
range: 48..54,
|
||||||
|
target: Name(
|
||||||
|
ExprName {
|
||||||
|
range: 48..49,
|
||||||
|
id: Name("x"),
|
||||||
|
ctx: Store,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
value: NumberLiteral(
|
||||||
|
ExprNumberLiteral {
|
||||||
|
range: 53..54,
|
||||||
|
value: Int(
|
||||||
|
1,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
value: None,
|
||||||
|
simple: true,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
FunctionDef(
|
||||||
|
StmtFunctionDef {
|
||||||
|
range: 56..107,
|
||||||
|
is_async: false,
|
||||||
|
decorator_list: [],
|
||||||
|
name: Identifier {
|
||||||
|
id: Name("outer"),
|
||||||
|
range: 60..65,
|
||||||
|
},
|
||||||
|
type_params: None,
|
||||||
|
parameters: Parameters {
|
||||||
|
range: 65..67,
|
||||||
|
posonlyargs: [],
|
||||||
|
args: [],
|
||||||
|
vararg: None,
|
||||||
|
kwonlyargs: [],
|
||||||
|
kwarg: None,
|
||||||
|
},
|
||||||
|
returns: None,
|
||||||
|
body: [
|
||||||
|
AnnAssign(
|
||||||
|
StmtAnnAssign {
|
||||||
|
range: 73..85,
|
||||||
|
target: Name(
|
||||||
|
ExprName {
|
||||||
|
range: 73..74,
|
||||||
|
id: Name("b"),
|
||||||
|
ctx: Store,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
annotation: Yield(
|
||||||
|
ExprYield {
|
||||||
|
range: 77..84,
|
||||||
|
value: Some(
|
||||||
|
NumberLiteral(
|
||||||
|
ExprNumberLiteral {
|
||||||
|
range: 83..84,
|
||||||
|
value: Int(
|
||||||
|
1,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
value: None,
|
||||||
|
simple: true,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
AnnAssign(
|
||||||
|
StmtAnnAssign {
|
||||||
|
range: 90..107,
|
||||||
|
target: Name(
|
||||||
|
ExprName {
|
||||||
|
range: 90..91,
|
||||||
|
id: Name("c"),
|
||||||
|
ctx: Store,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
annotation: YieldFrom(
|
||||||
|
ExprYieldFrom {
|
||||||
|
range: 94..106,
|
||||||
|
value: NumberLiteral(
|
||||||
|
ExprNumberLiteral {
|
||||||
|
range: 105..106,
|
||||||
|
value: Int(
|
||||||
|
1,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
value: None,
|
||||||
|
simple: true,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
FunctionDef(
|
||||||
|
StmtFunctionDef {
|
||||||
|
range: 108..143,
|
||||||
|
is_async: true,
|
||||||
|
decorator_list: [],
|
||||||
|
name: Identifier {
|
||||||
|
id: Name("outer"),
|
||||||
|
range: 118..123,
|
||||||
|
},
|
||||||
|
type_params: None,
|
||||||
|
parameters: Parameters {
|
||||||
|
range: 123..125,
|
||||||
|
posonlyargs: [],
|
||||||
|
args: [],
|
||||||
|
vararg: None,
|
||||||
|
kwonlyargs: [],
|
||||||
|
kwarg: None,
|
||||||
|
},
|
||||||
|
returns: None,
|
||||||
|
body: [
|
||||||
|
AnnAssign(
|
||||||
|
StmtAnnAssign {
|
||||||
|
range: 131..143,
|
||||||
|
target: Name(
|
||||||
|
ExprName {
|
||||||
|
range: 131..132,
|
||||||
|
id: Name("d"),
|
||||||
|
ctx: Store,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
annotation: Await(
|
||||||
|
ExprAwait {
|
||||||
|
range: 135..142,
|
||||||
|
value: NumberLiteral(
|
||||||
|
ExprNumberLiteral {
|
||||||
|
range: 141..142,
|
||||||
|
value: Int(
|
||||||
|
1,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
value: None,
|
||||||
|
simple: true,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
)
|
||||||
|
```
|
Loading…
Add table
Add a link
Reference in a new issue