Skip to content

Commit 1912c4a

Browse files
authored
Merge pull request #22721 from hvitved/hvitved-swift-implicit-init
Unified: Synthesize implicit Swift initializers
2 parents 74211cc + 6f9afe3 commit 1912c4a

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
@@ -1231,7 +1248,10 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
12311248
=>
12321249
(equality_type_constraint left: {left} right: {right})
12331250
),
1234-
// Class declaration with body containing members
1251+
// Class declaration with body containing members. If the class has no
1252+
// explicit initializer, add a (possibly dead) implicit `init`. The implicit
1253+
// `init` is dead when the class inherits a constructor from its base class,
1254+
// which we cannot check in the extractor.
12351255
rule!(
12361256
(classDecl
12371257
classKeyword: @@kind
@@ -1244,15 +1264,19 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
12441264
genericWhereClause: (genericWhereClause requirements: _* @declaration_constraints)?
12451265
memberBlock: (memberBlock members: _* @members))
12461266
=>
1247-
(class_like_declaration
1248-
modifier: (modifier #{kind})
1249-
modifier: {mods}
1250-
name_node: (identifier #{name})
1251-
type_parameter: {params}
1252-
type_constraint: {parameter_constraints}
1253-
type_constraint: {declaration_constraints}
1254-
base_type: {bases.into_iter().map(|ty| tree!((base_type type: {ty})))}
1255-
member: {members})
1267+
class_like_declaration {
1268+
let implicit_initializer = implicit_parameterless_initializer(&mut ctx, &members);
1269+
tree!((class_like_declaration
1270+
modifier: (modifier #{kind})
1271+
modifier: {mods}
1272+
name_node: (identifier #{name})
1273+
type_parameter: {params}
1274+
type_constraint: {parameter_constraints}
1275+
type_constraint: {declaration_constraints}
1276+
base_type: {bases.into_iter().map(|ty| tree!((base_type type: {ty})))}
1277+
member: {members}
1278+
member: {implicit_initializer}))
1279+
}
12561280
),
12571281
// Enum class declaration: same as a regular class but with an enum body.
12581282
rule!(
@@ -1277,7 +1301,8 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
12771301
base_type: {bases.into_iter().map(|ty| tree!((base_type type: {ty})))}
12781302
member: {members})
12791303
),
1280-
// A `struct` declaration.
1304+
// A `struct` declaration, including an implicit parameter-less `init`
1305+
// when no explicit initializer is present.
12811306
rule!(
12821307
(structDecl
12831308
structKeyword: @@kind
@@ -1290,15 +1315,19 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
12901315
genericWhereClause: (genericWhereClause requirements: _* @declaration_constraints)?
12911316
memberBlock: (memberBlock members: _* @members))
12921317
=>
1293-
(class_like_declaration
1294-
modifier: (modifier #{kind})
1295-
modifier: {mods}
1296-
name_node: (identifier #{name})
1297-
type_parameter: {params}
1298-
type_constraint: {parameter_constraints}
1299-
type_constraint: {declaration_constraints}
1300-
base_type: {bases.into_iter().map(|ty| tree!((base_type type: {ty})))}
1301-
member: {members})
1318+
class_like_declaration {
1319+
let implicit_initializer = implicit_parameterless_initializer(&mut ctx, &members);
1320+
tree!((class_like_declaration
1321+
modifier: (modifier #{kind})
1322+
modifier: {mods}
1323+
name_node: (identifier #{name})
1324+
type_parameter: {params}
1325+
type_constraint: {parameter_constraints}
1326+
type_constraint: {declaration_constraints}
1327+
base_type: {bases.into_iter().map(|ty| tree!((base_type type: {ty})))}
1328+
member: {members}
1329+
member: {implicit_initializer}))
1330+
}
13021331
),
13031332
// Protocol declaration
13041333
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)