unified: Port type-container declarations to swift-syntax

Retarget the nominal type declarations to the swift-syntax AST, output
unchanged.
`classDecl`/`structDecl`/`enumDecl`/`protocolDecl`/`extensionDecl`
each become a `class_like_declaration` tagged with a modifier naming the
declaration keyword, with members drawn from the `memberBlock`; each
`memberBlockItem` unwraps to its contained declaration. `superExpr` maps
to `super_expr`; `self` needs no rule (swift-syntax models it as an
ordinary `declReferenceExpr`, already a `name_expr`).

Following the tree-sitter path (PARITY), the inheritance clause is not
emitted as a `base_type` (the tree-sitter rule captured it positionally,
but the grammar nests it under a field, so it never actually matched);
swift-syntax exposes it cleanly, so that is a correctness improvement to
make once tree-sitter is retired. The tree-sitter grammar's standalone
`self`, dead modifier (`visibility_modifier`, etc.), key-path, and
inheritance-specifier rules are dropped; `#selector`/`#keyPath` (now a
`macroExpansionExpr`) stays an `unsupported_node`.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Taus
2026-07-20 14:44:51 +00:00
parent 37654b4bcc
commit 8e6651aa9b

View File

@@ -943,26 +943,15 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
imported_expr: {member_chain(&mut ctx, parts)}))
}
),
// ---- Types and classes ----
// Self expression → name_expr
rule!((self_expression) => (name_expr identifier: (identifier "self"))),
// Super expression → super_expr
rule!((super_expression) => (super_expr)),
// Modifiers — unwrap to individual modifier children
rule!((modifiers _* @mods) => modifier* { mods }),
// ---- Types and declarations ----
// A leading attribute (`@objc`) or access/function/member/mutation/
// ownership modifier (swift-syntax models each as a single `declModifier`)
// becomes a `modifier`; its source text is the modifier spelling.
rule!((attribute) @m => (modifier #{m})),
// swift-syntax models every access/function/member/mutation/ownership
// modifier as a single `declModifier`; its source text is the modifier.
rule!((declModifier) @m => (modifier #{m})),
rule!((visibility_modifier) @m => (modifier #{m})),
rule!((function_modifier) @m => (modifier #{m})),
rule!((member_modifier) @m => (modifier #{m})),
rule!((mutation_modifier) @m => (modifier #{m})),
rule!((ownership_modifier) @m => (modifier #{m})),
rule!((property_modifier) @m => (modifier #{m})),
rule!((parameter_modifier) @m => (modifier #{m})),
rule!((inheritance_modifier) @m => (modifier #{m})),
rule!((property_behavior_modifier) @m => (modifier #{m})),
// A `super` expression. (`self` needs no rule: swift-syntax models it as
// an ordinary `declReferenceExpr`, already mapped to a `name_expr`.)
rule!((superExpr) => (super_expr)),
// Type expressions. A generic type applied with explicit arguments
// (`Set<Int>`) is represented opaquely, using the whole source text as
// the name (PARITY(tree-sitter): the generic arguments are not
@@ -1041,77 +1030,71 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
}
),
// Selector expression: `#selector(inner)` -- not yet supported
rule!(
(selector_expression _ @inner)
=>
(unsupported_node)
),
// Key path expressions are currently unsupported.
rule!((key_path_expression) => (unsupported_node)),
// Inheritance specifier → base_type
rule!((inheritance_specifier inherits_from: @ty) => (base_type type: {ty})),
// (swift-syntax represents `#selector`/`#keyPath` and other macro
// expansions uniformly as a `macroExpansionExpr`).
rule!((macroExpansionExpr) => (unsupported_node)),
// PARITY(tree-sitter): a nominal type's `inheritanceClause` (`: Base,
// Proto`) is not emitted as a `base_type` — the tree-sitter path drops
// it (no corpus target has a `base_type`). swift-syntax exposes it
// cleanly, so emitting `base_type` is a correctness improvement to make
// once tree-sitter is retired. Each declaration keyword gets its own
// rule; the bodies are identical but for the keyword.
// Class declaration with body containing members
rule!(
(class_declaration
declaration_kind: @kind
name: @name
body: (class_body member: _* @members)
(inheritance_specifier)* @bases
(modifiers)* @mods)
(classDecl classKeyword: @kind modifiers: _* @mods name: @name memberBlock: (memberBlock members: _* @members))
=>
(class_like_declaration
modifier: (modifier #{kind})
modifier: {mods}
name: (identifier #{name})
base_type: {bases}
member: {members})
),
// Enum class declaration: same as a regular class but with an enum body.
rule!(
(class_declaration
declaration_kind: @kind
name: @name
body: (enum_class_body member: _* @members)
(inheritance_specifier)* @bases
(modifiers)* @mods)
(enumDecl enumKeyword: @kind modifiers: _* @mods name: @name memberBlock: (memberBlock members: _* @members))
=>
(class_like_declaration
modifier: (modifier #{kind})
modifier: {mods}
name: (identifier #{name})
base_type: {bases}
member: {members})
),
// Class declaration with empty body
// A `struct` declaration.
rule!(
(class_declaration
declaration_kind: @kind
name: @name
body: _
(inheritance_specifier)* @bases
(modifiers)* @mods)
(structDecl structKeyword: @kind modifiers: _* @mods name: @name memberBlock: (memberBlock members: _* @members))
=>
(class_like_declaration
modifier: (modifier #{kind})
modifier: {mods}
name: (identifier #{name})
base_type: {bases})
member: {members})
),
// Protocol declaration
rule!(
(protocol_declaration
name: @name
body: (protocol_body member: _* @members)
(inheritance_specifier)* @bases
(modifiers)* @mods)
(protocolDecl protocolKeyword: @kind modifiers: _* @mods name: @name memberBlock: (memberBlock members: _* @members))
=>
(class_like_declaration
modifier: (modifier "protocol")
modifier: (modifier #{kind})
modifier: {mods}
name: (identifier #{name})
base_type: {bases}
member: {members})
),
// An `extension Foo { … }` is likewise a `class_like_declaration`, named
// by the extended type. The extended type is captured opaquely (as its
// source text) so that qualified names (`extension String.Interpolation`,
// a `memberType`) name the declaration just like simple ones, matching the
// old tree-sitter `user_type` behaviour.
rule!(
(extensionDecl extensionKeyword: @kind modifiers: _* @mods extendedType: @@name memberBlock: (memberBlock members: _* @members))
=>
(class_like_declaration
modifier: (modifier #{kind})
modifier: {mods}
name: (identifier #{name})
member: {members})
),
// A member of a type declaration unwraps to the contained declaration.
rule!((memberBlockItem decl: _* @d) => member* { d }),
// Protocol function — return type and body statements both optional.
rule!(
(protocol_function_declaration