Skip to content

Commit 80c4b44

Browse files
tausbnCopilot
andcommitted
unified: Emit base types from inheritance clauses
Map a nominal type's inheritance clause (`class C: Base, Proto`, and likewise for enum/struct/protocol/extension) to `base_type` children on the `class_like_declaration`, one per inherited type. The tree-sitter path dropped these (no corpus target had a `base_type`) and the mapping matched that for parity; swift-syntax exposes the clause cleanly. Adds a focused `class-with-multiple-base-types` corpus case and updates `class-inheritance` to witness the restored base types. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 08024d8 commit 80c4b44

4 files changed

Lines changed: 97 additions & 11 deletions

File tree

unified/extractor/src/languages/swift/swift.rs

Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1028,50 +1028,73 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
10281028
// (swift-syntax represents `#selector`/`#keyPath` and other macro
10291029
// expansions uniformly as a `macroExpansionExpr`).
10301030
rule!((macroExpansionExpr) => (unsupported_node)),
1031-
// PARITY(tree-sitter): a nominal type's `inheritanceClause` (`: Base,
1032-
// Proto`) is not emitted as a `base_type` — the tree-sitter path drops
1033-
// it (no corpus target has a `base_type`). swift-syntax exposes it
1034-
// cleanly, so emitting `base_type` is a correctness improvement to make
1035-
// once tree-sitter is retired. Each declaration keyword gets its own
1036-
// rule; the bodies are identical but for the keyword.
1031+
// A nominal type's `inheritanceClause` (`: Base, Proto`) becomes a list
1032+
// of `base_type`s, one per inherited type. The tree-sitter path dropped
1033+
// it (no corpus target had a `base_type`) and the mapping matched that
1034+
// for parity; swift-syntax exposes it cleanly. Each declaration keyword
1035+
// gets its own rule; the bodies are identical but for the keyword.
10371036
// Class declaration with body containing members
10381037
rule!(
1039-
(classDecl classKeyword: @kind modifiers: _* @mods name: @name memberBlock: (memberBlock members: _* @members))
1038+
(classDecl
1039+
classKeyword: @kind
1040+
modifiers: _* @mods
1041+
name: @name
1042+
inheritanceClause: (inheritanceClause inheritedTypes: (inheritedType type: @bases)*)?
1043+
memberBlock: (memberBlock members: _* @members))
10401044
=>
10411045
(class_like_declaration
10421046
modifier: (modifier #{kind})
10431047
modifier: {mods}
10441048
name: (identifier #{name})
1049+
base_type: {bases.into_iter().map(|ty| tree!((base_type type: {ty})))}
10451050
member: {members})
10461051
),
10471052
// Enum class declaration: same as a regular class but with an enum body.
10481053
rule!(
1049-
(enumDecl enumKeyword: @kind modifiers: _* @mods name: @name memberBlock: (memberBlock members: _* @members))
1054+
(enumDecl
1055+
enumKeyword: @kind
1056+
modifiers: _* @mods
1057+
name: @name
1058+
inheritanceClause: (inheritanceClause inheritedTypes: (inheritedType type: @bases)*)?
1059+
memberBlock: (memberBlock members: _* @members))
10501060
=>
10511061
(class_like_declaration
10521062
modifier: (modifier #{kind})
10531063
modifier: {mods}
10541064
name: (identifier #{name})
1065+
base_type: {bases.into_iter().map(|ty| tree!((base_type type: {ty})))}
10551066
member: {members})
10561067
),
10571068
// A `struct` declaration.
10581069
rule!(
1059-
(structDecl structKeyword: @kind modifiers: _* @mods name: @name memberBlock: (memberBlock members: _* @members))
1070+
(structDecl
1071+
structKeyword: @kind
1072+
modifiers: _* @mods
1073+
name: @name
1074+
inheritanceClause: (inheritanceClause inheritedTypes: (inheritedType type: @bases)*)?
1075+
memberBlock: (memberBlock members: _* @members))
10601076
=>
10611077
(class_like_declaration
10621078
modifier: (modifier #{kind})
10631079
modifier: {mods}
10641080
name: (identifier #{name})
1081+
base_type: {bases.into_iter().map(|ty| tree!((base_type type: {ty})))}
10651082
member: {members})
10661083
),
10671084
// Protocol declaration
10681085
rule!(
1069-
(protocolDecl protocolKeyword: @kind modifiers: _* @mods name: @name memberBlock: (memberBlock members: _* @members))
1086+
(protocolDecl
1087+
protocolKeyword: @kind
1088+
modifiers: _* @mods
1089+
name: @name
1090+
inheritanceClause: (inheritanceClause inheritedTypes: (inheritedType type: @bases)*)?
1091+
memberBlock: (memberBlock members: _* @members))
10701092
=>
10711093
(class_like_declaration
10721094
modifier: (modifier #{kind})
10731095
modifier: {mods}
10741096
name: (identifier #{name})
1097+
base_type: {bases.into_iter().map(|ty| tree!((base_type type: {ty})))}
10751098
member: {members})
10761099
),
10771100
// An `extension Foo { … }` is likewise a `class_like_declaration`, named
@@ -1080,12 +1103,18 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
10801103
// a `memberType`) name the declaration just like simple ones, matching the
10811104
// old tree-sitter `user_type` behaviour.
10821105
rule!(
1083-
(extensionDecl extensionKeyword: @kind modifiers: _* @mods extendedType: @@name memberBlock: (memberBlock members: _* @members))
1106+
(extensionDecl
1107+
extensionKeyword: @kind
1108+
modifiers: _* @mods
1109+
extendedType: @@name
1110+
inheritanceClause: (inheritanceClause inheritedTypes: (inheritedType type: @bases)*)?
1111+
memberBlock: (memberBlock members: _* @members))
10841112
=>
10851113
(class_like_declaration
10861114
modifier: (modifier #{kind})
10871115
modifier: {mods}
10881116
name: (identifier #{name})
1117+
base_type: {bases.into_iter().map(|ty| tree!((base_type type: {ty})))}
10891118
member: {members})
10901119
),
10911120
// A member of a type declaration unwraps to the contained declaration.

unified/extractor/tests/corpus/swift/types/class-inheritance.output

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,8 @@ top_level
3535
class_like_declaration
3636
modifier: modifier "class"
3737
name: identifier "Dog"
38+
base_type:
39+
base_type
40+
type:
41+
named_type_expr
42+
name: identifier "Animal"
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
class Button: Control, Drawable {}
2+
3+
---
4+
5+
sourceFile
6+
endOfFileToken: endOfFile
7+
statements:
8+
codeBlockItem
9+
item:
10+
classDecl
11+
attributes:
12+
name: identifier "Button"
13+
inheritanceClause:
14+
inheritanceClause
15+
colon: :
16+
inheritedTypes:
17+
inheritedType
18+
trailingComma: ,
19+
type:
20+
identifierType
21+
name: identifier "Control"
22+
inheritedType
23+
type:
24+
identifierType
25+
name: identifier "Drawable"
26+
memberBlock:
27+
memberBlock
28+
leftBrace: {
29+
rightBrace: }
30+
members:
31+
modifiers:
32+
classKeyword: class
33+
34+
---
35+
36+
top_level
37+
body:
38+
block
39+
stmt:
40+
class_like_declaration
41+
modifier: modifier "class"
42+
name: identifier "Button"
43+
base_type:
44+
base_type
45+
type:
46+
named_type_expr
47+
name: identifier "Control"
48+
base_type
49+
type:
50+
named_type_expr
51+
name: identifier "Drawable"
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
class Button: Control, Drawable {}

0 commit comments

Comments
 (0)