@@ -18,10 +18,19 @@ public struct CompatibilityLayers /*: Sendable*/ {
18
18
/// Initializer signatures that are needed in the compatibility layer, in the order they ought to appear in the generated file.
19
19
public var deprecatedInitSignaturesByNode : [ SyntaxNodeKind : [ InitSignature ] ] = [ : ]
20
20
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 ] ) {
22
28
for node in nodes {
23
29
realizeLayers ( for: node)
24
30
}
31
+ for trait in traits {
32
+ realizeLayers ( for: trait)
33
+ }
25
34
}
26
35
27
36
private func extractedChildren( in layoutNode: LayoutNode ) -> ArraySlice < Child > {
@@ -70,26 +79,60 @@ public struct CompatibilityLayers /*: Sendable*/ {
70
79
71
80
/// Compute and cache compatibility layer information for the given node, unless it is already present.
72
81
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 {
74
99
return
75
100
}
76
101
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 ] ) {
77
120
// The results that will ultimately be saved into the *ByNode dictionaries.
78
121
var vars : [ Child ] = [ ]
79
122
var initSignatures : [ InitSignature ] = [ ]
80
123
81
124
// Temporary working state for the loop.
82
- var children = layoutNode . children
125
+ var children = initialChildren
83
126
var knownVars = Set ( children)
84
127
85
128
func firstIndexOfChild( named targetName: String ) -> Int {
86
129
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) ) ) " )
88
131
}
89
132
return i
90
133
}
91
134
92
- for changeSet in layoutNode . childHistory {
135
+ for changeSet in history {
93
136
var unexpectedChildrenWithNewNames : Set < Child > = [ ]
94
137
95
138
// First pass: Apply the changes explicitly specified in the change set.
@@ -99,12 +142,14 @@ public struct CompatibilityLayers /*: Sendable*/ {
99
142
let replacementChildren = replacementChildren ( for: children [ i] , by: refactoring)
100
143
children. replaceSubrange ( i... i, with: replacementChildren)
101
144
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
+ }
108
153
}
109
154
}
110
155
@@ -127,11 +172,13 @@ public struct CompatibilityLayers /*: Sendable*/ {
127
172
// 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.
128
173
vars += children. filter { knownVars. insert ( $0) . inserted }
129
174
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
+ }
131
179
}
132
180
133
- deprecatedVarsByNode [ node. syntaxNodeKind] = vars
134
- deprecatedInitSignaturesByNode [ node. syntaxNodeKind] = initSignatures
181
+ return ( vars, initSignatures)
135
182
}
136
183
}
137
184
0 commit comments