mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-28 21:05:08 +00:00
Reject more syntactically invalid Python programs (#8524)
## Summary This commit adds some additional error checking to the parser such that assignments that are invalid syntax are rejected. This covers the obvious cases like `5 = 3` and some not so obvious cases like `x + y = 42`. This does add an additional recursive call to the parser for the cases handling assignments. I had initially been concerned about doing this, but `set_context` is already doing recursion during assignments, so I didn't feel as though this was changing any fundamental performance characteristics of the parser. (Also, in practice, I would expect any such recursion here to be quite shallow since the recursion is done on the target of an assignment. Such things are rarely nested much in practice.) Fixes #6895 ## Test Plan I've added unit tests covering every case that is detected as invalid on an `Expr`.
This commit is contained in:
parent
c3d6d5d006
commit
6a1fa4778f
20 changed files with 1432 additions and 148 deletions
|
@ -0,0 +1,33 @@
|
|||
---
|
||||
source: crates/ruff_python_parser/src/invalid.rs
|
||||
expression: ast
|
||||
---
|
||||
Ok(
|
||||
[
|
||||
Expr(
|
||||
StmtExpr {
|
||||
range: 0..8,
|
||||
value: NamedExpr(
|
||||
ExprNamedExpr {
|
||||
range: 1..7,
|
||||
target: Name(
|
||||
ExprName {
|
||||
range: 1..2,
|
||||
id: "x",
|
||||
ctx: Store,
|
||||
},
|
||||
),
|
||||
value: NumberLiteral(
|
||||
ExprNumberLiteral {
|
||||
range: 6..7,
|
||||
value: Int(
|
||||
5,
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
)
|
|
@ -0,0 +1,40 @@
|
|||
---
|
||||
source: crates/ruff_python_parser/src/invalid.rs
|
||||
expression: ast
|
||||
---
|
||||
Ok(
|
||||
[
|
||||
Assign(
|
||||
StmtAssign {
|
||||
range: 0..12,
|
||||
targets: [
|
||||
Attribute(
|
||||
ExprAttribute {
|
||||
range: 0..7,
|
||||
value: Name(
|
||||
ExprName {
|
||||
range: 0..3,
|
||||
id: "foo",
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
attr: Identifier {
|
||||
id: "bar",
|
||||
range: 4..7,
|
||||
},
|
||||
ctx: Store,
|
||||
},
|
||||
),
|
||||
],
|
||||
value: NumberLiteral(
|
||||
ExprNumberLiteral {
|
||||
range: 10..12,
|
||||
value: Int(
|
||||
42,
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
)
|
|
@ -0,0 +1,41 @@
|
|||
---
|
||||
source: crates/ruff_python_parser/src/invalid.rs
|
||||
expression: ast
|
||||
---
|
||||
Ok(
|
||||
[
|
||||
Assign(
|
||||
StmtAssign {
|
||||
range: 0..12,
|
||||
targets: [
|
||||
Attribute(
|
||||
ExprAttribute {
|
||||
range: 0..7,
|
||||
value: StringLiteral(
|
||||
ExprStringLiteral {
|
||||
range: 0..5,
|
||||
value: "foo",
|
||||
unicode: false,
|
||||
implicit_concatenated: false,
|
||||
},
|
||||
),
|
||||
attr: Identifier {
|
||||
id: "y",
|
||||
range: 6..7,
|
||||
},
|
||||
ctx: Store,
|
||||
},
|
||||
),
|
||||
],
|
||||
value: NumberLiteral(
|
||||
ExprNumberLiteral {
|
||||
range: 10..12,
|
||||
value: Int(
|
||||
42,
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
)
|
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
source: crates/ruff_python_parser/src/invalid.rs
|
||||
expression: ast
|
||||
---
|
||||
Ok(
|
||||
Module(
|
||||
ModModule {
|
||||
range: 0..9,
|
||||
body: [
|
||||
IpyEscapeCommand(
|
||||
StmtIpyEscapeCommand {
|
||||
range: 0..9,
|
||||
kind: Shell,
|
||||
value: "foo = 42",
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
)
|
|
@ -0,0 +1,76 @@
|
|||
---
|
||||
source: crates/ruff_python_parser/src/invalid.rs
|
||||
expression: ast
|
||||
---
|
||||
Ok(
|
||||
[
|
||||
Assign(
|
||||
StmtAssign {
|
||||
range: 0..21,
|
||||
targets: [
|
||||
List(
|
||||
ExprList {
|
||||
range: 0..9,
|
||||
elts: [
|
||||
Name(
|
||||
ExprName {
|
||||
range: 1..2,
|
||||
id: "x",
|
||||
ctx: Store,
|
||||
},
|
||||
),
|
||||
Name(
|
||||
ExprName {
|
||||
range: 4..5,
|
||||
id: "y",
|
||||
ctx: Store,
|
||||
},
|
||||
),
|
||||
Name(
|
||||
ExprName {
|
||||
range: 7..8,
|
||||
id: "z",
|
||||
ctx: Store,
|
||||
},
|
||||
),
|
||||
],
|
||||
ctx: Store,
|
||||
},
|
||||
),
|
||||
],
|
||||
value: List(
|
||||
ExprList {
|
||||
range: 12..21,
|
||||
elts: [
|
||||
NumberLiteral(
|
||||
ExprNumberLiteral {
|
||||
range: 13..14,
|
||||
value: Int(
|
||||
1,
|
||||
),
|
||||
},
|
||||
),
|
||||
NumberLiteral(
|
||||
ExprNumberLiteral {
|
||||
range: 16..17,
|
||||
value: Int(
|
||||
2,
|
||||
),
|
||||
},
|
||||
),
|
||||
NumberLiteral(
|
||||
ExprNumberLiteral {
|
||||
range: 19..20,
|
||||
value: Int(
|
||||
3,
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
)
|
|
@ -0,0 +1,30 @@
|
|||
---
|
||||
source: crates/ruff_python_parser/src/invalid.rs
|
||||
expression: ast
|
||||
---
|
||||
Ok(
|
||||
[
|
||||
Assign(
|
||||
StmtAssign {
|
||||
range: 0..8,
|
||||
targets: [
|
||||
Name(
|
||||
ExprName {
|
||||
range: 0..3,
|
||||
id: "foo",
|
||||
ctx: Store,
|
||||
},
|
||||
),
|
||||
],
|
||||
value: NumberLiteral(
|
||||
ExprNumberLiteral {
|
||||
range: 6..8,
|
||||
value: Int(
|
||||
42,
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
)
|
|
@ -0,0 +1,70 @@
|
|||
---
|
||||
source: crates/ruff_python_parser/src/invalid.rs
|
||||
expression: ast
|
||||
---
|
||||
Ok(
|
||||
[
|
||||
Assign(
|
||||
StmtAssign {
|
||||
range: 0..13,
|
||||
targets: [
|
||||
Subscript(
|
||||
ExprSubscript {
|
||||
range: 0..6,
|
||||
value: Name(
|
||||
ExprName {
|
||||
range: 0..1,
|
||||
id: "x",
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
slice: Slice(
|
||||
ExprSlice {
|
||||
range: 2..5,
|
||||
lower: Some(
|
||||
NumberLiteral(
|
||||
ExprNumberLiteral {
|
||||
range: 2..3,
|
||||
value: Int(
|
||||
1,
|
||||
),
|
||||
},
|
||||
),
|
||||
),
|
||||
upper: Some(
|
||||
NumberLiteral(
|
||||
ExprNumberLiteral {
|
||||
range: 4..5,
|
||||
value: Int(
|
||||
2,
|
||||
),
|
||||
},
|
||||
),
|
||||
),
|
||||
step: None,
|
||||
},
|
||||
),
|
||||
ctx: Store,
|
||||
},
|
||||
),
|
||||
],
|
||||
value: List(
|
||||
ExprList {
|
||||
range: 9..13,
|
||||
elts: [
|
||||
NumberLiteral(
|
||||
ExprNumberLiteral {
|
||||
range: 10..12,
|
||||
value: Int(
|
||||
42,
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
)
|
|
@ -0,0 +1,71 @@
|
|||
---
|
||||
source: crates/ruff_python_parser/src/invalid.rs
|
||||
expression: ast
|
||||
---
|
||||
Ok(
|
||||
[
|
||||
Assign(
|
||||
StmtAssign {
|
||||
range: 0..13,
|
||||
targets: [
|
||||
Subscript(
|
||||
ExprSubscript {
|
||||
range: 0..6,
|
||||
value: NumberLiteral(
|
||||
ExprNumberLiteral {
|
||||
range: 0..1,
|
||||
value: Int(
|
||||
5,
|
||||
),
|
||||
},
|
||||
),
|
||||
slice: Slice(
|
||||
ExprSlice {
|
||||
range: 2..5,
|
||||
lower: Some(
|
||||
NumberLiteral(
|
||||
ExprNumberLiteral {
|
||||
range: 2..3,
|
||||
value: Int(
|
||||
1,
|
||||
),
|
||||
},
|
||||
),
|
||||
),
|
||||
upper: Some(
|
||||
NumberLiteral(
|
||||
ExprNumberLiteral {
|
||||
range: 4..5,
|
||||
value: Int(
|
||||
2,
|
||||
),
|
||||
},
|
||||
),
|
||||
),
|
||||
step: None,
|
||||
},
|
||||
),
|
||||
ctx: Store,
|
||||
},
|
||||
),
|
||||
],
|
||||
value: List(
|
||||
ExprList {
|
||||
range: 9..13,
|
||||
elts: [
|
||||
NumberLiteral(
|
||||
ExprNumberLiteral {
|
||||
range: 10..12,
|
||||
value: Int(
|
||||
42,
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
)
|
|
@ -0,0 +1,36 @@
|
|||
---
|
||||
source: crates/ruff_python_parser/src/invalid.rs
|
||||
expression: ast
|
||||
---
|
||||
Ok(
|
||||
[
|
||||
Assign(
|
||||
StmtAssign {
|
||||
range: 0..9,
|
||||
targets: [
|
||||
Starred(
|
||||
ExprStarred {
|
||||
range: 0..4,
|
||||
value: Name(
|
||||
ExprName {
|
||||
range: 1..4,
|
||||
id: "foo",
|
||||
ctx: Store,
|
||||
},
|
||||
),
|
||||
ctx: Store,
|
||||
},
|
||||
),
|
||||
],
|
||||
value: NumberLiteral(
|
||||
ExprNumberLiteral {
|
||||
range: 7..9,
|
||||
value: Int(
|
||||
42,
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
)
|
|
@ -0,0 +1,44 @@
|
|||
---
|
||||
source: crates/ruff_python_parser/src/invalid.rs
|
||||
expression: ast
|
||||
---
|
||||
Ok(
|
||||
[
|
||||
Assign(
|
||||
StmtAssign {
|
||||
range: 0..9,
|
||||
targets: [
|
||||
Subscript(
|
||||
ExprSubscript {
|
||||
range: 0..4,
|
||||
value: Name(
|
||||
ExprName {
|
||||
range: 0..1,
|
||||
id: "x",
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
slice: NumberLiteral(
|
||||
ExprNumberLiteral {
|
||||
range: 2..3,
|
||||
value: Int(
|
||||
0,
|
||||
),
|
||||
},
|
||||
),
|
||||
ctx: Store,
|
||||
},
|
||||
),
|
||||
],
|
||||
value: NumberLiteral(
|
||||
ExprNumberLiteral {
|
||||
range: 7..9,
|
||||
value: Int(
|
||||
42,
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
)
|
|
@ -0,0 +1,45 @@
|
|||
---
|
||||
source: crates/ruff_python_parser/src/invalid.rs
|
||||
expression: ast
|
||||
---
|
||||
Ok(
|
||||
[
|
||||
Assign(
|
||||
StmtAssign {
|
||||
range: 0..9,
|
||||
targets: [
|
||||
Subscript(
|
||||
ExprSubscript {
|
||||
range: 0..4,
|
||||
value: NumberLiteral(
|
||||
ExprNumberLiteral {
|
||||
range: 0..1,
|
||||
value: Int(
|
||||
5,
|
||||
),
|
||||
},
|
||||
),
|
||||
slice: NumberLiteral(
|
||||
ExprNumberLiteral {
|
||||
range: 2..3,
|
||||
value: Int(
|
||||
0,
|
||||
),
|
||||
},
|
||||
),
|
||||
ctx: Store,
|
||||
},
|
||||
),
|
||||
],
|
||||
value: NumberLiteral(
|
||||
ExprNumberLiteral {
|
||||
range: 7..9,
|
||||
value: Int(
|
||||
42,
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
)
|
|
@ -0,0 +1,76 @@
|
|||
---
|
||||
source: crates/ruff_python_parser/src/invalid.rs
|
||||
expression: ast
|
||||
---
|
||||
Ok(
|
||||
[
|
||||
Assign(
|
||||
StmtAssign {
|
||||
range: 0..21,
|
||||
targets: [
|
||||
Tuple(
|
||||
ExprTuple {
|
||||
range: 0..9,
|
||||
elts: [
|
||||
Name(
|
||||
ExprName {
|
||||
range: 1..2,
|
||||
id: "x",
|
||||
ctx: Store,
|
||||
},
|
||||
),
|
||||
Name(
|
||||
ExprName {
|
||||
range: 4..5,
|
||||
id: "y",
|
||||
ctx: Store,
|
||||
},
|
||||
),
|
||||
Name(
|
||||
ExprName {
|
||||
range: 7..8,
|
||||
id: "z",
|
||||
ctx: Store,
|
||||
},
|
||||
),
|
||||
],
|
||||
ctx: Store,
|
||||
},
|
||||
),
|
||||
],
|
||||
value: Tuple(
|
||||
ExprTuple {
|
||||
range: 12..21,
|
||||
elts: [
|
||||
NumberLiteral(
|
||||
ExprNumberLiteral {
|
||||
range: 13..14,
|
||||
value: Int(
|
||||
1,
|
||||
),
|
||||
},
|
||||
),
|
||||
NumberLiteral(
|
||||
ExprNumberLiteral {
|
||||
range: 16..17,
|
||||
value: Int(
|
||||
2,
|
||||
),
|
||||
},
|
||||
),
|
||||
NumberLiteral(
|
||||
ExprNumberLiteral {
|
||||
range: 19..20,
|
||||
value: Int(
|
||||
3,
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
)
|
Loading…
Add table
Add a link
Reference in a new issue