|
| 1 | +# schemagen |
| 2 | + |
| 3 | +Generates [`unified/extractor/swift_node_types.yml`][schema], the schema that |
| 4 | +describes the shape of the trees produced by `swift_syntax_rs::parse_to_json`. |
| 5 | +The extractor seeds every parse with it, so rule matching never refers to a |
| 6 | +node kind or field that swift-syntax can produce but the schema does not know. |
| 7 | + |
| 8 | +Run it through the script, which stages the sources described below: |
| 9 | + |
| 10 | +```console |
| 11 | +$ unified/scripts/regenerate-node-types.sh |
| 12 | +``` |
| 13 | + |
| 14 | +Do this after changing the pinned swift-syntax version, and read the resulting |
| 15 | +diff: a new or renamed node kind usually means the mapping in |
| 16 | +[`swift.rs`][mapping] needs attention too. |
| 17 | + |
| 18 | +This requires the local Swift toolchain pinned by |
| 19 | +[`.swift-version`](../.swift-version). |
| 20 | + |
| 21 | +## Why the sources are copied in |
| 22 | + |
| 23 | +The schema is derived from `SyntaxSupport`, the module that describes |
| 24 | +swift-syntax's own syntax tree. This is the same description swift-syntax |
| 25 | +generates itself from, and is therefore authoritative in a way that observing |
| 26 | +parser output never would be. The runtime `SwiftSyntax` module is not a |
| 27 | +substitute: its `SyntaxNodeStructure` exposes layout as key paths, without the |
| 28 | +field names, optionality, and base-kind relationships this schema records. |
| 29 | + |
| 30 | +`SyntaxSupport` is awkward to depend on, though. It is a target of |
| 31 | +`CodeGeneration`, a package inside the swift-syntax repository that is |
| 32 | +separate from swift-syntax itself, and it is not one of that package's |
| 33 | +products. SwiftPM can only depend on products, and Bazel's swift-syntax module |
| 34 | +does not export the `CodeGeneration` sources, so neither build system can |
| 35 | +reach it directly. |
| 36 | + |
| 37 | +The regeneration script therefore copies those sources out of the resolved |
| 38 | +swift-syntax checkout into `Sources/SyntaxSupport`, where this package builds |
| 39 | +them as its own. That directory is git-ignored and refreshed on every run, so |
| 40 | +it always matches the pinned version rather than drifting as a stale vendored |
| 41 | +copy would. |
| 42 | + |
| 43 | +For the same reason this package takes swift-syntax as a path dependency on the |
| 44 | +checkout the neighbouring FFI package resolved, rather than declaring a second |
| 45 | +pinned dependency of its own. The schema must describe exactly the |
| 46 | +swift-syntax version linked by `swift-syntax-rs`. |
| 47 | + |
| 48 | +## What is filtered out |
| 49 | + |
| 50 | +The schema describes the JSON the extractor's adapter receives, not |
| 51 | +swift-syntax's tree verbatim, so `main.swift` mirrors what |
| 52 | +[`adapter.rs`][adapter] does: |
| 53 | + |
| 54 | +- Abstract base kinds become `supertypes:` entries rather than node kinds. |
| 55 | +- Collection nodes are dropped, and a collection-typed child is recorded as |
| 56 | + its element kinds, because the adapter elides collections into JSON arrays. |
| 57 | +- `unexpectedBeforeX` and `unexpectedBetweenXAndY` error-recovery children are |
| 58 | + dropped; no rule matches them. This filters on the child name: |
| 59 | + `unexpectedCodeDecl` is a real node kind and is retained. |
| 60 | +- Token-typed children become the synthetic `_token` kind. Only the varying |
| 61 | + token kinds whose text is not implied by the kind, listed in |
| 62 | + `VARYING_TOKEN_KINDS` in `adapter.rs`, are emitted as kinds of their own. |
| 63 | + Fixed tokens are anonymous and keyed by their text, so no rule can name |
| 64 | + them. |
| 65 | + |
| 66 | +Setting `EMIT_SUPERTYPES=0` omits the `supertypes:` section, which can be useful |
| 67 | +when diffing two versions for kind and field changes alone. |
| 68 | + |
| 69 | +[schema]: ../../extractor/swift_node_types.yml |
| 70 | +[mapping]: ../../extractor/src/languages/swift/swift.rs |
| 71 | +[adapter]: ../../extractor/src/languages/swift/adapter.rs |
0 commit comments