@@ -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!(
0 commit comments