Auto-generate AST boilerplate (#15544)
This PR replaces most of the hard-coded AST definitions with a generation script, similar to what happens in `rust_python_formatter`. I've replaced every "rote" definition that I could find, where the content is entirely boilerplate and only depends on what syntax nodes there are and which groups they belong to. This is a pretty massive diff, but it's entirely a refactoring. It should make absolutely no changes to the API or implementation. In particular, this required adding some configuration knobs that let us override default auto-generated names where they don't line up with types that we created previously by hand. ## Test plan There should be no changes outside of the `rust_python_ast` crate, which verifies that there were no API changes as a result of the auto-generation. Aggressive `cargo clippy` and `uvx pre-commit` runs after each commit in the branch. --------- Co-authored-by: Micha Reiser <micha@reiser.io> Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
This commit is contained in:
174
crates/ruff_python_ast/ast.toml
Normal file
174
crates/ruff_python_ast/ast.toml
Normal file
@@ -0,0 +1,174 @@
|
||||
# This file is used by generate.py to autogenerate our Python AST data model.
|
||||
#
|
||||
# We have defined a Rust struct for each syntax node in `src/nodes.rs`. Many of
|
||||
# these nodes belong to groups. For instance, there is a `Stmt` group
|
||||
# consisting of all of the syntax nodes that represent valid Python statements.
|
||||
#
|
||||
# There is a special group named `ungrouped` that contains syntax nodes that do
|
||||
# not belong to any group.
|
||||
#
|
||||
# Each group is defined by two sections below. The `[GROUP]` section defines
|
||||
# options that control the auto-generation for that group. The `[GROUP.nodes]`
|
||||
# section defines which syntax nodes belong to that group. The name of each
|
||||
# entry in the nodes section must match the name of the corresponding Rust
|
||||
# struct. The value of each entry defines options that control the
|
||||
# auto-generation for that syntax node.
|
||||
#
|
||||
# The following group options are available:
|
||||
#
|
||||
# add_suffix_to_is_methods: [true/false]
|
||||
# Controls the name of the is_foo methods of the group's enums. If false (the
|
||||
# default), these methods will use the variant name in snake_case. If true,
|
||||
# then the group prefix will be moved to the end before snake_casing. (That
|
||||
# is, `StmtIf` will become `if_stmt`.)
|
||||
#
|
||||
# anynode_is_label: foo_bar
|
||||
# Controls the name of the AnyNode::foo_bar, AnyNode::is_foo_bar, and
|
||||
# AnyNodeRef::is_foo_bar methods. The default is the group name in
|
||||
# snake_case.
|
||||
#
|
||||
# ref_enum_ty:
|
||||
# The name of the reference enum that we create for this group. The default
|
||||
# is the group name with `Ref` added to the end.
|
||||
#
|
||||
# rustdoc:
|
||||
# A rustdoc comment that is added to the group's enums.
|
||||
#
|
||||
# The following syntax node options are available:
|
||||
#
|
||||
# variant:
|
||||
# The name of the enum variant for this syntax node. Defaults to the node
|
||||
# name with the group prefix removed. (That is, `StmtIf` becomes `If`.)
|
||||
|
||||
[Mod]
|
||||
anynode_is_label = "module"
|
||||
rustdoc = "/// See also [mod](https://docs.python.org/3/library/ast.html#ast.mod)"
|
||||
|
||||
[Mod.nodes]
|
||||
ModModule = {}
|
||||
ModExpression = {}
|
||||
|
||||
[Stmt]
|
||||
add_suffix_to_is_methods = true
|
||||
anynode_is_label = "statement"
|
||||
rustdoc = "/// See also [stmt](https://docs.python.org/3/library/ast.html#ast.stmt)"
|
||||
ref_enum_ty = "StatementRef"
|
||||
|
||||
[Stmt.nodes]
|
||||
StmtFunctionDef = {}
|
||||
StmtClassDef = {}
|
||||
StmtReturn = {}
|
||||
StmtDelete = {}
|
||||
StmtTypeAlias = {}
|
||||
StmtAssign = {}
|
||||
StmtAugAssign = {}
|
||||
StmtAnnAssign = {}
|
||||
StmtFor = {}
|
||||
StmtWhile = {}
|
||||
StmtIf = {}
|
||||
StmtWith = {}
|
||||
StmtMatch = {}
|
||||
StmtRaise = {}
|
||||
StmtTry = {}
|
||||
StmtAssert = {}
|
||||
StmtImport = {}
|
||||
StmtImportFrom = {}
|
||||
StmtGlobal = {}
|
||||
StmtNonlocal = {}
|
||||
StmtExpr = {}
|
||||
StmtPass = {}
|
||||
StmtBreak = {}
|
||||
StmtContinue = {}
|
||||
StmtIpyEscapeCommand = {}
|
||||
|
||||
[Expr]
|
||||
add_suffix_to_is_methods = true
|
||||
anynode_is_label = "expression"
|
||||
rustdoc = "/// See also [expr](https://docs.python.org/3/library/ast.html#ast.expr)"
|
||||
ref_enum_ty = "ExpressionRef"
|
||||
|
||||
[Expr.nodes]
|
||||
ExprBoolOp = {}
|
||||
ExprNamed = {}
|
||||
ExprBinOp = {}
|
||||
ExprUnaryOp = {}
|
||||
ExprLambda = {}
|
||||
ExprIf = {}
|
||||
ExprDict = {}
|
||||
ExprSet = {}
|
||||
ExprListComp = {}
|
||||
ExprSetComp = {}
|
||||
ExprDictComp = {}
|
||||
ExprGenerator = {}
|
||||
ExprAwait = {}
|
||||
ExprYield = {}
|
||||
ExprYieldFrom = {}
|
||||
ExprCompare = {}
|
||||
ExprCall = {}
|
||||
ExprFString = {}
|
||||
ExprStringLiteral = {}
|
||||
ExprBytesLiteral = {}
|
||||
ExprNumberLiteral = {}
|
||||
ExprBooleanLiteral = {}
|
||||
ExprNoneLiteral = {}
|
||||
ExprEllipsisLiteral = {}
|
||||
ExprAttribute = {}
|
||||
ExprSubscript = {}
|
||||
ExprStarred = {}
|
||||
ExprName = {}
|
||||
ExprList = {}
|
||||
ExprTuple = {}
|
||||
ExprSlice = {}
|
||||
ExprIpyEscapeCommand = {}
|
||||
|
||||
[ExceptHandler]
|
||||
rustdoc = "/// See also [excepthandler](https://docs.python.org/3/library/ast.html#ast.excepthandler)"
|
||||
|
||||
[ExceptHandler.nodes]
|
||||
ExceptHandlerExceptHandler = {}
|
||||
|
||||
[FStringElement.nodes]
|
||||
FStringExpressionElement = {variant = "Expression"}
|
||||
FStringLiteralElement = {variant = "Literal"}
|
||||
|
||||
[Pattern]
|
||||
rustdoc = "/// See also [pattern](https://docs.python.org/3/library/ast.html#ast.pattern)"
|
||||
|
||||
[Pattern.nodes]
|
||||
PatternMatchValue = {}
|
||||
PatternMatchSingleton = {}
|
||||
PatternMatchSequence = {}
|
||||
PatternMatchMapping = {}
|
||||
PatternMatchClass = {}
|
||||
PatternMatchStar = {}
|
||||
PatternMatchAs = {}
|
||||
PatternMatchOr = {}
|
||||
|
||||
[TypeParam]
|
||||
rustdoc = "/// See also [type_param](https://docs.python.org/3/library/ast.html#ast.type_param)"
|
||||
|
||||
[TypeParam.nodes]
|
||||
TypeParamTypeVar = {}
|
||||
TypeParamTypeVarTuple = {}
|
||||
TypeParamParamSpec = {}
|
||||
|
||||
[ungrouped.nodes]
|
||||
FStringFormatSpec = {}
|
||||
PatternArguments = {}
|
||||
PatternKeyword = {}
|
||||
Comprehension = {}
|
||||
Arguments = {}
|
||||
Parameters = {}
|
||||
Parameter = {}
|
||||
ParameterWithDefault = {}
|
||||
Keyword = {}
|
||||
Alias = {}
|
||||
WithItem = {}
|
||||
MatchCase = {}
|
||||
Decorator = {}
|
||||
ElifElseClause = {}
|
||||
TypeParams = {}
|
||||
FString = {}
|
||||
StringLiteral = {}
|
||||
BytesLiteral = {}
|
||||
Identifier = {}
|
||||
Reference in New Issue
Block a user