@@ -27,9 +27,14 @@ struct SwiftContext {
2727 default_value : Option < yeast:: Id > ,
2828 /// Translated outer modifiers (e.g. visibility, attributes) to
2929 /// attach to each child of a flattening outer rule. Set by
30- /// `protocol_property_declaration` (and, later,
31- /// `property_declaration`/`enum_entry`) .
30+ /// `property_declaration`, `enum_entry`, and
31+ /// `protocol_property_declaration` .
3232 outer_modifiers : Vec < yeast:: Id > ,
33+ /// The `let`/`var` binding modifier for a `property_declaration`.
34+ /// Set by `property_declaration`; read by the inner declaration
35+ /// rules (`property_binding` variants, accessor rules) so they
36+ /// emit it as part of the output node's `modifier:` field.
37+ binding_modifier : Option < yeast:: Id > ,
3338 /// True when the current child of a flattening outer rule is not
3439 /// the first one — its inner rule should emit a
3540 /// `chained_declaration` modifier so the original grouping can be
@@ -143,6 +148,12 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
143148 // (`computed_getter`/`computed_setter`/`computed_modify`) builds
144149 // its `accessor_declaration` with `name` and `type` set from the
145150 // start — no schema-invalid intermediate state.
151+ //
152+ // Toggles `ctx.is_chained` per accessor iteration: the first
153+ // accessor inherits the outer rule's chained state (i.e. whether
154+ // this whole property_binding is itself a non-first declarator
155+ // of a containing property_declaration); subsequent accessors
156+ // always emit `chained_declaration`.
146157 manual_rule!(
147158 ( property_binding
148159 name: @pattern
@@ -160,21 +171,29 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
160171 ctx. property_type = translated_ty;
161172
162173 let mut result = Vec :: new( ) ;
163- for acc in & accessors {
164- result. extend( ctx. translate( * acc) ?) ;
174+ for ( i, acc) in accessors. into_iter( ) . enumerate( ) {
175+ if i > 0 {
176+ ctx. is_chained = true ;
177+ }
178+ result. extend( ctx. translate( acc) ?) ;
165179 }
166180 Ok ( result)
167181 }
168182 ) ,
169- // Computed property: shorthand getter (no explicit get/set, just statements) →
170- // a single accessor_declaration with kind "get".
183+ // Computed property: shorthand getter (no explicit get/set, just
184+ // statements) → a single accessor_declaration with kind "get".
185+ // Reads outer modifiers / chained tag from `ctx` (set by the
186+ // outer `property_declaration` rule).
171187 rule!(
172188 ( property_binding
173189 name: ( pattern bound_identifier: @name)
174190 type : _? @ty
175191 computed_value: ( computed_property statement: _* @body) )
176192 =>
177193 ( accessor_declaration
194+ modifier: { ..ctx. binding_modifier}
195+ modifier: { ..ctx. outer_modifiers. clone( ) }
196+ modifier: { ..chained_modifier( & mut ctx) }
178197 name: ( identifier #{ name} )
179198 type : { ..ty}
180199 accessor_kind: ( accessor_kind "get" )
@@ -187,6 +206,10 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
187206 // into `ctx` before translating the observer children so the
188207 // inner `willset_clause` / `didset_clause` rules construct
189208 // valid `accessor_declaration` nodes from the start.
209+ //
210+ // The `variable_declaration` itself inherits the outer rule's
211+ // chained state; observers always get `chained_declaration`
212+ // because they're subsequent outputs of this flattening rule.
190213 manual_rule!(
191214 ( property_binding
192215 name: ( pattern bound_identifier: @name)
@@ -201,13 +224,19 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
201224
202225 let var_decl = tree!(
203226 ( variable_declaration
227+ modifier: { ..ctx. binding_modifier}
228+ modifier: { ..ctx. outer_modifiers. clone( ) }
229+ modifier: { ..chained_modifier( & mut ctx) }
204230 pattern: ( name_pattern identifier: ( identifier #{ name} ) )
205231 type : { ..translated_ty}
206232 value: { ..translated_val} )
207233 ) ;
208234
209235 // Publish the property name for the observer rules.
210236 ctx. property_name = Some ( tree!( ( identifier #{ name} ) ) ) ;
237+ // Observers are subsequent outputs of this flattening
238+ // rule, so they always get `chained_declaration`.
239+ ctx. is_chained = true ;
211240
212241 let mut result = vec![ var_decl] ;
213242 for obs in ws. into_iter( ) . chain( ds) {
@@ -216,45 +245,53 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
216245 Ok ( result)
217246 }
218247 ) ,
219- // property_binding with any pattern name (identifier or destructuring)
248+ // property_binding with any pattern name (identifier or
249+ // destructuring). Reads outer modifiers / chained tag from `ctx`.
220250 rule!(
221251 ( property_binding
222252 name: @pattern
223253 type : _? @ty
224254 value: _? @val)
225255 =>
226256 ( variable_declaration
257+ modifier: { ..ctx. binding_modifier}
258+ modifier: { ..ctx. outer_modifiers. clone( ) }
259+ modifier: { ..chained_modifier( & mut ctx) }
227260 pattern: { pattern}
228261 type : { ..ty}
229262 value: { ..val} )
230263 ) ,
231- // property_declaration: splice declarators (each may translate to multiple nodes —
232- // variable_declaration and/or accessor_declaration), and attach the binding modifier
233- // (let/var) and any outer modifiers to each. All children after the first additionally
234- // get a synthetic chained_declaration modifier so the grouping can be recovered.
235- rule!(
264+ // property_declaration: flatten declarators (each may translate
265+ // to multiple nodes — variable_declaration and/or
266+ // accessor_declaration) and attach the binding modifier
267+ // (let/var), outer modifiers, and `chained_declaration` for
268+ // non-first declarations. Manual rule: publishes
269+ // binding/outer modifiers into `ctx` and translates each
270+ // declarator with `ctx.is_chained` toggled per iteration. The
271+ // inner declaration rules (`property_binding` variants,
272+ // accessor inner rules) read these fields and emit complete
273+ // `modifier:` lists from the start.
274+ manual_rule!(
236275 ( property_declaration
237276 binding: ( value_binding_pattern mutability: @binding_kind)
238277 declarator: _* @decls
239278 ( modifiers) * @mods)
240- =>
241- { ..{
242- let binding_text = ctx. ast. source_text( binding_kind. into( ) ) ;
243- let mod_ids: Vec <usize > = mods. iter( ) . map( |& m| m. into( ) ) . collect( ) ;
244- let decl_ids: Vec <usize > = decls. iter( ) . map( |& d| d. into( ) ) . collect( ) ;
245- for ( i, & decl_id) in decl_ids. iter( ) . enumerate( ) {
246- if i > 0 {
247- let chained = ctx. literal( "modifier" , "chained_declaration" ) ;
248- ctx. prepend_field( decl_id, "modifier" , chained) ;
249- }
250- for & mod_id in mod_ids. iter( ) . rev( ) {
251- ctx. prepend_field( decl_id, "modifier" , mod_id) ;
252- }
253- let binding_mod = ctx. literal( "modifier" , & binding_text) ;
254- ctx. prepend_field( decl_id, "modifier" , binding_mod) ;
279+ {
280+ let binding_text = ctx. ast. source_text( binding_kind. 0 ) ;
281+ ctx. binding_modifier = Some ( ctx. literal( "modifier" , & binding_text) ) ;
282+ let mut modifiers = Vec :: new( ) ;
283+ for m in mods {
284+ modifiers. extend( ctx. translate( m) ?) ;
255285 }
256- decl_ids
257- } }
286+ ctx. outer_modifiers = modifiers;
287+
288+ let mut result = Vec :: new( ) ;
289+ for ( i, decl) in decls. into_iter( ) . enumerate( ) {
290+ ctx. is_chained = i > 0 ;
291+ result. extend( ctx. translate( decl) ?) ;
292+ }
293+ Ok ( result)
294+ }
258295 ) ,
259296 // ---- Enums ----
260297 // enum_type_parameter → parameter (with optional name as pattern).
@@ -996,12 +1033,16 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
9961033 // protocol_property_requirements wrapper — should be consumed by above; fallback
9971034 rule!( ( protocol_property_requirements accessor: _* @accs) => { ..accs} ) ,
9981035 // Computed getter → accessor_declaration (body optional).
999- // Reads `ctx.property_name`/`ctx.property_type` set by the outer
1000- // property_binding manual rule.
1036+ // Reads property name/type from the outer property_binding rule
1037+ // and binding/outer modifiers + chained tag from the outer
1038+ // property_declaration rule.
10011039 rule!(
10021040 ( computed_getter body: ( block statement: _* @body) ?)
10031041 =>
10041042 ( accessor_declaration
1043+ modifier: { ..ctx. binding_modifier}
1044+ modifier: { ..ctx. outer_modifiers. clone( ) }
1045+ modifier: { ..chained_modifier( & mut ctx) }
10051046 name: { ctx. property_name. ok_or( "computed_getter outside property_binding context" ) ?}
10061047 type : { ..ctx. property_type}
10071048 accessor_kind: ( accessor_kind "get" )
@@ -1012,6 +1053,9 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
10121053 ( computed_setter parameter: @param body: ( block statement: _* @body) )
10131054 =>
10141055 ( accessor_declaration
1056+ modifier: { ..ctx. binding_modifier}
1057+ modifier: { ..ctx. outer_modifiers. clone( ) }
1058+ modifier: { ..chained_modifier( & mut ctx) }
10151059 name: { ctx. property_name. ok_or( "computed_setter outside property_binding context" ) ?}
10161060 type : { ..ctx. property_type}
10171061 accessor_kind: ( accessor_kind "set" )
@@ -1023,6 +1067,9 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
10231067 ( computed_setter body: ( block statement: _* @body) ?)
10241068 =>
10251069 ( accessor_declaration
1070+ modifier: { ..ctx. binding_modifier}
1071+ modifier: { ..ctx. outer_modifiers. clone( ) }
1072+ modifier: { ..chained_modifier( & mut ctx) }
10261073 name: { ctx. property_name. ok_or( "computed_setter outside property_binding context" ) ?}
10271074 type : { ..ctx. property_type}
10281075 accessor_kind: ( accessor_kind "set" )
@@ -1033,6 +1080,9 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
10331080 ( computed_modify body: ( block statement: _* @body) )
10341081 =>
10351082 ( accessor_declaration
1083+ modifier: { ..ctx. binding_modifier}
1084+ modifier: { ..ctx. outer_modifiers. clone( ) }
1085+ modifier: { ..chained_modifier( & mut ctx) }
10361086 name: { ctx. property_name. ok_or( "computed_modify outside property_binding context" ) ?}
10371087 type : { ..ctx. property_type}
10381088 accessor_kind: ( accessor_kind "modify" )
@@ -1043,11 +1093,16 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
10431093 // captures the willset/didset clauses directly).
10441094 rule!( ( willset_didset_block _* @clauses) => { ..clauses} ) ,
10451095 // willset clause → accessor_declaration (body optional). Reads
1046- // `ctx.property_name` set by the outer property_binding rule.
1096+ // `ctx.property_name` set by the outer property_binding rule and
1097+ // binding/outer modifiers + chained tag from the outer
1098+ // property_declaration rule.
10471099 rule!(
10481100 ( willset_clause body: ( block statement: _* @body) ?)
10491101 =>
10501102 ( accessor_declaration
1103+ modifier: { ..ctx. binding_modifier}
1104+ modifier: { ..ctx. outer_modifiers. clone( ) }
1105+ modifier: { ..chained_modifier( & mut ctx) }
10511106 name: { ctx. property_name. ok_or( "willset_clause outside property_binding context" ) ?}
10521107 accessor_kind: ( accessor_kind "willSet" )
10531108 body: ( block stmt: { ..body} ) )
@@ -1057,6 +1112,9 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
10571112 ( didset_clause body: ( block statement: _* @body) ?)
10581113 =>
10591114 ( accessor_declaration
1115+ modifier: { ..ctx. binding_modifier}
1116+ modifier: { ..ctx. outer_modifiers. clone( ) }
1117+ modifier: { ..chained_modifier( & mut ctx) }
10601118 name: { ctx. property_name. ok_or( "didset_clause outside property_binding context" ) ?}
10611119 accessor_kind: ( accessor_kind "didSet" )
10621120 body: ( block stmt: { ..body} ) )
0 commit comments