mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-26 20:10:09 +00:00
[syntax-errors] nonlocal
declaration at module level (#17559)
## Summary Part of #17412 Add a new compile-time syntax error for detecting `nonlocal` declarations at a module level. ## Test Plan - Added new inline tests for the syntax error - Updated existing tests for `nonlocal` statement parsing to be inside a function scope Co-authored-by: Brent Westbrook <36778786+ntBre@users.noreply.github.com>
This commit is contained in:
parent
538393d1f3
commit
cf59cee928
16 changed files with 363 additions and 131 deletions
|
@ -616,7 +616,8 @@ impl SemanticSyntaxContext for Checker<'_> {
|
||||||
| SemanticSyntaxErrorKind::DuplicateMatchClassAttribute(_)
|
| SemanticSyntaxErrorKind::DuplicateMatchClassAttribute(_)
|
||||||
| SemanticSyntaxErrorKind::InvalidStarExpression
|
| SemanticSyntaxErrorKind::InvalidStarExpression
|
||||||
| SemanticSyntaxErrorKind::AsyncComprehensionInSyncComprehension(_)
|
| SemanticSyntaxErrorKind::AsyncComprehensionInSyncComprehension(_)
|
||||||
| SemanticSyntaxErrorKind::DuplicateParameter(_) => {
|
| SemanticSyntaxErrorKind::DuplicateParameter(_)
|
||||||
|
| SemanticSyntaxErrorKind::NonlocalDeclarationAtModuleLevel => {
|
||||||
if self.settings.preview.is_enabled() {
|
if self.settings.preview.is_enabled() {
|
||||||
self.semantic_errors.borrow_mut().push(error);
|
self.semantic_errors.borrow_mut().push(error);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
nonlocal x
|
||||||
|
nonlocal x, y
|
|
@ -1 +1,2 @@
|
||||||
nonlocal
|
def _():
|
||||||
|
nonlocal
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
nonlocal x + 1
|
def _():
|
||||||
|
nonlocal x + 1
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
nonlocal ,
|
def _():
|
||||||
nonlocal x,
|
nonlocal ,
|
||||||
nonlocal x, y,
|
nonlocal x,
|
||||||
|
nonlocal x, y,
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
def _():
|
||||||
|
nonlocal x
|
|
@ -1,2 +1,3 @@
|
||||||
nonlocal x
|
def _():
|
||||||
nonlocal x, y, z
|
nonlocal x
|
||||||
|
nonlocal x, y, z
|
||||||
|
|
|
@ -897,11 +897,13 @@ impl<'src> Parser<'src> {
|
||||||
self.bump(TokenKind::Nonlocal);
|
self.bump(TokenKind::Nonlocal);
|
||||||
|
|
||||||
// test_err nonlocal_stmt_trailing_comma
|
// test_err nonlocal_stmt_trailing_comma
|
||||||
|
// def _():
|
||||||
// nonlocal ,
|
// nonlocal ,
|
||||||
// nonlocal x,
|
// nonlocal x,
|
||||||
// nonlocal x, y,
|
// nonlocal x, y,
|
||||||
|
|
||||||
// test_err nonlocal_stmt_expression
|
// test_err nonlocal_stmt_expression
|
||||||
|
// def _():
|
||||||
// nonlocal x + 1
|
// nonlocal x + 1
|
||||||
let names = self.parse_comma_separated_list_into_vec(
|
let names = self.parse_comma_separated_list_into_vec(
|
||||||
RecoveryContextKind::Identifiers,
|
RecoveryContextKind::Identifiers,
|
||||||
|
@ -910,6 +912,7 @@ impl<'src> Parser<'src> {
|
||||||
|
|
||||||
if names.is_empty() {
|
if names.is_empty() {
|
||||||
// test_err nonlocal_stmt_empty
|
// test_err nonlocal_stmt_empty
|
||||||
|
// def _():
|
||||||
// nonlocal
|
// nonlocal
|
||||||
self.add_error(
|
self.add_error(
|
||||||
ParseErrorType::EmptyNonlocalNames,
|
ParseErrorType::EmptyNonlocalNames,
|
||||||
|
@ -918,6 +921,7 @@ impl<'src> Parser<'src> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// test_ok nonlocal_stmt
|
// test_ok nonlocal_stmt
|
||||||
|
// def _():
|
||||||
// nonlocal x
|
// nonlocal x
|
||||||
// nonlocal x, y, z
|
// nonlocal x, y, z
|
||||||
ast::StmtNonlocal {
|
ast::StmtNonlocal {
|
||||||
|
|
|
@ -142,6 +142,22 @@ impl SemanticSyntaxChecker {
|
||||||
AwaitOutsideAsyncFunctionKind::AsyncWith,
|
AwaitOutsideAsyncFunctionKind::AsyncWith,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Stmt::Nonlocal(ast::StmtNonlocal { range, .. }) => {
|
||||||
|
// test_ok nonlocal_declaration_at_module_level
|
||||||
|
// def _():
|
||||||
|
// nonlocal x
|
||||||
|
|
||||||
|
// test_err nonlocal_declaration_at_module_level
|
||||||
|
// nonlocal x
|
||||||
|
// nonlocal x, y
|
||||||
|
if ctx.in_module_scope() {
|
||||||
|
Self::add_error(
|
||||||
|
ctx,
|
||||||
|
SemanticSyntaxErrorKind::NonlocalDeclarationAtModuleLevel,
|
||||||
|
*range,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -933,6 +949,9 @@ impl Display for SemanticSyntaxError {
|
||||||
SemanticSyntaxErrorKind::DuplicateParameter(name) => {
|
SemanticSyntaxErrorKind::DuplicateParameter(name) => {
|
||||||
write!(f, r#"Duplicate parameter "{name}""#)
|
write!(f, r#"Duplicate parameter "{name}""#)
|
||||||
}
|
}
|
||||||
|
SemanticSyntaxErrorKind::NonlocalDeclarationAtModuleLevel => {
|
||||||
|
write!(f, "nonlocal declaration not allowed at module level")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1254,6 +1273,9 @@ pub enum SemanticSyntaxErrorKind {
|
||||||
/// lambda x, x: ...
|
/// lambda x, x: ...
|
||||||
/// ```
|
/// ```
|
||||||
DuplicateParameter(String),
|
DuplicateParameter(String),
|
||||||
|
|
||||||
|
/// Represents a nonlocal declaration at module level
|
||||||
|
NonlocalDeclarationAtModuleLevel,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
|
|
@ -538,7 +538,7 @@ impl SemanticSyntaxContext for SemanticSyntaxCheckerVisitor<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn in_module_scope(&self) -> bool {
|
fn in_module_scope(&self) -> bool {
|
||||||
true
|
self.scopes.len() == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
fn in_function_scope(&self) -> bool {
|
fn in_function_scope(&self) -> bool {
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
---
|
||||||
|
source: crates/ruff_python_parser/tests/fixtures.rs
|
||||||
|
input_file: crates/ruff_python_parser/resources/inline/err/nonlocal_declaration_at_module_level.py
|
||||||
|
---
|
||||||
|
## AST
|
||||||
|
|
||||||
|
```
|
||||||
|
Module(
|
||||||
|
ModModule {
|
||||||
|
range: 0..25,
|
||||||
|
body: [
|
||||||
|
Nonlocal(
|
||||||
|
StmtNonlocal {
|
||||||
|
range: 0..10,
|
||||||
|
names: [
|
||||||
|
Identifier {
|
||||||
|
id: Name("x"),
|
||||||
|
range: 9..10,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Nonlocal(
|
||||||
|
StmtNonlocal {
|
||||||
|
range: 11..24,
|
||||||
|
names: [
|
||||||
|
Identifier {
|
||||||
|
id: Name("x"),
|
||||||
|
range: 20..21,
|
||||||
|
},
|
||||||
|
Identifier {
|
||||||
|
id: Name("y"),
|
||||||
|
range: 23..24,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
)
|
||||||
|
```
|
||||||
|
## Semantic Syntax Errors
|
||||||
|
|
||||||
|
|
|
||||||
|
1 | nonlocal x
|
||||||
|
| ^^^^^^^^^^ Syntax Error: nonlocal declaration not allowed at module level
|
||||||
|
2 | nonlocal x, y
|
||||||
|
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
1 | nonlocal x
|
||||||
|
2 | nonlocal x, y
|
||||||
|
| ^^^^^^^^^^^^^ Syntax Error: nonlocal declaration not allowed at module level
|
||||||
|
|
|
|
@ -1,28 +1,51 @@
|
||||||
---
|
---
|
||||||
source: crates/ruff_python_parser/tests/fixtures.rs
|
source: crates/ruff_python_parser/tests/fixtures.rs
|
||||||
input_file: crates/ruff_python_parser/resources/inline/err/nonlocal_stmt_empty.py
|
input_file: crates/ruff_python_parser/resources/inline/err/nonlocal_stmt_empty.py
|
||||||
snapshot_kind: text
|
|
||||||
---
|
---
|
||||||
## AST
|
## AST
|
||||||
|
|
||||||
```
|
```
|
||||||
Module(
|
Module(
|
||||||
ModModule {
|
ModModule {
|
||||||
range: 0..9,
|
range: 0..22,
|
||||||
|
body: [
|
||||||
|
FunctionDef(
|
||||||
|
StmtFunctionDef {
|
||||||
|
range: 0..21,
|
||||||
|
is_async: false,
|
||||||
|
decorator_list: [],
|
||||||
|
name: Identifier {
|
||||||
|
id: Name("_"),
|
||||||
|
range: 4..5,
|
||||||
|
},
|
||||||
|
type_params: None,
|
||||||
|
parameters: Parameters {
|
||||||
|
range: 5..7,
|
||||||
|
posonlyargs: [],
|
||||||
|
args: [],
|
||||||
|
vararg: None,
|
||||||
|
kwonlyargs: [],
|
||||||
|
kwarg: None,
|
||||||
|
},
|
||||||
|
returns: None,
|
||||||
body: [
|
body: [
|
||||||
Nonlocal(
|
Nonlocal(
|
||||||
StmtNonlocal {
|
StmtNonlocal {
|
||||||
range: 0..8,
|
range: 13..21,
|
||||||
names: [],
|
names: [],
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
## Errors
|
## Errors
|
||||||
|
|
||||||
|
|
|
|
||||||
1 | nonlocal
|
1 | def _():
|
||||||
|
2 | nonlocal
|
||||||
| ^ Syntax Error: Nonlocal statement must have at least one name
|
| ^ Syntax Error: Nonlocal statement must have at least one name
|
||||||
|
|
|
|
||||||
|
|
|
@ -1,36 +1,55 @@
|
||||||
---
|
---
|
||||||
source: crates/ruff_python_parser/tests/fixtures.rs
|
source: crates/ruff_python_parser/tests/fixtures.rs
|
||||||
input_file: crates/ruff_python_parser/resources/inline/err/nonlocal_stmt_expression.py
|
input_file: crates/ruff_python_parser/resources/inline/err/nonlocal_stmt_expression.py
|
||||||
snapshot_kind: text
|
|
||||||
---
|
---
|
||||||
## AST
|
## AST
|
||||||
|
|
||||||
```
|
```
|
||||||
Module(
|
Module(
|
||||||
ModModule {
|
ModModule {
|
||||||
range: 0..15,
|
range: 0..28,
|
||||||
|
body: [
|
||||||
|
FunctionDef(
|
||||||
|
StmtFunctionDef {
|
||||||
|
range: 0..27,
|
||||||
|
is_async: false,
|
||||||
|
decorator_list: [],
|
||||||
|
name: Identifier {
|
||||||
|
id: Name("_"),
|
||||||
|
range: 4..5,
|
||||||
|
},
|
||||||
|
type_params: None,
|
||||||
|
parameters: Parameters {
|
||||||
|
range: 5..7,
|
||||||
|
posonlyargs: [],
|
||||||
|
args: [],
|
||||||
|
vararg: None,
|
||||||
|
kwonlyargs: [],
|
||||||
|
kwarg: None,
|
||||||
|
},
|
||||||
|
returns: None,
|
||||||
body: [
|
body: [
|
||||||
Nonlocal(
|
Nonlocal(
|
||||||
StmtNonlocal {
|
StmtNonlocal {
|
||||||
range: 0..10,
|
range: 13..23,
|
||||||
names: [
|
names: [
|
||||||
Identifier {
|
Identifier {
|
||||||
id: Name("x"),
|
id: Name("x"),
|
||||||
range: 9..10,
|
range: 22..23,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
Expr(
|
Expr(
|
||||||
StmtExpr {
|
StmtExpr {
|
||||||
range: 11..14,
|
range: 24..27,
|
||||||
value: UnaryOp(
|
value: UnaryOp(
|
||||||
ExprUnaryOp {
|
ExprUnaryOp {
|
||||||
range: 11..14,
|
range: 24..27,
|
||||||
op: UAdd,
|
op: UAdd,
|
||||||
operand: NumberLiteral(
|
operand: NumberLiteral(
|
||||||
ExprNumberLiteral {
|
ExprNumberLiteral {
|
||||||
range: 13..14,
|
range: 26..27,
|
||||||
value: Int(
|
value: Int(
|
||||||
1,
|
1,
|
||||||
),
|
),
|
||||||
|
@ -42,11 +61,15 @@ Module(
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
## Errors
|
## Errors
|
||||||
|
|
||||||
|
|
|
|
||||||
1 | nonlocal x + 1
|
1 | def _():
|
||||||
|
2 | nonlocal x + 1
|
||||||
| ^ Syntax Error: Simple statements must be separated by newlines or semicolons
|
| ^ Syntax Error: Simple statements must be separated by newlines or semicolons
|
||||||
|
|
|
|
||||||
|
|
|
@ -1,80 +1,105 @@
|
||||||
---
|
---
|
||||||
source: crates/ruff_python_parser/tests/fixtures.rs
|
source: crates/ruff_python_parser/tests/fixtures.rs
|
||||||
input_file: crates/ruff_python_parser/resources/inline/err/nonlocal_stmt_trailing_comma.py
|
input_file: crates/ruff_python_parser/resources/inline/err/nonlocal_stmt_trailing_comma.py
|
||||||
snapshot_kind: text
|
|
||||||
---
|
---
|
||||||
## AST
|
## AST
|
||||||
|
|
||||||
```
|
```
|
||||||
Module(
|
Module(
|
||||||
ModModule {
|
ModModule {
|
||||||
range: 0..38,
|
range: 0..59,
|
||||||
|
body: [
|
||||||
|
FunctionDef(
|
||||||
|
StmtFunctionDef {
|
||||||
|
range: 0..58,
|
||||||
|
is_async: false,
|
||||||
|
decorator_list: [],
|
||||||
|
name: Identifier {
|
||||||
|
id: Name("_"),
|
||||||
|
range: 4..5,
|
||||||
|
},
|
||||||
|
type_params: None,
|
||||||
|
parameters: Parameters {
|
||||||
|
range: 5..7,
|
||||||
|
posonlyargs: [],
|
||||||
|
args: [],
|
||||||
|
vararg: None,
|
||||||
|
kwonlyargs: [],
|
||||||
|
kwarg: None,
|
||||||
|
},
|
||||||
|
returns: None,
|
||||||
body: [
|
body: [
|
||||||
Nonlocal(
|
Nonlocal(
|
||||||
StmtNonlocal {
|
StmtNonlocal {
|
||||||
range: 0..10,
|
range: 13..23,
|
||||||
names: [],
|
names: [],
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
Nonlocal(
|
Nonlocal(
|
||||||
StmtNonlocal {
|
StmtNonlocal {
|
||||||
range: 11..22,
|
range: 28..39,
|
||||||
names: [
|
names: [
|
||||||
Identifier {
|
Identifier {
|
||||||
id: Name("x"),
|
id: Name("x"),
|
||||||
range: 20..21,
|
range: 37..38,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
Nonlocal(
|
Nonlocal(
|
||||||
StmtNonlocal {
|
StmtNonlocal {
|
||||||
range: 23..37,
|
range: 44..58,
|
||||||
names: [
|
names: [
|
||||||
Identifier {
|
Identifier {
|
||||||
id: Name("x"),
|
id: Name("x"),
|
||||||
range: 32..33,
|
range: 53..54,
|
||||||
},
|
},
|
||||||
Identifier {
|
Identifier {
|
||||||
id: Name("y"),
|
id: Name("y"),
|
||||||
range: 35..36,
|
range: 56..57,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
## Errors
|
## Errors
|
||||||
|
|
||||||
|
|
|
|
||||||
1 | nonlocal ,
|
1 | def _():
|
||||||
|
2 | nonlocal ,
|
||||||
| ^ Syntax Error: Expected an identifier
|
| ^ Syntax Error: Expected an identifier
|
||||||
2 | nonlocal x,
|
3 | nonlocal x,
|
||||||
3 | nonlocal x, y,
|
4 | nonlocal x, y,
|
||||||
|
|
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
|
||||||
1 | nonlocal ,
|
1 | def _():
|
||||||
|
2 | nonlocal ,
|
||||||
| ^ Syntax Error: Nonlocal statement must have at least one name
|
| ^ Syntax Error: Nonlocal statement must have at least one name
|
||||||
2 | nonlocal x,
|
3 | nonlocal x,
|
||||||
3 | nonlocal x, y,
|
4 | nonlocal x, y,
|
||||||
|
|
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
|
||||||
1 | nonlocal ,
|
1 | def _():
|
||||||
2 | nonlocal x,
|
2 | nonlocal ,
|
||||||
|
3 | nonlocal x,
|
||||||
| ^ Syntax Error: Trailing comma not allowed
|
| ^ Syntax Error: Trailing comma not allowed
|
||||||
3 | nonlocal x, y,
|
4 | nonlocal x, y,
|
||||||
|
|
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
|
||||||
1 | nonlocal ,
|
2 | nonlocal ,
|
||||||
2 | nonlocal x,
|
3 | nonlocal x,
|
||||||
3 | nonlocal x, y,
|
4 | nonlocal x, y,
|
||||||
| ^ Syntax Error: Trailing comma not allowed
|
| ^ Syntax Error: Trailing comma not allowed
|
||||||
|
|
|
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
---
|
||||||
|
source: crates/ruff_python_parser/tests/fixtures.rs
|
||||||
|
input_file: crates/ruff_python_parser/resources/inline/ok/nonlocal_declaration_at_module_level.py
|
||||||
|
---
|
||||||
|
## AST
|
||||||
|
|
||||||
|
```
|
||||||
|
Module(
|
||||||
|
ModModule {
|
||||||
|
range: 0..24,
|
||||||
|
body: [
|
||||||
|
FunctionDef(
|
||||||
|
StmtFunctionDef {
|
||||||
|
range: 0..23,
|
||||||
|
is_async: false,
|
||||||
|
decorator_list: [],
|
||||||
|
name: Identifier {
|
||||||
|
id: Name("_"),
|
||||||
|
range: 4..5,
|
||||||
|
},
|
||||||
|
type_params: None,
|
||||||
|
parameters: Parameters {
|
||||||
|
range: 5..7,
|
||||||
|
posonlyargs: [],
|
||||||
|
args: [],
|
||||||
|
vararg: None,
|
||||||
|
kwonlyargs: [],
|
||||||
|
kwarg: None,
|
||||||
|
},
|
||||||
|
returns: None,
|
||||||
|
body: [
|
||||||
|
Nonlocal(
|
||||||
|
StmtNonlocal {
|
||||||
|
range: 13..23,
|
||||||
|
names: [
|
||||||
|
Identifier {
|
||||||
|
id: Name("x"),
|
||||||
|
range: 22..23,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
)
|
||||||
|
```
|
|
@ -1,46 +1,68 @@
|
||||||
---
|
---
|
||||||
source: crates/ruff_python_parser/tests/fixtures.rs
|
source: crates/ruff_python_parser/tests/fixtures.rs
|
||||||
input_file: crates/ruff_python_parser/resources/inline/ok/nonlocal_stmt.py
|
input_file: crates/ruff_python_parser/resources/inline/ok/nonlocal_stmt.py
|
||||||
snapshot_kind: text
|
|
||||||
---
|
---
|
||||||
## AST
|
## AST
|
||||||
|
|
||||||
```
|
```
|
||||||
Module(
|
Module(
|
||||||
ModModule {
|
ModModule {
|
||||||
range: 0..28,
|
range: 0..45,
|
||||||
|
body: [
|
||||||
|
FunctionDef(
|
||||||
|
StmtFunctionDef {
|
||||||
|
range: 0..44,
|
||||||
|
is_async: false,
|
||||||
|
decorator_list: [],
|
||||||
|
name: Identifier {
|
||||||
|
id: Name("_"),
|
||||||
|
range: 4..5,
|
||||||
|
},
|
||||||
|
type_params: None,
|
||||||
|
parameters: Parameters {
|
||||||
|
range: 5..7,
|
||||||
|
posonlyargs: [],
|
||||||
|
args: [],
|
||||||
|
vararg: None,
|
||||||
|
kwonlyargs: [],
|
||||||
|
kwarg: None,
|
||||||
|
},
|
||||||
|
returns: None,
|
||||||
body: [
|
body: [
|
||||||
Nonlocal(
|
Nonlocal(
|
||||||
StmtNonlocal {
|
StmtNonlocal {
|
||||||
range: 0..10,
|
range: 13..23,
|
||||||
names: [
|
names: [
|
||||||
Identifier {
|
Identifier {
|
||||||
id: Name("x"),
|
id: Name("x"),
|
||||||
range: 9..10,
|
range: 22..23,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
Nonlocal(
|
Nonlocal(
|
||||||
StmtNonlocal {
|
StmtNonlocal {
|
||||||
range: 11..27,
|
range: 28..44,
|
||||||
names: [
|
names: [
|
||||||
Identifier {
|
Identifier {
|
||||||
id: Name("x"),
|
id: Name("x"),
|
||||||
range: 20..21,
|
range: 37..38,
|
||||||
},
|
},
|
||||||
Identifier {
|
Identifier {
|
||||||
id: Name("y"),
|
id: Name("y"),
|
||||||
range: 23..24,
|
range: 40..41,
|
||||||
},
|
},
|
||||||
Identifier {
|
Identifier {
|
||||||
id: Name("z"),
|
id: Name("z"),
|
||||||
range: 26..27,
|
range: 43..44,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue