@@ -18,10 +18,19 @@ public struct CompatibilityLayers /*: Sendable*/ {
1818 /// Initializer signatures that are needed in the compatibility layer, in the order they ought to appear in the generated file.
1919 public var deprecatedInitSignaturesByNode : [ SyntaxNodeKind : [ InitSignature ] ] = [ : ]
2020
21- internal init ( nodes: [ Node ] ) {
21+ /// Properties that are needed in the compatibility layer, in the order they ought to appear in the generated file.
22+ public var deprecatedVarsByTrait : [ String : [ Child ] ] = [ : ]
23+
24+ /// Initializer signatures that are needed in the compatibility layer, in the order they ought to appear in the generated file.
25+ public var deprecatedInitSignaturesByTrait : [ String : [ InitSignature ] ] = [ : ]
26+
27+ internal init ( nodes: [ Node ] , traits: [ Trait ] ) {
2228 for node in nodes {
2329 realizeLayers ( for: node)
2430 }
31+ for trait in traits {
32+ realizeLayers ( for: trait)
33+ }
2534 }
2635
2736 private func extractedChildren( in layoutNode: LayoutNode ) -> ArraySlice < Child > {
@@ -70,26 +79,60 @@ public struct CompatibilityLayers /*: Sendable*/ {
7079
7180 /// Compute and cache compatibility layer information for the given node, unless it is already present.
7281 private mutating func realizeLayers( for node: Node ) {
73- guard deprecatedVarsByNode [ node. syntaxNodeKind] == nil && deprecatedInitSignaturesByNode [ node. syntaxNodeKind] == nil , let layoutNode = node. layoutNode else {
82+ guard deprecatedVarsByNode [ node. syntaxNodeKind] == nil , let layoutNode = node. layoutNode else {
83+ return
84+ }
85+
86+ let result = computeLayersFor (
87+ typeName: layoutNode. kind. rawValue,
88+ initialChildren: layoutNode. children,
89+ history: layoutNode. childHistory,
90+ areRequirements: false
91+ )
92+
93+ deprecatedVarsByNode [ node. syntaxNodeKind] = result. vars
94+ deprecatedInitSignaturesByNode [ node. syntaxNodeKind] = result. initSignatures
95+ }
96+
97+ private mutating func realizeLayers( for trait: Trait ) {
98+ guard deprecatedVarsByTrait [ trait. traitName] == nil else {
7499 return
75100 }
76101
102+ let result = computeLayersFor (
103+ typeName: trait. traitName,
104+ initialChildren: trait. children,
105+ history: trait. childHistory,
106+ areRequirements: true
107+ )
108+
109+ deprecatedVarsByTrait [ trait. traitName] = result. vars
110+ deprecatedInitSignaturesByTrait [ trait. traitName] = result. initSignatures
111+ }
112+
113+ /// Compute and cache compatibility layer information for the given children.
114+ private mutating func computeLayersFor(
115+ typeName: String ,
116+ initialChildren: [ Child ] ,
117+ history: Child . History ,
118+ areRequirements: Bool
119+ ) -> ( vars: [ Child ] , initSignatures: [ InitSignature ] ) {
77120 // The results that will ultimately be saved into the *ByNode dictionaries.
78121 var vars : [ Child ] = [ ]
79122 var initSignatures : [ InitSignature ] = [ ]
80123
81124 // Temporary working state for the loop.
82- var children = layoutNode . children
125+ var children = initialChildren
83126 var knownVars = Set ( children)
84127
85128 func firstIndexOfChild( named targetName: String ) -> Int {
86129 guard let i = children. firstIndex ( where: { $0. name == targetName } ) else {
87- fatalError ( " couldn't find ' \( targetName) ' in current children of \( node . syntaxNodeKind . rawValue ) : \( String ( reflecting: children. map ( \. name) ) ) " )
130+ fatalError ( " couldn't find ' \( targetName) ' in current children of \( typeName ) : \( String ( reflecting: children. map ( \. name) ) ) " )
88131 }
89132 return i
90133 }
91134
92- for changeSet in layoutNode . childHistory {
135+ for changeSet in history {
93136 var unexpectedChildrenWithNewNames : Set < Child > = [ ]
94137
95138 // First pass: Apply the changes explicitly specified in the change set.
@@ -99,12 +142,14 @@ public struct CompatibilityLayers /*: Sendable*/ {
99142 let replacementChildren = replacementChildren ( for: children [ i] , by: refactoring)
100143 children. replaceSubrange ( i... i, with: replacementChildren)
101144
102- // Mark adjacent unexpected node children whose names have changed too.
103- if currentName != ( replacementChildren. first? . name ?? " " ) {
104- unexpectedChildrenWithNewNames. insert ( children [ i - 1 ] )
105- }
106- if currentName != ( replacementChildren. last? . name ?? " " ) {
107- unexpectedChildrenWithNewNames. insert ( children [ i + replacementChildren. count] )
145+ if !areRequirements {
146+ // Mark adjacent unexpected node children whose names have changed too.
147+ if currentName != ( replacementChildren. first? . name ?? " " ) {
148+ unexpectedChildrenWithNewNames. insert ( children [ i - 1 ] )
149+ }
150+ if currentName != ( replacementChildren. last? . name ?? " " ) {
151+ unexpectedChildrenWithNewNames. insert ( children [ i + replacementChildren. count] )
152+ }
108153 }
109154 }
110155
@@ -127,11 +172,13 @@ public struct CompatibilityLayers /*: Sendable*/ {
127172 // Third pass: Append newly-created children to vars. We do this now so that changes from the first two passes are properly interleaved, preserving source order.
128173 vars += children. filter { knownVars. insert ( $0) . inserted }
129174
130- initSignatures. append ( InitSignature ( children: children) )
175+ // We don't create compatibility layers for protocol requirement inits.
176+ if !areRequirements {
177+ initSignatures. append ( InitSignature ( children: children) )
178+ }
131179 }
132180
133- deprecatedVarsByNode [ node. syntaxNodeKind] = vars
134- deprecatedInitSignaturesByNode [ node. syntaxNodeKind] = initSignatures
181+ return ( vars, initSignatures)
135182 }
136183}
137184
0 commit comments