Skip to content

Commit 2069f4c

Browse files
hvitvedCopilot
andcommitted
Unified: Synthesize implicit Swift initializers
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
1 parent e37391e commit 2069f4c

31 files changed

Lines changed: 1088 additions & 890 deletions

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

Lines changed: 49 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,23 @@ fn chained_modifier(ctx: &mut yeast::build::BuildCtx<'_, SwiftContext>) -> Optio
7272
}
7373
}
7474

75+
fn implicit_parameterless_initializer(
76+
ctx: &mut yeast::build::BuildCtx<'_, SwiftContext>,
77+
members: &[yeast::Id],
78+
) -> Option<yeast::Id> {
79+
let has_explicit_initializer = members.iter().any(|member| {
80+
ctx.ast
81+
.get_node(*member)
82+
.is_some_and(|node| node.kind_name() == "constructor_declaration")
83+
});
84+
(!has_explicit_initializer).then(|| {
85+
tree!((constructor_declaration
86+
modifier: (modifier "generated")
87+
name_node: (identifier "init")
88+
body: (block)))
89+
})
90+
}
91+
7592
/// Combine a list of boolean sub-conditions into a single expression by
7693
/// left-folding with the infix `&&` operator. Used by control-flow
7794
/// rules (`if`, `guard`, `while`, `repeat-while`), which carry one or
@@ -1228,7 +1245,10 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
12281245
=>
12291246
(equality_type_constraint left: {left} right: {right})
12301247
),
1231-
// Class declaration with body containing members
1248+
// Class declaration with body containing members. If the class has no
1249+
// explicit initializer, add a (possibly dead) implicit `init`. The implicit
1250+
// `init` is dead when the class inherits a constructor from its base class,
1251+
// which we cannot check in the extractor.
12321252
rule!(
12331253
(classDecl
12341254
classKeyword: @@kind
@@ -1241,15 +1261,19 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
12411261
genericWhereClause: (genericWhereClause requirements: _* @declaration_constraints)?
12421262
memberBlock: (memberBlock members: _* @members))
12431263
=>
1244-
(class_like_declaration
1245-
modifier: (modifier #{kind})
1246-
modifier: {mods}
1247-
name_node: (identifier #{name})
1248-
type_parameter: {params}
1249-
type_constraint: {parameter_constraints}
1250-
type_constraint: {declaration_constraints}
1251-
base_type: {bases.into_iter().map(|ty| tree!((base_type type: {ty})))}
1252-
member: {members})
1264+
class_like_declaration {
1265+
let implicit_initializer = implicit_parameterless_initializer(&mut ctx, &members);
1266+
tree!((class_like_declaration
1267+
modifier: (modifier #{kind})
1268+
modifier: {mods}
1269+
name_node: (identifier #{name})
1270+
type_parameter: {params}
1271+
type_constraint: {parameter_constraints}
1272+
type_constraint: {declaration_constraints}
1273+
base_type: {bases.into_iter().map(|ty| tree!((base_type type: {ty})))}
1274+
member: {members}
1275+
member: {implicit_initializer}))
1276+
}
12531277
),
12541278
// Enum class declaration: same as a regular class but with an enum body.
12551279
rule!(
@@ -1274,7 +1298,8 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
12741298
base_type: {bases.into_iter().map(|ty| tree!((base_type type: {ty})))}
12751299
member: {members})
12761300
),
1277-
// A `struct` declaration.
1301+
// A `struct` declaration, including an implicit parameter-less `init`
1302+
// when no explicit initializer is present.
12781303
rule!(
12791304
(structDecl
12801305
structKeyword: @@kind
@@ -1287,15 +1312,19 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
12871312
genericWhereClause: (genericWhereClause requirements: _* @declaration_constraints)?
12881313
memberBlock: (memberBlock members: _* @members))
12891314
=>
1290-
(class_like_declaration
1291-
modifier: (modifier #{kind})
1292-
modifier: {mods}
1293-
name_node: (identifier #{name})
1294-
type_parameter: {params}
1295-
type_constraint: {parameter_constraints}
1296-
type_constraint: {declaration_constraints}
1297-
base_type: {bases.into_iter().map(|ty| tree!((base_type type: {ty})))}
1298-
member: {members})
1315+
class_like_declaration {
1316+
let implicit_initializer = implicit_parameterless_initializer(&mut ctx, &members);
1317+
tree!((class_like_declaration
1318+
modifier: (modifier #{kind})
1319+
modifier: {mods}
1320+
name_node: (identifier #{name})
1321+
type_parameter: {params}
1322+
type_constraint: {parameter_constraints}
1323+
type_constraint: {declaration_constraints}
1324+
base_type: {bases.into_iter().map(|ty| tree!((base_type type: {ty})))}
1325+
member: {members}
1326+
member: {implicit_initializer}))
1327+
}
12991328
),
13001329
// Protocol declaration
13011330
rule!(

‎unified/extractor/tests/corpus/swift/control-flow/discard-statement.output‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,7 @@ top_level source="⟨body⟩"
8080
body:
8181
block source="{\n ⟨stmt⟩\n }"
8282
stmt: unsupported_node "discard self" source="discard self"
83+
constructor_declaration source=""
84+
modifier: modifier "generated" source=""
85+
name_node: identifier "init" source=""
86+
body: block source=""

‎unified/extractor/tests/corpus/swift/expressions/super-expression.output‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,10 @@ top_level source="⟨body⟩"
157157
function_declaration source="func ⟨name_node⟩() ⟨body⟩"
158158
name_node: identifier "update" source="update"
159159
body: block "{}" source="{}"
160+
constructor_declaration source=""
161+
modifier: modifier "generated" source=""
162+
name_node: identifier "init" source=""
163+
body: block source=""
160164
class_like_declaration source="⟨modifier⟩ ⟨name_node⟩: ⟨base_type⟩ {\n ⟨member⟩\n}"
161165
modifier: modifier "class" source="class"
162166
name_node: identifier "Derived" source="Derived"
@@ -182,3 +186,7 @@ top_level source="⟨body⟩"
182186
member_access_expr source="⟨base⟩.⟨member_name_node⟩"
183187
base: super_expr "super" source="super"
184188
member_name_node: identifier "update" source="update"
189+
constructor_declaration source=""
190+
modifier: modifier "generated" source=""
191+
name_node: identifier "init" source=""
192+
body: block source=""

‎unified/extractor/tests/corpus/swift/functions/constructor-call-with-type-arguments.output‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,12 +83,22 @@ top_level source="⟨body⟩"
8383
class_like_declaration source="⟨modifier⟩ ⟨name_node⟩ {}"
8484
modifier: modifier "class" source="class"
8585
name_node: identifier "Foo" source="Foo"
86+
member:
87+
constructor_declaration source=""
88+
modifier: modifier "generated" source=""
89+
name_node: identifier "init" source=""
90+
body: block source=""
8691
class_like_declaration source="⟨modifier⟩ ⟨name_node⟩<⟨type_parameter⟩> {}"
8792
modifier: modifier "class" source="class"
8893
name_node: identifier "C" source="C"
8994
type_parameter:
9095
type_parameter source="⟨name_node⟩"
9196
name_node: identifier "T" source="T"
97+
member:
98+
constructor_declaration source=""
99+
modifier: modifier "generated" source=""
100+
name_node: identifier "init" source=""
101+
body: block source=""
92102
variable_declaration source="⟨modifier⟩ ⟨pattern⟩ = ⟨value⟩"
93103
modifier: modifier "let" source="let"
94104
pattern: identifier "x" source="x"

‎unified/extractor/tests/corpus/swift/types/class-function.output‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,7 @@ top_level source="⟨body⟩"
5555
modifier: modifier "class" source="class"
5656
name_node: identifier "make" source="make"
5757
body: block "{}" source="{}"
58+
constructor_declaration source=""
59+
modifier: modifier "generated" source=""
60+
name_node: identifier "init" source=""
61+
body: block source=""

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,8 @@ top_level source="⟨body⟩"
3838
base_type:
3939
base_type source="⟨type⟩"
4040
type: identifier "Animal" source="Animal"
41+
member:
42+
constructor_declaration source=""
43+
modifier: modifier "generated" source=""
44+
name_node: identifier "init" source=""
45+
body: block source=""

‎unified/extractor/tests/corpus/swift/types/class-with-method.output‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,3 +94,7 @@ top_level source="⟨body⟩"
9494
left: identifier "n" source="n"
9595
operator: infix_operator "+=" source="+="
9696
right: int_literal "1" source="1"
97+
constructor_declaration source=""
98+
modifier: modifier "generated" source=""
99+
name_node: identifier "init" source=""
100+
body: block source=""

‎unified/extractor/tests/corpus/swift/types/class-with-multiple-base-types.output‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,8 @@ top_level source="⟨body⟩"
4545
type: identifier "Control" source="Control"
4646
base_type source="⟨type⟩"
4747
type: identifier "Drawable" source="Drawable"
48+
member:
49+
constructor_declaration source=""
50+
modifier: modifier "generated" source=""
51+
name_node: identifier "init" source=""
52+
body: block source=""

‎unified/extractor/tests/corpus/swift/types/class-with-stored-properties.output‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,3 +73,7 @@ top_level source="⟨body⟩"
7373
modifier: modifier "var" source="var"
7474
pattern: identifier "y" source="y"
7575
type: identifier "Int" source="Int"
76+
constructor_declaration source=""
77+
modifier: modifier "generated" source=""
78+
name_node: identifier "init" source=""
79+
body: block source=""

‎unified/extractor/tests/corpus/swift/types/computed-property.output‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,3 +127,7 @@ top_level source="⟨body⟩"
127127
left: identifier "w" source="w"
128128
operator: infix_operator "*" source="*"
129129
right: identifier "h" source="h"
130+
constructor_declaration source=""
131+
modifier: modifier "generated" source=""
132+
name_node: identifier "init" source=""
133+
body: block source=""

0 commit comments

Comments
 (0)