Skip to content

Commit f479aec

Browse files
committed
Auto generate visit_source_order
1 parent b662c3f commit f479aec

File tree

37 files changed

+1558
-1412
lines changed

37 files changed

+1558
-1412
lines changed

crates/ruff_python_ast/ast.toml

Lines changed: 47 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@
3737
# derives:
3838
# List of derives to add to the syntax node struct. Clone, Debug, PartialEq are added by default.
3939
#
40+
# custom_source_order:
41+
# A boolean that specifies if this node has a custom source order visitor implementation.
42+
# generation of visit_source_order will be skipped for this node.
43+
#
4044
# fields:
4145
# List of fields in the syntax node struct. Each field is a table with the
4246
# following keys:
@@ -48,6 +52,7 @@
4852
# * `Expr*` - A vector of Expr.
4953
# * `&Expr*` - A boxed slice of Expr.
5054
# These properties cannot be nested, for example we cannot create a vector of option types.
55+
# * skip_source_order - (Optional) if this field should be skipped during source order visit.
5156
#
5257
# variant:
5358
# The name of the enum variant for this syntax node. Defaults to the node
@@ -57,9 +62,13 @@
5762
anynode_is_label = "module"
5863
doc = "See also [mod](https://docs.python.org/3/library/ast.html#ast.mod)"
5964

60-
[Mod.nodes]
61-
ModModule = {}
62-
ModExpression = {}
65+
[Mod.nodes.ModModule]
66+
doc = "See also [Module](https://docs.python.org/3/library/ast.html#ast.Module)"
67+
fields = [{ name = "body", type = "Stmt*" }]
68+
69+
[Mod.nodes.ModExpression]
70+
doc = "See also [Module](https://docs.python.org/3/library/ast.html#ast.Module)"
71+
fields = [{ name = "body", type = "Box<Expr>" }]
6372

6473
[Stmt]
6574
add_suffix_to_is_methods = true
@@ -72,13 +81,12 @@ and [AsyncFunctionDef](https://docs.python.org/3/library/ast.html#ast.AsyncFunct
7281
7382
This type differs from the original Python AST, as it collapses the synchronous and asynchronous variants into a single type."""
7483
fields = [
75-
{ name = "is_async", type = "bool" },
84+
{ name = "is_async", type = "bool", skip_source_order = true },
7685
{ name = "decorator_list", type = "Decorator*" },
7786
{ name = "name", type = "Identifier" },
7887
{ name = "type_params", type = "Box<crate::TypeParams>?" },
7988
{ name = "parameters", type = "Box<crate::Parameters>" },
80-
81-
{ name = "returns", type = "Expr?" },
89+
{ name = "returns", type = "Expr?", is_annotation = true },
8290
{ name = "body", type = "Stmt*" },
8391
]
8492

@@ -100,6 +108,7 @@ fields = [{ name = "value", type = "Expr?" }]
100108
doc = "See also [Delete](https://docs.python.org/3/library/ast.html#ast.Delete)"
101109
fields = [{ name = "targets", type = "Expr*" }]
102110

111+
103112
[Stmt.nodes.StmtTypeAlias]
104113
doc = "See also [TypeAlias](https://docs.python.org/3/library/ast.html#ast.TypeAlias)"
105114
fields = [
@@ -129,7 +138,7 @@ fields = [
129138
{ name = "target", type = "Expr" },
130139
{ name = "annotation", type = "Expr" },
131140
{ name = "value", type = "Expr?" },
132-
{ name = "simple", type = "bool" },
141+
{ name = "simple", type = "bool", skip_source_order = true },
133142
]
134143

135144
[Stmt.nodes.StmtFor]
@@ -138,7 +147,7 @@ and [AsyncFor](https://docs.python.org/3/library/ast.html#ast.AsyncFor).
138147
139148
This type differs from the original Python AST, as it collapses the synchronous and asynchronous variants into a single type."""
140149
fields = [
141-
{ name = "is_async", type = "bool" },
150+
{ name = "is_async", type = "bool", skip_source_order = true },
142151
{ name = "target", type = "Expr" },
143152
{ name = "iter", type = "Expr" },
144153
{ name = "body", type = "Stmt*" },
@@ -154,6 +163,7 @@ fields = [
154163
{ name = "orelse", type = "Stmt*" },
155164
]
156165

166+
157167
[Stmt.nodes.StmtIf]
158168
doc = "See also [If](https://docs.python.org/3/library/ast.html#ast.If)"
159169
fields = [
@@ -169,7 +179,7 @@ and [AsyncWith](https://docs.python.org/3/library/ast.html#ast.AsyncWith).
169179
170180
This type differs from the original Python AST, as it collapses the synchronous and asynchronous variants into a single type."""
171181
fields = [
172-
{ name = "is_async", type = "bool" },
182+
{ name = "is_async", type = "bool", skip_source_order = true },
173183
{ name = "items", type = "WithItem*" },
174184
{ name = "body", type = "Stmt*" },
175185
]
@@ -193,23 +203,25 @@ fields = [
193203
{ name = "handlers", type = "ExceptHandler*" },
194204
{ name = "orelse", type = "Stmt*" },
195205
{ name = "finalbody", type = "Stmt*" },
196-
{ name = "is_star", type = "bool" },
206+
{ name = "is_star", type = "bool", skip_source_order = true },
197207
]
198208

199209
[Stmt.nodes.StmtAssert]
200210
doc = "See also [Assert](https://docs.python.org/3/library/ast.html#ast.Assert)"
201211
fields = [{ name = "test", type = "Expr" }, { name = "msg", type = "Expr?" }]
212+
source_order = ["test", "msg"]
202213

203214
[Stmt.nodes.StmtImport]
204215
doc = "See also [Import](https://docs.python.org/3/library/ast.html#ast.Import)"
205216
fields = [{ name = "names", type = "Alias*" }]
217+
source_order = ["names"]
206218

207219
[Stmt.nodes.StmtImportFrom]
208220
doc = "See also [ImportFrom](https://docs.python.org/3/library/ast.html#ast.ImportFrom)"
209221
fields = [
210222
{ name = "module", type = "Identifier?" },
211223
{ name = "names", type = "Alias*" },
212-
{ name = "level", type = "u32" },
224+
{ name = "level", type = "u32", skip_source_order = true },
213225
]
214226

215227
[Stmt.nodes.StmtGlobal]
@@ -293,8 +305,8 @@ The final syntax is the combined version of the above two. For example, `%matplo
293305
[Escape kind]: crate::IpyEscapeKind
294306
"""
295307
fields = [
296-
{ name = "kind", type = "IpyEscapeKind" },
297-
{ name = "value", type = "Box<str>" },
308+
{ name = "kind", type = "IpyEscapeKind", skip_source_order = true },
309+
{ name = "value", type = "Box<str>", skip_source_order = true },
298310
]
299311

300312
[Expr]
@@ -305,6 +317,7 @@ doc = "See also [expr](https://docs.python.org/3/library/ast.html#ast.expr)"
305317
[Expr.nodes.ExprBoolOp]
306318
doc = "See also [BoolOp](https://docs.python.org/3/library/ast.html#ast.BoolOp)"
307319
fields = [{ name = "op", type = "BoolOp" }, { name = "values", type = "Expr*" }]
320+
custom_source_order = true
308321

309322
[Expr.nodes.ExprNamed]
310323
doc = "See also [NamedExpr](https://docs.python.org/3/library/ast.html#ast.NamedExpr)"
@@ -335,8 +348,8 @@ fields = [
335348
[Expr.nodes.ExprIf]
336349
doc = "See also [IfExp](https://docs.python.org/3/library/ast.html#ast.IfExp)"
337350
fields = [
338-
{ name = "test", type = "Expr" },
339351
{ name = "body", type = "Expr" },
352+
{ name = "test", type = "Expr" },
340353
{ name = "orelse", type = "Expr" },
341354
]
342355

@@ -375,7 +388,7 @@ doc = "See also [GeneratorExp](https://docs.python.org/3/library/ast.html#ast.Ge
375388
fields = [
376389
{ name = "elt", type = "Expr" },
377390
{ name = "generators", type = "Comprehension*" },
378-
{ name = "parenthesized", type = "bool" },
391+
{ name = "parenthesized", type = "bool", skip_source_order = true },
379392
]
380393

381394
[Expr.nodes.ExprAwait]
@@ -397,6 +410,8 @@ fields = [
397410
{ name = "ops", type = "&CmpOp*" },
398411
{ name = "comparators", type = "&Expr*" },
399412
]
413+
# The fields must be visited simultaneously
414+
custom_source_order = true
400415

401416
[Expr.nodes.ExprCall]
402417
doc = "See also [Call](https://docs.python.org/3/library/ast.html#ast.Call)"
@@ -415,22 +430,27 @@ it keeps them separate and provide various methods to access the parts.
415430
416431
See also [JoinedStr](https://docs.python.org/3/library/ast.html#ast.JoinedStr)"""
417432
fields = [{ name = "value", type = "FStringValue" }]
433+
source_order = ["value"]
418434

419435
[Expr.nodes.ExprStringLiteral]
420436
doc = """An AST node that represents either a single-part string literal
421437
or an implicitly concatenated string literal."""
422438
fields = [{ name = "value", type = "StringLiteralValue" }]
439+
# Because StringLiteralValue type is an iterator and it's not clear from the type
440+
custom_source_order = true
423441

424442
[Expr.nodes.ExprBytesLiteral]
425443
doc = """An AST node that represents either a single-part bytestring literal
426444
or an implicitly concatenated bytestring literal."""
427445
fields = [{ name = "value", type = "BytesLiteralValue" }]
446+
# Because StringLiteralValue type is an iterator and it's not clear from the type
447+
custom_source_order = true
428448

429449
[Expr.nodes.ExprNumberLiteral]
430-
fields = [{ name = "value", type = "Number" }]
450+
fields = [{ name = "value", type = "Number", skip_source_order = true }]
431451

432452
[Expr.nodes.ExprBooleanLiteral]
433-
fields = [{ name = "value", type = "bool" }]
453+
fields = [{ name = "value", type = "bool", skip_source_order = true }]
434454
derives = ["Default"]
435455

436456
[Expr.nodes.ExprNoneLiteral]
@@ -446,44 +466,44 @@ doc = "See also [Attribute](https://docs.python.org/3/library/ast.html#ast.Attri
446466
fields = [
447467
{ name = "value", type = "Expr" },
448468
{ name = "attr", type = "Identifier" },
449-
{ name = "ctx", type = "ExprContext" },
469+
{ name = "ctx", type = "ExprContext", skip_source_order = true },
450470
]
451471

452472
[Expr.nodes.ExprSubscript]
453473
doc = "See also [Subscript](https://docs.python.org/3/library/ast.html#ast.Subscript)"
454474
fields = [
455475
{ name = "value", type = "Expr" },
456476
{ name = "slice", type = "Expr" },
457-
{ name = "ctx", type = "ExprContext" },
477+
{ name = "ctx", type = "ExprContext", skip_source_order = true },
458478
]
459479

460480
[Expr.nodes.ExprStarred]
461481
doc = "See also [Starred](https://docs.python.org/3/library/ast.html#ast.Starred)"
462482
fields = [
463483
{ name = "value", type = "Expr" },
464-
{ name = "ctx", type = "ExprContext" },
484+
{ name = "ctx", type = "ExprContext", skip_source_order = true },
465485
]
466486

467487
[Expr.nodes.ExprName]
468488
doc = "See also [Name](https://docs.python.org/3/library/ast.html#ast.Name)"
469489
fields = [
470-
{ name = "id", type = "Name" },
471-
{ name = "ctx", type = "ExprContext" },
490+
{ name = "id", type = "Name", skip_source_order = true },
491+
{ name = "ctx", type = "ExprContext", skip_source_order = true },
472492
]
473493

474494
[Expr.nodes.ExprList]
475495
doc = "See also [List](https://docs.python.org/3/library/ast.html#ast.List)"
476496
fields = [
477497
{ name = "elts", type = "Expr*" },
478-
{ name = "ctx", type = "ExprContext" },
498+
{ name = "ctx", type = "ExprContext", skip_source_order = true },
479499
]
480500

481501
[Expr.nodes.ExprTuple]
482502
doc = "See also [Tuple](https://docs.python.org/3/library/ast.html#ast.Tuple)"
483503
fields = [
484504
{ name = "elts", type = "Expr*" },
485-
{ name = "ctx", type = "ExprContext" },
486-
{ name = "parenthesized", type = "bool" },
505+
{ name = "ctx", type = "ExprContext", skip_source_order = true },
506+
{ name = "parenthesized", type = "bool", skip_source_order = true },
487507
]
488508

489509
[Expr.nodes.ExprSlice]
@@ -508,8 +528,8 @@ For more information related to terminology and syntax of escape commands,
508528
see [`StmtIpyEscapeCommand`]."""
509529

510530
fields = [
511-
{ name = "kind", type = "IpyEscapeKind" },
512-
{ name = "value", type = "Box<str>" },
531+
{ name = "kind", type = "IpyEscapeKind", skip_source_order = true },
532+
{ name = "value", type = "Box<str>", skip_source_order = true },
513533
]
514534

515535
[ExceptHandler]

0 commit comments

Comments
 (0)