@@ -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 /// Returns the child or children that would have existed in place of this
@@ -51,26 +60,60 @@ public struct CompatibilityLayers /*: Sendable*/ {
5160
5261 /// Compute and cache compatibility layer information for the given node, unless it is already present.
5362 private mutating func realizeLayers( for node: Node ) {
54- guard deprecatedVarsByNode [ node. syntaxNodeKind] == nil && deprecatedInitSignaturesByNode [ node. syntaxNodeKind] == nil , let layoutNode = node. layoutNode else {
63+ guard deprecatedVarsByNode [ node. syntaxNodeKind] == nil , let layoutNode = node. layoutNode else {
64+ return
65+ }
66+
67+ let result = computeLayersFor (
68+ typeName: layoutNode. kind. rawValue,
69+ initialChildren: layoutNode. children,
70+ history: layoutNode. childHistory,
71+ areRequirements: false
72+ )
73+
74+ deprecatedVarsByNode [ node. syntaxNodeKind] = result. vars
75+ deprecatedInitSignaturesByNode [ node. syntaxNodeKind] = result. initSignatures
76+ }
77+
78+ private mutating func realizeLayers( for trait: Trait ) {
79+ guard deprecatedVarsByTrait [ trait. traitName] == nil else {
5580 return
5681 }
5782
83+ let result = computeLayersFor (
84+ typeName: trait. traitName,
85+ initialChildren: trait. children,
86+ history: trait. childHistory,
87+ areRequirements: true
88+ )
89+
90+ deprecatedVarsByTrait [ trait. traitName] = result. vars
91+ deprecatedInitSignaturesByTrait [ trait. traitName] = result. initSignatures
92+ }
93+
94+ /// Compute and cache compatibility layer information for the given children.
95+ private mutating func computeLayersFor(
96+ typeName: String ,
97+ initialChildren: [ Child ] ,
98+ history: Child . History ,
99+ areRequirements: Bool
100+ ) -> ( vars: [ Child ] , initSignatures: [ InitSignature ] ) {
58101 // The results that will ultimately be saved into the *ByNode dictionaries.
59102 var vars : [ Child ] = [ ]
60103 var initSignatures : [ InitSignature ] = [ ]
61104
62105 // Temporary working state for the loop.
63- var children = layoutNode . children
106+ var children = initialChildren
64107 var knownVars = Set ( children)
65108
66109 func firstIndexOfChild( named targetName: String ) -> Int {
67110 guard let i = children. firstIndex ( where: { $0. name == targetName } ) else {
68- fatalError ( " couldn't find ' \( targetName) ' in current children of \( node . syntaxNodeKind . rawValue ) : \( String ( reflecting: children. map ( \. name) ) ) " )
111+ fatalError ( " couldn't find ' \( targetName) ' in current children of \( typeName ) : \( String ( reflecting: children. map ( \. name) ) ) " )
69112 }
70113 return i
71114 }
72115
73- for changeSet in layoutNode . childHistory {
116+ for changeSet in history {
74117 var unexpectedChildrenWithNewNames : Set < Child > = [ ]
75118
76119 // First pass: Apply the changes explicitly specified in the change set.
@@ -80,12 +123,14 @@ public struct CompatibilityLayers /*: Sendable*/ {
80123 let replacementChildren = replacementChildren ( for: children [ i] , by: refactoring)
81124 children. replaceSubrange ( i... i, with: replacementChildren)
82125
83- // Mark adjacented unexpected node children whose names have changed too.
84- if currentName != ( replacementChildren. first? . name ?? " " ) {
85- unexpectedChildrenWithNewNames. insert ( children [ i - 1 ] )
86- }
87- if currentName != ( replacementChildren. last? . name ?? " " ) {
88- unexpectedChildrenWithNewNames. insert ( children [ i + replacementChildren. count] )
126+ if !areRequirements {
127+ // Mark adjacent unexpected node children whose names have changed too.
128+ if currentName != ( replacementChildren. first? . name ?? " " ) {
129+ unexpectedChildrenWithNewNames. insert ( children [ i - 1 ] )
130+ }
131+ if currentName != ( replacementChildren. last? . name ?? " " ) {
132+ unexpectedChildrenWithNewNames. insert ( children [ i + replacementChildren. count] )
133+ }
89134 }
90135 }
91136
@@ -108,11 +153,13 @@ public struct CompatibilityLayers /*: Sendable*/ {
108153 // 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.
109154 vars += children. filter { knownVars. insert ( $0) . inserted }
110155
111- initSignatures. append ( InitSignature ( children: children) )
156+ // We don't create compatibility layers for protocol requirement inits.
157+ if !areRequirements {
158+ initSignatures. append ( InitSignature ( children: children) )
159+ }
112160 }
113161
114- deprecatedVarsByNode [ node. syntaxNodeKind] = vars
115- deprecatedInitSignaturesByNode [ node. syntaxNodeKind] = initSignatures
162+ return ( vars, initSignatures)
116163 }
117164}
118165
0 commit comments