[red-knot] Auto generate statement nodes (#16645)

<!--
Thank you for contributing to Ruff! To help us out with reviewing,
please consider the following:

- Does this pull request include a summary of the change? (See below.)
- Does this pull request include a descriptive title?
- Does this pull request include references to any relevant issues?
-->

## Summary

<!-- What's the purpose of the change? What does it do, and why? -->

Part of #15655 

Replaced statement nodes with autogenerated ones. Reused the stuff we
introduced in #16285. Nothing except for copying the nodes to new
format.

## Test Plan

Tests run without any changes. Also moved the test that checks size of
AST nodes to `generated.rs` since all of the structs that it tests are
now there.
<!-- How was it tested? -->
This commit is contained in:
Shaygan Hooshyari 2025-03-13 15:43:48 +01:00 committed by GitHub
parent d8159e816f
commit 360ba095ff
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 552 additions and 375 deletions

View file

@ -66,32 +66,236 @@ add_suffix_to_is_methods = true
anynode_is_label = "statement" anynode_is_label = "statement"
doc = "See also [stmt](https://docs.python.org/3/library/ast.html#ast.stmt)" doc = "See also [stmt](https://docs.python.org/3/library/ast.html#ast.stmt)"
[Stmt.nodes] [Stmt.nodes.StmtFunctionDef]
StmtFunctionDef = {} doc = """See also [FunctionDef](https://docs.python.org/3/library/ast.html#ast.FunctionDef)
StmtClassDef = {} and [AsyncFunctionDef](https://docs.python.org/3/library/ast.html#ast.AsyncFunctionDef).
StmtReturn = {}
StmtDelete = {} This type differs from the original Python AST, as it collapses the synchronous and asynchronous variants into a single type."""
StmtTypeAlias = {} fields = [
StmtAssign = {} { name = "is_async", type = "bool" },
StmtAugAssign = {} { name = "decorator_list", type = "Decorator*" },
StmtAnnAssign = {} { name = "name", type = "Identifier" },
StmtFor = {} { name = "type_params", type = "Box<crate::TypeParams>?" },
StmtWhile = {} { name = "parameters", type = "Box<crate::Parameters>" },
StmtIf = {}
StmtWith = {} { name = "returns", type = "Expr?" },
StmtMatch = {} { name = "body", type = "Stmt*" },
StmtRaise = {} ]
StmtTry = {}
StmtAssert = {} [Stmt.nodes.StmtClassDef]
StmtImport = {} doc = "See also [ClassDef](https://docs.python.org/3/library/ast.html#ast.ClassDef)"
StmtImportFrom = {} fields = [
StmtGlobal = {} { name = "decorator_list", type = "Decorator*" },
StmtNonlocal = {} { name = "name", type = "Identifier" },
StmtExpr = {} { name = "type_params", type = "Box<crate::TypeParams>?" },
StmtPass = {} { name = "arguments", type = "Box<crate::Arguments>?" },
StmtBreak = {} { name = "body", type = "Stmt*" },
StmtContinue = {} ]
StmtIpyEscapeCommand = {}
[Stmt.nodes.StmtReturn]
doc = "See also [Return](https://docs.python.org/3/library/ast.html#ast.Return)"
fields = [{ name = "value", type = "Expr?" }]
[Stmt.nodes.StmtDelete]
doc = "See also [Delete](https://docs.python.org/3/library/ast.html#ast.Delete)"
fields = [{ name = "targets", type = "Expr*" }]
[Stmt.nodes.StmtTypeAlias]
doc = "See also [TypeAlias](https://docs.python.org/3/library/ast.html#ast.TypeAlias)"
fields = [
{ name = "name", type = "Expr" },
{ name = "type_params", type = "TypeParams?" },
{ name = "value", type = "Expr" },
]
[Stmt.nodes.StmtAssign]
doc = "See also [Assign](https://docs.python.org/3/library/ast.html#ast.Assign)"
fields = [
{ name = "targets", type = "Expr*" },
{ name = "value", type = "Expr" },
]
[Stmt.nodes.StmtAugAssign]
doc = "See also [AugAssign](https://docs.python.org/3/library/ast.html#ast.AugAssign)"
fields = [
{ name = "target", type = "Expr" },
{ name = "op", type = "Operator" },
{ name = "value", type = "Expr" },
]
[Stmt.nodes.StmtAnnAssign]
doc = "See also [AnnAssign](https://docs.python.org/3/library/ast.html#ast.AnnAssign)"
fields = [
{ name = "target", type = "Expr" },
{ name = "annotation", type = "Expr" },
{ name = "value", type = "Expr?" },
{ name = "simple", type = "bool" },
]
[Stmt.nodes.StmtFor]
doc = """See also [For](https://docs.python.org/3/library/ast.html#ast.For)
and [AsyncFor](https://docs.python.org/3/library/ast.html#ast.AsyncFor).
This type differs from the original Python AST, as it collapses the synchronous and asynchronous variants into a single type."""
fields = [
{ name = "is_async", type = "bool" },
{ name = "target", type = "Expr" },
{ name = "iter", type = "Expr" },
{ name = "body", type = "Stmt*" },
{ name = "orelse", type = "Stmt*" },
]
[Stmt.nodes.StmtWhile]
doc = """See also [While](https://docs.python.org/3/library/ast.html#ast.While)
and [AsyncWhile](https://docs.python.org/3/library/ast.html#ast.AsyncWhile)."""
fields = [
{ name = "test", type = "Expr" },
{ name = "body", type = "Stmt*" },
{ name = "orelse", type = "Stmt*" },
]
[Stmt.nodes.StmtIf]
doc = "See also [If](https://docs.python.org/3/library/ast.html#ast.If)"
fields = [
{ name = "test", type = "Expr" },
{ name = "body", type = "Stmt*" },
{ name = "elif_else_clauses", type = "ElifElseClause*" },
]
[Stmt.nodes.StmtWith]
doc = """See also [With](https://docs.python.org/3/library/ast.html#ast.With)
and [AsyncWith](https://docs.python.org/3/library/ast.html#ast.AsyncWith).
This type differs from the original Python AST, as it collapses the synchronous and asynchronous variants into a single type."""
fields = [
{ name = "is_async", type = "bool" },
{ name = "items", type = "WithItem*" },
{ name = "body", type = "Stmt*" },
]
[Stmt.nodes.StmtMatch]
doc = "See also [Match](https://docs.python.org/3/library/ast.html#ast.Match)"
fields = [
{ name = "subject", type = "Expr" },
{ name = "cases", type = "MatchCase*" },
]
[Stmt.nodes.StmtRaise]
doc = "See also [Raise](https://docs.python.org/3/library/ast.html#ast.Raise)"
fields = [{ name = "exc", type = "Expr?" }, { name = "cause", type = "Expr?" }]
[Stmt.nodes.StmtTry]
doc = """See also [Try](https://docs.python.org/3/library/ast.html#ast.Try)
and [TryStar](https://docs.python.org/3/library/ast.html#ast.TryStar)"""
fields = [
{ name = "body", type = "Stmt*" },
{ name = "handlers", type = "ExceptHandler*" },
{ name = "orelse", type = "Stmt*" },
{ name = "finalbody", type = "Stmt*" },
{ name = "is_star", type = "bool" },
]
[Stmt.nodes.StmtAssert]
doc = "See also [Assert](https://docs.python.org/3/library/ast.html#ast.Assert)"
fields = [{ name = "test", type = "Expr" }, { name = "msg", type = "Expr?" }]
[Stmt.nodes.StmtImport]
doc = "See also [Import](https://docs.python.org/3/library/ast.html#ast.Import)"
fields = [{ name = "names", type = "Alias*" }]
[Stmt.nodes.StmtImportFrom]
doc = "See also [ImportFrom](https://docs.python.org/3/library/ast.html#ast.ImportFrom)"
fields = [
{ name = "module", type = "Identifier?" },
{ name = "names", type = "Alias*" },
{ name = "level", type = "u32" },
]
[Stmt.nodes.StmtGlobal]
doc = "See also [Global](https://docs.python.org/3/library/ast.html#ast.Global)"
fields = [{ name = "names", type = "Identifier*" }]
[Stmt.nodes.StmtNonlocal]
doc = "See also [Nonlocal](https://docs.python.org/3/library/ast.html#ast.Nonlocal)"
fields = [{ name = "names", type = "Identifier*" }]
[Stmt.nodes.StmtExpr]
doc = "See also [Expr](https://docs.python.org/3/library/ast.html#ast.Expr)"
fields = [{ name = "value", type = "Expr" }]
[Stmt.nodes.StmtPass]
doc = "See also [Pass](https://docs.python.org/3/library/ast.html#ast.Pass)"
fields = []
[Stmt.nodes.StmtBreak]
doc = "See also [Break](https://docs.python.org/3/library/ast.html#ast.Break)"
fields = []
[Stmt.nodes.StmtContinue]
doc = "See also [Continue](https://docs.python.org/3/library/ast.html#ast.Continue)"
fields = []
[Stmt.nodes.StmtIpyEscapeCommand]
# TODO: remove crate:: prefix from IpyEscapeKind after it's auto generated
doc = """An AST node used to represent a IPython escape command at the statement level.
For example,
```python
%matplotlib inline
```
## Terminology
Escape commands are special IPython syntax which starts with a token to identify
the escape kind followed by the command value itself. [Escape kind] are the kind
of escape commands that are recognized by the token: `%`, `%%`, `!`, `!!`,
`?`, `??`, `/`, `;`, and `,`.
Help command (or Dynamic Object Introspection as it's called) are the escape commands
of the kind `?` and `??`. For example, `?str.replace`. Help end command are a subset
of Help command where the token can be at the end of the line i.e., after the value.
For example, `str.replace?`.
Here's where things get tricky. I'll divide the help end command into two types for
better understanding:
1. Strict version: The token is _only_ at the end of the line. For example,
`str.replace?` or `str.replace??`.
2. Combined version: Along with the `?` or `??` token, which are at the end of the
line, there are other escape kind tokens that are present at the start as well.
For example, `%matplotlib?` or `%%timeit?`.
Priority comes into picture for the "Combined version" mentioned above. How do
we determine the escape kind if there are tokens on both side of the value, i.e., which
token to choose? The Help end command always takes priority over any other token which
means that if there is `?`/`??` at the end then that is used to determine the kind.
For example, in `%matplotlib?` the escape kind is determined using the `?` token
instead of `%` token.
## Syntax
`<IpyEscapeKind><Command value>`
The simplest form is an escape kind token followed by the command value. For example,
`%matplotlib inline`, `/foo`, `!pwd`, etc.
`<Command value><IpyEscapeKind ("?" or "??")>`
The help end escape command would be the reverse of the above syntax. Here, the
escape kind token can only be either `?` or `??` and it is at the end of the line.
For example, `str.replace?`, `math.pi??`, etc.
`<IpyEscapeKind><Command value><EscapeKind ("?" or "??")>`
The final syntax is the combined version of the above two. For example, `%matplotlib?`,
`%%timeit??`, etc.
[Escape kind]: crate::IpyEscapeKind
"""
fields = [
{ name = "kind", type = "IpyEscapeKind" },
{ name = "value", type = "Box<str>" },
]
[Expr] [Expr]
add_suffix_to_is_methods = true add_suffix_to_is_methods = true
@ -100,38 +304,32 @@ doc = "See also [expr](https://docs.python.org/3/library/ast.html#ast.expr)"
[Expr.nodes.ExprBoolOp] [Expr.nodes.ExprBoolOp]
doc = "See also [BoolOp](https://docs.python.org/3/library/ast.html#ast.BoolOp)" doc = "See also [BoolOp](https://docs.python.org/3/library/ast.html#ast.BoolOp)"
fields = [ fields = [{ name = "op", type = "BoolOp" }, { name = "values", type = "Expr*" }]
{ name = "op", type = "BoolOp" },
{ name = "values", type = "Expr*" }
]
[Expr.nodes.ExprNamed] [Expr.nodes.ExprNamed]
doc = "See also [NamedExpr](https://docs.python.org/3/library/ast.html#ast.NamedExpr)" doc = "See also [NamedExpr](https://docs.python.org/3/library/ast.html#ast.NamedExpr)"
fields = [ fields = [{ name = "target", type = "Expr" }, { name = "value", type = "Expr" }]
{ name = "target", type = "Expr" },
{ name = "value", type = "Expr" }
]
[Expr.nodes.ExprBinOp] [Expr.nodes.ExprBinOp]
doc = "See also [BinOp](https://docs.python.org/3/library/ast.html#ast.BinOp)" doc = "See also [BinOp](https://docs.python.org/3/library/ast.html#ast.BinOp)"
fields = [ fields = [
{ name = "left", type = "Expr" }, { name = "left", type = "Expr" },
{ name = "op", type = "Operator" }, { name = "op", type = "Operator" },
{ name = "right", type = "Expr" } { name = "right", type = "Expr" },
] ]
[Expr.nodes.ExprUnaryOp] [Expr.nodes.ExprUnaryOp]
doc = "See also [UnaryOp](https://docs.python.org/3/library/ast.html#ast.UnaryOp)" doc = "See also [UnaryOp](https://docs.python.org/3/library/ast.html#ast.UnaryOp)"
fields = [ fields = [
{ name = "op", type = "UnaryOp" }, { name = "op", type = "UnaryOp" },
{ name = "operand", type = "Expr" } { name = "operand", type = "Expr" },
] ]
[Expr.nodes.ExprLambda] [Expr.nodes.ExprLambda]
doc = "See also [Lambda](https://docs.python.org/3/library/ast.html#ast.Lambda)" doc = "See also [Lambda](https://docs.python.org/3/library/ast.html#ast.Lambda)"
fields = [ fields = [
{ name = "parameters", type = "Box<crate::Parameters>?" }, { name = "parameters", type = "Box<crate::Parameters>?" },
{ name = "body", type = "Expr" } { name = "body", type = "Expr" },
] ]
[Expr.nodes.ExprIf] [Expr.nodes.ExprIf]
@ -139,33 +337,29 @@ doc = "See also [IfExp](https://docs.python.org/3/library/ast.html#ast.IfExp)"
fields = [ fields = [
{ name = "test", type = "Expr" }, { name = "test", type = "Expr" },
{ name = "body", type = "Expr" }, { name = "body", type = "Expr" },
{ name = "orelse", type = "Expr" } { name = "orelse", type = "Expr" },
] ]
[Expr.nodes.ExprDict] [Expr.nodes.ExprDict]
doc = "See also [Dict](https://docs.python.org/3/library/ast.html#ast.Dict)" doc = "See also [Dict](https://docs.python.org/3/library/ast.html#ast.Dict)"
fields = [ fields = [{ name = "items", type = "DictItem*" }]
{ name = "items", type = "DictItem*" }
]
[Expr.nodes.ExprSet] [Expr.nodes.ExprSet]
doc = "See also [Set](https://docs.python.org/3/library/ast.html#ast.Set)" doc = "See also [Set](https://docs.python.org/3/library/ast.html#ast.Set)"
fields = [ fields = [{ name = "elts", type = "Expr*" }]
{ name = "elts", type = "Expr*" }
]
[Expr.nodes.ExprListComp] [Expr.nodes.ExprListComp]
doc = "See also [ListComp](https://docs.python.org/3/library/ast.html#ast.ListComp)" doc = "See also [ListComp](https://docs.python.org/3/library/ast.html#ast.ListComp)"
fields = [ fields = [
{ name = "elt", type = "Expr" }, { name = "elt", type = "Expr" },
{ name = "generators", type = "Comprehension*" } { name = "generators", type = "Comprehension*" },
] ]
[Expr.nodes.ExprSetComp] [Expr.nodes.ExprSetComp]
doc = "See also [SetComp](https://docs.python.org/3/library/ast.html#ast.SetComp)" doc = "See also [SetComp](https://docs.python.org/3/library/ast.html#ast.SetComp)"
fields = [ fields = [
{ name = "elt", type = "Expr" }, { name = "elt", type = "Expr" },
{ name = "generators", type = "Comprehension*" } { name = "generators", type = "Comprehension*" },
] ]
[Expr.nodes.ExprDictComp] [Expr.nodes.ExprDictComp]
@ -173,7 +367,7 @@ doc = "See also [DictComp](https://docs.python.org/3/library/ast.html#ast.DictCo
fields = [ fields = [
{ name = "key", type = "Expr" }, { name = "key", type = "Expr" },
{ name = "value", type = "Expr" }, { name = "value", type = "Expr" },
{ name = "generators", type = "Comprehension*" } { name = "generators", type = "Comprehension*" },
] ]
[Expr.nodes.ExprGenerator] [Expr.nodes.ExprGenerator]
@ -181,40 +375,34 @@ doc = "See also [GeneratorExp](https://docs.python.org/3/library/ast.html#ast.Ge
fields = [ fields = [
{ name = "elt", type = "Expr" }, { name = "elt", type = "Expr" },
{ name = "generators", type = "Comprehension*" }, { name = "generators", type = "Comprehension*" },
{ name = "parenthesized", type = "bool" } { name = "parenthesized", type = "bool" },
] ]
[Expr.nodes.ExprAwait] [Expr.nodes.ExprAwait]
doc = "See also [Await](https://docs.python.org/3/library/ast.html#ast.Await)" doc = "See also [Await](https://docs.python.org/3/library/ast.html#ast.Await)"
fields = [ fields = [{ name = "value", type = "Expr" }]
{ name = "value", type = "Expr" }
]
[Expr.nodes.ExprYield] [Expr.nodes.ExprYield]
doc = "See also [Yield](https://docs.python.org/3/library/ast.html#ast.Yield)" doc = "See also [Yield](https://docs.python.org/3/library/ast.html#ast.Yield)"
fields = [ fields = [{ name = "value", type = "Expr?" }]
{ name = "value", type = "Expr?" }
]
[Expr.nodes.ExprYieldFrom] [Expr.nodes.ExprYieldFrom]
doc = "See also [YieldFrom](https://docs.python.org/3/library/ast.html#ast.YieldFrom)" doc = "See also [YieldFrom](https://docs.python.org/3/library/ast.html#ast.YieldFrom)"
fields = [ fields = [{ name = "value", type = "Expr" }]
{ name = "value", type = "Expr" }
]
[Expr.nodes.ExprCompare] [Expr.nodes.ExprCompare]
doc = "See also [Compare](https://docs.python.org/3/library/ast.html#ast.Compare)" doc = "See also [Compare](https://docs.python.org/3/library/ast.html#ast.Compare)"
fields = [ fields = [
{ name = "left", type = "Expr" }, { name = "left", type = "Expr" },
{ name = "ops", type = "&CmpOp*" }, { name = "ops", type = "&CmpOp*" },
{ name = "comparators", type = "&Expr*" } { name = "comparators", type = "&Expr*" },
] ]
[Expr.nodes.ExprCall] [Expr.nodes.ExprCall]
doc = "See also [Call](https://docs.python.org/3/library/ast.html#ast.Call)" doc = "See also [Call](https://docs.python.org/3/library/ast.html#ast.Call)"
fields = [ fields = [
{ name = "func", type = "Expr" }, { name = "func", type = "Expr" },
{ name = "arguments", type = "Arguments" } { name = "arguments", type = "Arguments" },
] ]
[Expr.nodes.ExprFString] [Expr.nodes.ExprFString]
@ -226,33 +414,23 @@ doesn't join the implicitly concatenated parts into a single string. Instead,
it keeps them separate and provide various methods to access the parts. it keeps them separate and provide various methods to access the parts.
See also [JoinedStr](https://docs.python.org/3/library/ast.html#ast.JoinedStr)""" See also [JoinedStr](https://docs.python.org/3/library/ast.html#ast.JoinedStr)"""
fields = [ fields = [{ name = "value", type = "FStringValue" }]
{ name = "value", type = "FStringValue" }
]
[Expr.nodes.ExprStringLiteral] [Expr.nodes.ExprStringLiteral]
doc = """An AST node that represents either a single-part string literal doc = """An AST node that represents either a single-part string literal
or an implicitly concatenated string literal.""" or an implicitly concatenated string literal."""
fields = [ fields = [{ name = "value", type = "StringLiteralValue" }]
{ name = "value", type = "StringLiteralValue" }
]
[Expr.nodes.ExprBytesLiteral] [Expr.nodes.ExprBytesLiteral]
doc = """An AST node that represents either a single-part bytestring literal doc = """An AST node that represents either a single-part bytestring literal
or an implicitly concatenated bytestring literal.""" or an implicitly concatenated bytestring literal."""
fields = [ fields = [{ name = "value", type = "BytesLiteralValue" }]
{ name = "value", type = "BytesLiteralValue" }
]
[Expr.nodes.ExprNumberLiteral] [Expr.nodes.ExprNumberLiteral]
fields = [ fields = [{ name = "value", type = "Number" }]
{ name = "value", type = "Number" }
]
[Expr.nodes.ExprBooleanLiteral] [Expr.nodes.ExprBooleanLiteral]
fields = [ fields = [{ name = "value", type = "bool" }]
{ name = "value", type = "bool" }
]
derives = ["Default"] derives = ["Default"]
[Expr.nodes.ExprNoneLiteral] [Expr.nodes.ExprNoneLiteral]
@ -268,7 +446,7 @@ doc = "See also [Attribute](https://docs.python.org/3/library/ast.html#ast.Attri
fields = [ fields = [
{ name = "value", type = "Expr" }, { name = "value", type = "Expr" },
{ name = "attr", type = "Identifier" }, { name = "attr", type = "Identifier" },
{ name = "ctx", type = "ExprContext" } { name = "ctx", type = "ExprContext" },
] ]
[Expr.nodes.ExprSubscript] [Expr.nodes.ExprSubscript]
@ -276,28 +454,28 @@ doc = "See also [Subscript](https://docs.python.org/3/library/ast.html#ast.Subsc
fields = [ fields = [
{ name = "value", type = "Expr" }, { name = "value", type = "Expr" },
{ name = "slice", type = "Expr" }, { name = "slice", type = "Expr" },
{ name = "ctx", type = "ExprContext" } { name = "ctx", type = "ExprContext" },
] ]
[Expr.nodes.ExprStarred] [Expr.nodes.ExprStarred]
doc = "See also [Starred](https://docs.python.org/3/library/ast.html#ast.Starred)" doc = "See also [Starred](https://docs.python.org/3/library/ast.html#ast.Starred)"
fields = [ fields = [
{ name = "value", type = "Expr" }, { name = "value", type = "Expr" },
{ name = "ctx", type = "ExprContext" } { name = "ctx", type = "ExprContext" },
] ]
[Expr.nodes.ExprName] [Expr.nodes.ExprName]
doc = "See also [Name](https://docs.python.org/3/library/ast.html#ast.Name)" doc = "See also [Name](https://docs.python.org/3/library/ast.html#ast.Name)"
fields = [ fields = [
{ name = "id", type = "Name" }, { name = "id", type = "Name" },
{ name = "ctx", type = "ExprContext" } { name = "ctx", type = "ExprContext" },
] ]
[Expr.nodes.ExprList] [Expr.nodes.ExprList]
doc = "See also [List](https://docs.python.org/3/library/ast.html#ast.List)" doc = "See also [List](https://docs.python.org/3/library/ast.html#ast.List)"
fields = [ fields = [
{ name = "elts", type = "Expr*" }, { name = "elts", type = "Expr*" },
{ name = "ctx", type = "ExprContext" } { name = "ctx", type = "ExprContext" },
] ]
[Expr.nodes.ExprTuple] [Expr.nodes.ExprTuple]
@ -305,7 +483,7 @@ doc = "See also [Tuple](https://docs.python.org/3/library/ast.html#ast.Tuple)"
fields = [ fields = [
{ name = "elts", type = "Expr*" }, { name = "elts", type = "Expr*" },
{ name = "ctx", type = "ExprContext" }, { name = "ctx", type = "ExprContext" },
{ name = "parenthesized", type = "bool" } { name = "parenthesized", type = "bool" },
] ]
[Expr.nodes.ExprSlice] [Expr.nodes.ExprSlice]
@ -313,11 +491,10 @@ doc = "See also [Slice](https://docs.python.org/3/library/ast.html#ast.Slice)"
fields = [ fields = [
{ name = "lower", type = "Expr?" }, { name = "lower", type = "Expr?" },
{ name = "upper", type = "Expr?" }, { name = "upper", type = "Expr?" },
{ name = "step", type = "Expr?" } { name = "step", type = "Expr?" },
] ]
[Expr.nodes.ExprIpyEscapeCommand] [Expr.nodes.ExprIpyEscapeCommand]
# TODO: Remove the crate:: prefix once StmtIpyEscapeCommand is moved to generated.rs
doc = """An AST node used to represent a IPython escape command at the expression level. doc = """An AST node used to represent a IPython escape command at the expression level.
For example, For example,
@ -328,11 +505,11 @@ dir = !pwd
Here, the escape kind can only be `!` or `%` otherwise it is a syntax error. Here, the escape kind can only be `!` or `%` otherwise it is a syntax error.
For more information related to terminology and syntax of escape commands, For more information related to terminology and syntax of escape commands,
see [`crate::StmtIpyEscapeCommand`].""" see [`StmtIpyEscapeCommand`]."""
fields = [ fields = [
{ name = "kind", type = "IpyEscapeKind" }, { name = "kind", type = "IpyEscapeKind" },
{ name = "value", type = "Box<str>" } { name = "value", type = "Box<str>" },
] ]
[ExceptHandler] [ExceptHandler]

View file

@ -30,6 +30,14 @@ types_requiring_create_prefix = [
"UnaryOp", "UnaryOp",
"BoolOp", "BoolOp",
"Operator", "Operator",
"Decorator",
"TypeParams",
"Parameters",
"Arguments",
"ElifElseClause",
"WithItem",
"MatchCase",
"Alias",
] ]

View file

@ -6448,6 +6448,280 @@ impl AnyNodeRef<'_> {
} }
} }
/// See also [FunctionDef](https://docs.python.org/3/library/ast.html#ast.FunctionDef)
/// and [AsyncFunctionDef](https://docs.python.org/3/library/ast.html#ast.AsyncFunctionDef).
///
/// This type differs from the original Python AST, as it collapses the synchronous and asynchronous variants into a single type.
#[derive(Clone, Debug, PartialEq)]
pub struct StmtFunctionDef {
pub range: ruff_text_size::TextRange,
pub is_async: bool,
pub decorator_list: Vec<crate::Decorator>,
pub name: crate::Identifier,
pub type_params: Option<Box<crate::TypeParams>>,
pub parameters: Box<crate::Parameters>,
pub returns: Option<Box<Expr>>,
pub body: Vec<Stmt>,
}
/// See also [ClassDef](https://docs.python.org/3/library/ast.html#ast.ClassDef)
#[derive(Clone, Debug, PartialEq)]
pub struct StmtClassDef {
pub range: ruff_text_size::TextRange,
pub decorator_list: Vec<crate::Decorator>,
pub name: crate::Identifier,
pub type_params: Option<Box<crate::TypeParams>>,
pub arguments: Option<Box<crate::Arguments>>,
pub body: Vec<Stmt>,
}
/// See also [Return](https://docs.python.org/3/library/ast.html#ast.Return)
#[derive(Clone, Debug, PartialEq)]
pub struct StmtReturn {
pub range: ruff_text_size::TextRange,
pub value: Option<Box<Expr>>,
}
/// See also [Delete](https://docs.python.org/3/library/ast.html#ast.Delete)
#[derive(Clone, Debug, PartialEq)]
pub struct StmtDelete {
pub range: ruff_text_size::TextRange,
pub targets: Vec<Expr>,
}
/// See also [TypeAlias](https://docs.python.org/3/library/ast.html#ast.TypeAlias)
#[derive(Clone, Debug, PartialEq)]
pub struct StmtTypeAlias {
pub range: ruff_text_size::TextRange,
pub name: Box<Expr>,
pub type_params: Option<crate::TypeParams>,
pub value: Box<Expr>,
}
/// See also [Assign](https://docs.python.org/3/library/ast.html#ast.Assign)
#[derive(Clone, Debug, PartialEq)]
pub struct StmtAssign {
pub range: ruff_text_size::TextRange,
pub targets: Vec<Expr>,
pub value: Box<Expr>,
}
/// See also [AugAssign](https://docs.python.org/3/library/ast.html#ast.AugAssign)
#[derive(Clone, Debug, PartialEq)]
pub struct StmtAugAssign {
pub range: ruff_text_size::TextRange,
pub target: Box<Expr>,
pub op: crate::Operator,
pub value: Box<Expr>,
}
/// See also [AnnAssign](https://docs.python.org/3/library/ast.html#ast.AnnAssign)
#[derive(Clone, Debug, PartialEq)]
pub struct StmtAnnAssign {
pub range: ruff_text_size::TextRange,
pub target: Box<Expr>,
pub annotation: Box<Expr>,
pub value: Option<Box<Expr>>,
pub simple: bool,
}
/// See also [For](https://docs.python.org/3/library/ast.html#ast.For)
/// and [AsyncFor](https://docs.python.org/3/library/ast.html#ast.AsyncFor).
///
/// This type differs from the original Python AST, as it collapses the synchronous and asynchronous variants into a single type.
#[derive(Clone, Debug, PartialEq)]
pub struct StmtFor {
pub range: ruff_text_size::TextRange,
pub is_async: bool,
pub target: Box<Expr>,
pub iter: Box<Expr>,
pub body: Vec<Stmt>,
pub orelse: Vec<Stmt>,
}
/// See also [While](https://docs.python.org/3/library/ast.html#ast.While)
/// and [AsyncWhile](https://docs.python.org/3/library/ast.html#ast.AsyncWhile).
#[derive(Clone, Debug, PartialEq)]
pub struct StmtWhile {
pub range: ruff_text_size::TextRange,
pub test: Box<Expr>,
pub body: Vec<Stmt>,
pub orelse: Vec<Stmt>,
}
/// See also [If](https://docs.python.org/3/library/ast.html#ast.If)
#[derive(Clone, Debug, PartialEq)]
pub struct StmtIf {
pub range: ruff_text_size::TextRange,
pub test: Box<Expr>,
pub body: Vec<Stmt>,
pub elif_else_clauses: Vec<crate::ElifElseClause>,
}
/// See also [With](https://docs.python.org/3/library/ast.html#ast.With)
/// and [AsyncWith](https://docs.python.org/3/library/ast.html#ast.AsyncWith).
///
/// This type differs from the original Python AST, as it collapses the synchronous and asynchronous variants into a single type.
#[derive(Clone, Debug, PartialEq)]
pub struct StmtWith {
pub range: ruff_text_size::TextRange,
pub is_async: bool,
pub items: Vec<crate::WithItem>,
pub body: Vec<Stmt>,
}
/// See also [Match](https://docs.python.org/3/library/ast.html#ast.Match)
#[derive(Clone, Debug, PartialEq)]
pub struct StmtMatch {
pub range: ruff_text_size::TextRange,
pub subject: Box<Expr>,
pub cases: Vec<crate::MatchCase>,
}
/// See also [Raise](https://docs.python.org/3/library/ast.html#ast.Raise)
#[derive(Clone, Debug, PartialEq)]
pub struct StmtRaise {
pub range: ruff_text_size::TextRange,
pub exc: Option<Box<Expr>>,
pub cause: Option<Box<Expr>>,
}
/// See also [Try](https://docs.python.org/3/library/ast.html#ast.Try)
/// and [TryStar](https://docs.python.org/3/library/ast.html#ast.TryStar)
#[derive(Clone, Debug, PartialEq)]
pub struct StmtTry {
pub range: ruff_text_size::TextRange,
pub body: Vec<Stmt>,
pub handlers: Vec<ExceptHandler>,
pub orelse: Vec<Stmt>,
pub finalbody: Vec<Stmt>,
pub is_star: bool,
}
/// See also [Assert](https://docs.python.org/3/library/ast.html#ast.Assert)
#[derive(Clone, Debug, PartialEq)]
pub struct StmtAssert {
pub range: ruff_text_size::TextRange,
pub test: Box<Expr>,
pub msg: Option<Box<Expr>>,
}
/// See also [Import](https://docs.python.org/3/library/ast.html#ast.Import)
#[derive(Clone, Debug, PartialEq)]
pub struct StmtImport {
pub range: ruff_text_size::TextRange,
pub names: Vec<crate::Alias>,
}
/// See also [ImportFrom](https://docs.python.org/3/library/ast.html#ast.ImportFrom)
#[derive(Clone, Debug, PartialEq)]
pub struct StmtImportFrom {
pub range: ruff_text_size::TextRange,
pub module: Option<crate::Identifier>,
pub names: Vec<crate::Alias>,
pub level: u32,
}
/// See also [Global](https://docs.python.org/3/library/ast.html#ast.Global)
#[derive(Clone, Debug, PartialEq)]
pub struct StmtGlobal {
pub range: ruff_text_size::TextRange,
pub names: Vec<crate::Identifier>,
}
/// See also [Nonlocal](https://docs.python.org/3/library/ast.html#ast.Nonlocal)
#[derive(Clone, Debug, PartialEq)]
pub struct StmtNonlocal {
pub range: ruff_text_size::TextRange,
pub names: Vec<crate::Identifier>,
}
/// See also [Expr](https://docs.python.org/3/library/ast.html#ast.Expr)
#[derive(Clone, Debug, PartialEq)]
pub struct StmtExpr {
pub range: ruff_text_size::TextRange,
pub value: Box<Expr>,
}
/// See also [Pass](https://docs.python.org/3/library/ast.html#ast.Pass)
#[derive(Clone, Debug, PartialEq)]
pub struct StmtPass {
pub range: ruff_text_size::TextRange,
}
/// See also [Break](https://docs.python.org/3/library/ast.html#ast.Break)
#[derive(Clone, Debug, PartialEq)]
pub struct StmtBreak {
pub range: ruff_text_size::TextRange,
}
/// See also [Continue](https://docs.python.org/3/library/ast.html#ast.Continue)
#[derive(Clone, Debug, PartialEq)]
pub struct StmtContinue {
pub range: ruff_text_size::TextRange,
}
/// An AST node used to represent a IPython escape command at the statement level.
///
/// For example,
/// ```python
/// %matplotlib inline
/// ```
///
/// ## Terminology
///
/// Escape commands are special IPython syntax which starts with a token to identify
/// the escape kind followed by the command value itself. [Escape kind] are the kind
/// of escape commands that are recognized by the token: `%`, `%%`, `!`, `!!`,
/// `?`, `??`, `/`, `;`, and `,`.
///
/// Help command (or Dynamic Object Introspection as it's called) are the escape commands
/// of the kind `?` and `??`. For example, `?str.replace`. Help end command are a subset
/// of Help command where the token can be at the end of the line i.e., after the value.
/// For example, `str.replace?`.
///
/// Here's where things get tricky. I'll divide the help end command into two types for
/// better understanding:
/// 1. Strict version: The token is _only_ at the end of the line. For example,
/// `str.replace?` or `str.replace??`.
/// 2. Combined version: Along with the `?` or `??` token, which are at the end of the
/// line, there are other escape kind tokens that are present at the start as well.
/// For example, `%matplotlib?` or `%%timeit?`.
///
/// Priority comes into picture for the "Combined version" mentioned above. How do
/// we determine the escape kind if there are tokens on both side of the value, i.e., which
/// token to choose? The Help end command always takes priority over any other token which
/// means that if there is `?`/`??` at the end then that is used to determine the kind.
/// For example, in `%matplotlib?` the escape kind is determined using the `?` token
/// instead of `%` token.
///
/// ## Syntax
///
/// `<IpyEscapeKind><Command value>`
///
/// The simplest form is an escape kind token followed by the command value. For example,
/// `%matplotlib inline`, `/foo`, `!pwd`, etc.
///
/// `<Command value><IpyEscapeKind ("?" or "??")>`
///
/// The help end escape command would be the reverse of the above syntax. Here, the
/// escape kind token can only be either `?` or `??` and it is at the end of the line.
/// For example, `str.replace?`, `math.pi??`, etc.
///
/// `<IpyEscapeKind><Command value><EscapeKind ("?" or "??")>`
///
/// The final syntax is the combined version of the above two. For example, `%matplotlib?`,
/// `%%timeit??`, etc.
///
/// [Escape kind]: crate::IpyEscapeKind
///
#[derive(Clone, Debug, PartialEq)]
pub struct StmtIpyEscapeCommand {
pub range: ruff_text_size::TextRange,
pub kind: crate::IpyEscapeKind,
pub value: Box<str>,
}
/// See also [BoolOp](https://docs.python.org/3/library/ast.html#ast.BoolOp) /// See also [BoolOp](https://docs.python.org/3/library/ast.html#ast.BoolOp)
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub struct ExprBoolOp { pub struct ExprBoolOp {
@ -6706,7 +6980,7 @@ pub struct ExprSlice {
/// Here, the escape kind can only be `!` or `%` otherwise it is a syntax error. /// Here, the escape kind can only be `!` or `%` otherwise it is a syntax error.
/// ///
/// For more information related to terminology and syntax of escape commands, /// For more information related to terminology and syntax of escape commands,
/// see [`crate::StmtIpyEscapeCommand`]. /// see [`StmtIpyEscapeCommand`].
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub struct ExprIpyEscapeCommand { pub struct ExprIpyEscapeCommand {
pub range: ruff_text_size::TextRange, pub range: ruff_text_size::TextRange,

View file

@ -2,7 +2,7 @@
use crate::generated::{ use crate::generated::{
ExprBytesLiteral, ExprDict, ExprFString, ExprList, ExprName, ExprSet, ExprStringLiteral, ExprBytesLiteral, ExprDict, ExprFString, ExprList, ExprName, ExprSet, ExprStringLiteral,
ExprTuple, ExprTuple, StmtClassDef,
}; };
use std::borrow::Cow; use std::borrow::Cow;
use std::fmt; use std::fmt;
@ -17,13 +17,13 @@ use itertools::Itertools;
use ruff_text_size::{Ranged, TextLen, TextRange, TextSize}; use ruff_text_size::{Ranged, TextLen, TextRange, TextSize};
use crate::str_prefix::{AnyStringPrefix, ByteStringPrefix, FStringPrefix, StringLiteralPrefix};
use crate::{ use crate::{
int, int,
name::Name, name::Name,
str::{Quote, TripleQuotes}, str::{Quote, TripleQuotes},
str_prefix::{AnyStringPrefix, ByteStringPrefix, FStringPrefix, StringLiteralPrefix}, Expr, ExprRef, FStringElement, LiteralExpressionRef, OperatorPrecedence, Pattern, Stmt,
ExceptHandler, Expr, ExprRef, FStringElement, LiteralExpressionRef, OperatorPrecedence, TypeParam,
Pattern, Stmt, TypeParam,
}; };
/// See also [Module](https://docs.python.org/3/library/ast.html#ast.Module) /// See also [Module](https://docs.python.org/3/library/ast.html#ast.Module)
@ -40,95 +40,6 @@ pub struct ModExpression {
pub body: Box<Expr>, pub body: Box<Expr>,
} }
/// An AST node used to represent a IPython escape command at the statement level.
///
/// For example,
/// ```python
/// %matplotlib inline
/// ```
///
/// ## Terminology
///
/// Escape commands are special IPython syntax which starts with a token to identify
/// the escape kind followed by the command value itself. [Escape kind] are the kind
/// of escape commands that are recognized by the token: `%`, `%%`, `!`, `!!`,
/// `?`, `??`, `/`, `;`, and `,`.
///
/// Help command (or Dynamic Object Introspection as it's called) are the escape commands
/// of the kind `?` and `??`. For example, `?str.replace`. Help end command are a subset
/// of Help command where the token can be at the end of the line i.e., after the value.
/// For example, `str.replace?`.
///
/// Here's where things get tricky. I'll divide the help end command into two types for
/// better understanding:
/// 1. Strict version: The token is _only_ at the end of the line. For example,
/// `str.replace?` or `str.replace??`.
/// 2. Combined version: Along with the `?` or `??` token, which are at the end of the
/// line, there are other escape kind tokens that are present at the start as well.
/// For example, `%matplotlib?` or `%%timeit?`.
///
/// Priority comes into picture for the "Combined version" mentioned above. How do
/// we determine the escape kind if there are tokens on both side of the value, i.e., which
/// token to choose? The Help end command always takes priority over any other token which
/// means that if there is `?`/`??` at the end then that is used to determine the kind.
/// For example, in `%matplotlib?` the escape kind is determined using the `?` token
/// instead of `%` token.
///
/// ## Syntax
///
/// `<IpyEscapeKind><Command value>`
///
/// The simplest form is an escape kind token followed by the command value. For example,
/// `%matplotlib inline`, `/foo`, `!pwd`, etc.
///
/// `<Command value><IpyEscapeKind ("?" or "??")>`
///
/// The help end escape command would be the reverse of the above syntax. Here, the
/// escape kind token can only be either `?` or `??` and it is at the end of the line.
/// For example, `str.replace?`, `math.pi??`, etc.
///
/// `<IpyEscapeKind><Command value><EscapeKind ("?" or "??")>`
///
/// The final syntax is the combined version of the above two. For example, `%matplotlib?`,
/// `%%timeit??`, etc.
///
/// [Escape kind]: IpyEscapeKind
#[derive(Clone, Debug, PartialEq)]
pub struct StmtIpyEscapeCommand {
pub range: TextRange,
pub kind: IpyEscapeKind,
pub value: Box<str>,
}
/// See also [FunctionDef](https://docs.python.org/3/library/ast.html#ast.FunctionDef) and
/// [AsyncFunctionDef](https://docs.python.org/3/library/ast.html#ast.AsyncFunctionDef).
///
/// This type differs from the original Python AST, as it collapses the
/// synchronous and asynchronous variants into a single type.
#[derive(Clone, Debug, PartialEq)]
pub struct StmtFunctionDef {
pub range: TextRange,
pub is_async: bool,
pub decorator_list: Vec<Decorator>,
pub name: Identifier,
pub type_params: Option<Box<TypeParams>>,
pub parameters: Box<Parameters>,
pub returns: Option<Box<Expr>>,
pub body: Vec<Stmt>,
}
/// See also [ClassDef](https://docs.python.org/3/library/ast.html#ast.ClassDef)
#[derive(Clone, Debug, PartialEq)]
pub struct StmtClassDef {
pub range: TextRange,
pub decorator_list: Vec<Decorator>,
pub name: Identifier,
pub type_params: Option<Box<TypeParams>>,
// TODO: can remove?
pub arguments: Option<Box<Arguments>>,
pub body: Vec<Stmt>,
}
impl StmtClassDef { impl StmtClassDef {
/// Return an iterator over the bases of the class. /// Return an iterator over the bases of the class.
pub fn bases(&self) -> &[Expr] { pub fn bases(&self) -> &[Expr] {
@ -147,90 +58,6 @@ impl StmtClassDef {
} }
} }
/// See also [Return](https://docs.python.org/3/library/ast.html#ast.Return)
#[derive(Clone, Debug, PartialEq)]
pub struct StmtReturn {
pub range: TextRange,
pub value: Option<Box<Expr>>,
}
/// See also [Delete](https://docs.python.org/3/library/ast.html#ast.Delete)
#[derive(Clone, Debug, PartialEq)]
pub struct StmtDelete {
pub range: TextRange,
pub targets: Vec<Expr>,
}
/// See also [TypeAlias](https://docs.python.org/3/library/ast.html#ast.TypeAlias)
#[derive(Clone, Debug, PartialEq)]
pub struct StmtTypeAlias {
pub range: TextRange,
pub name: Box<Expr>,
pub type_params: Option<TypeParams>,
pub value: Box<Expr>,
}
/// See also [Assign](https://docs.python.org/3/library/ast.html#ast.Assign)
#[derive(Clone, Debug, PartialEq)]
pub struct StmtAssign {
pub range: TextRange,
pub targets: Vec<Expr>,
pub value: Box<Expr>,
}
/// See also [AugAssign](https://docs.python.org/3/library/ast.html#ast.AugAssign)
#[derive(Clone, Debug, PartialEq)]
pub struct StmtAugAssign {
pub range: TextRange,
pub target: Box<Expr>,
pub op: Operator,
pub value: Box<Expr>,
}
/// See also [AnnAssign](https://docs.python.org/3/library/ast.html#ast.AnnAssign)
#[derive(Clone, Debug, PartialEq)]
pub struct StmtAnnAssign {
pub range: TextRange,
pub target: Box<Expr>,
pub annotation: Box<Expr>,
pub value: Option<Box<Expr>>,
pub simple: bool,
}
/// See also [For](https://docs.python.org/3/library/ast.html#ast.For) and
/// [AsyncFor](https://docs.python.org/3/library/ast.html#ast.AsyncFor).
///
/// This type differs from the original Python AST, as it collapses the
/// synchronous and asynchronous variants into a single type.
#[derive(Clone, Debug, PartialEq)]
pub struct StmtFor {
pub range: TextRange,
pub is_async: bool,
pub target: Box<Expr>,
pub iter: Box<Expr>,
pub body: Vec<Stmt>,
pub orelse: Vec<Stmt>,
}
/// See also [While](https://docs.python.org/3/library/ast.html#ast.While) and
/// [AsyncWhile](https://docs.python.org/3/library/ast.html#ast.AsyncWhile).
#[derive(Clone, Debug, PartialEq)]
pub struct StmtWhile {
pub range: TextRange,
pub test: Box<Expr>,
pub body: Vec<Stmt>,
pub orelse: Vec<Stmt>,
}
/// See also [If](https://docs.python.org/3/library/ast.html#ast.If)
#[derive(Clone, Debug, PartialEq)]
pub struct StmtIf {
pub range: TextRange,
pub test: Box<Expr>,
pub body: Vec<Stmt>,
pub elif_else_clauses: Vec<ElifElseClause>,
}
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub struct ElifElseClause { pub struct ElifElseClause {
pub range: TextRange, pub range: TextRange,
@ -238,110 +65,6 @@ pub struct ElifElseClause {
pub body: Vec<Stmt>, pub body: Vec<Stmt>,
} }
/// See also [With](https://docs.python.org/3/library/ast.html#ast.With) and
/// [AsyncWith](https://docs.python.org/3/library/ast.html#ast.AsyncWith).
///
/// This type differs from the original Python AST, as it collapses the
/// synchronous and asynchronous variants into a single type.
#[derive(Clone, Debug, PartialEq)]
pub struct StmtWith {
pub range: TextRange,
pub is_async: bool,
pub items: Vec<WithItem>,
pub body: Vec<Stmt>,
}
/// See also [Match](https://docs.python.org/3/library/ast.html#ast.Match)
#[derive(Clone, Debug, PartialEq)]
pub struct StmtMatch {
pub range: TextRange,
pub subject: Box<Expr>,
pub cases: Vec<MatchCase>,
}
/// See also [Raise](https://docs.python.org/3/library/ast.html#ast.Raise)
#[derive(Clone, Debug, PartialEq)]
pub struct StmtRaise {
pub range: TextRange,
pub exc: Option<Box<Expr>>,
pub cause: Option<Box<Expr>>,
}
/// See also [Try](https://docs.python.org/3/library/ast.html#ast.Try) and
/// [TryStar](https://docs.python.org/3/library/ast.html#ast.TryStar)
#[derive(Clone, Debug, PartialEq)]
pub struct StmtTry {
pub range: TextRange,
pub body: Vec<Stmt>,
pub handlers: Vec<ExceptHandler>,
pub orelse: Vec<Stmt>,
pub finalbody: Vec<Stmt>,
pub is_star: bool,
}
/// See also [Assert](https://docs.python.org/3/library/ast.html#ast.Assert)
#[derive(Clone, Debug, PartialEq)]
pub struct StmtAssert {
pub range: TextRange,
pub test: Box<Expr>,
pub msg: Option<Box<Expr>>,
}
/// See also [Import](https://docs.python.org/3/library/ast.html#ast.Import)
#[derive(Clone, Debug, PartialEq)]
pub struct StmtImport {
pub range: TextRange,
pub names: Vec<Alias>,
}
/// See also [ImportFrom](https://docs.python.org/3/library/ast.html#ast.ImportFrom)
#[derive(Clone, Debug, PartialEq)]
pub struct StmtImportFrom {
pub range: TextRange,
pub module: Option<Identifier>,
pub names: Vec<Alias>,
pub level: u32,
}
/// See also [Global](https://docs.python.org/3/library/ast.html#ast.Global)
#[derive(Clone, Debug, PartialEq)]
pub struct StmtGlobal {
pub range: TextRange,
pub names: Vec<Identifier>,
}
/// See also [Nonlocal](https://docs.python.org/3/library/ast.html#ast.Nonlocal)
#[derive(Clone, Debug, PartialEq)]
pub struct StmtNonlocal {
pub range: TextRange,
pub names: Vec<Identifier>,
}
/// See also [Expr](https://docs.python.org/3/library/ast.html#ast.Expr)
#[derive(Clone, Debug, PartialEq)]
pub struct StmtExpr {
pub range: TextRange,
pub value: Box<Expr>,
}
/// See also [Pass](https://docs.python.org/3/library/ast.html#ast.Pass)
#[derive(Clone, Debug, PartialEq)]
pub struct StmtPass {
pub range: TextRange,
}
/// See also [Break](https://docs.python.org/3/library/ast.html#ast.Break)
#[derive(Clone, Debug, PartialEq)]
pub struct StmtBreak {
pub range: TextRange,
}
/// See also [Continue](https://docs.python.org/3/library/ast.html#ast.Continue)
#[derive(Clone, Debug, PartialEq)]
pub struct StmtContinue {
pub range: TextRange,
}
impl Expr { impl Expr {
/// Returns `true` if the expression is a literal expression. /// Returns `true` if the expression is a literal expression.
/// ///
@ -3366,9 +3089,6 @@ impl From<bool> for Singleton {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
#[allow(clippy::wildcard_imports)]
use super::*;
use crate::generated::*; use crate::generated::*;
use crate::Mod; use crate::Mod;
@ -3380,8 +3100,7 @@ mod tests {
assert!(std::mem::size_of::<StmtClassDef>() <= 104); assert!(std::mem::size_of::<StmtClassDef>() <= 104);
assert!(std::mem::size_of::<StmtTry>() <= 112); assert!(std::mem::size_of::<StmtTry>() <= 112);
assert!(std::mem::size_of::<Mod>() <= 32); assert!(std::mem::size_of::<Mod>() <= 32);
// 96 for Rustc < 1.76 assert!(matches!(std::mem::size_of::<Pattern>(), 88));
assert!(matches!(std::mem::size_of::<Pattern>(), 88 | 96));
assert_eq!(std::mem::size_of::<Expr>(), 64); assert_eq!(std::mem::size_of::<Expr>(), 64);
assert_eq!(std::mem::size_of::<ExprAttribute>(), 56); assert_eq!(std::mem::size_of::<ExprAttribute>(), 56);
@ -3395,8 +3114,7 @@ mod tests {
assert_eq!(std::mem::size_of::<ExprDict>(), 32); assert_eq!(std::mem::size_of::<ExprDict>(), 32);
assert_eq!(std::mem::size_of::<ExprDictComp>(), 48); assert_eq!(std::mem::size_of::<ExprDictComp>(), 48);
assert_eq!(std::mem::size_of::<ExprEllipsisLiteral>(), 8); assert_eq!(std::mem::size_of::<ExprEllipsisLiteral>(), 8);
// 56 for Rustc < 1.76 assert!(matches!(std::mem::size_of::<ExprFString>(), 48));
assert!(matches!(std::mem::size_of::<ExprFString>(), 48 | 56));
assert_eq!(std::mem::size_of::<ExprGenerator>(), 48); assert_eq!(std::mem::size_of::<ExprGenerator>(), 48);
assert_eq!(std::mem::size_of::<ExprIf>(), 32); assert_eq!(std::mem::size_of::<ExprIf>(), 32);
assert_eq!(std::mem::size_of::<ExprIpyEscapeCommand>(), 32); assert_eq!(std::mem::size_of::<ExprIpyEscapeCommand>(), 32);