@@ -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
/// Returns the child or children that would have existed in place of this
@@ -51,26 +60,60 @@ public struct CompatibilityLayers /*: Sendable*/ {
51
60
52
61
/// Compute and cache compatibility layer information for the given node, unless it is already present.
53
62
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 {
55
80
return
56
81
}
57
82
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 ] ) {
58
101
// The results that will ultimately be saved into the *ByNode dictionaries.
59
102
var vars : [ Child ] = [ ]
60
103
var initSignatures : [ InitSignature ] = [ ]
61
104
62
105
// Temporary working state for the loop.
63
- var children = layoutNode . children
106
+ var children = initialChildren
64
107
var knownVars = Set ( children)
65
108
66
109
func firstIndexOfChild( named targetName: String ) -> Int {
67
110
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) ) ) " )
69
112
}
70
113
return i
71
114
}
72
115
73
- for changeSet in layoutNode . childHistory {
116
+ for changeSet in history {
74
117
var unexpectedChildrenWithNewNames : Set < Child > = [ ]
75
118
76
119
// First pass: Apply the changes explicitly specified in the change set.
@@ -80,12 +123,14 @@ public struct CompatibilityLayers /*: Sendable*/ {
80
123
let replacementChildren = replacementChildren ( for: children [ i] , by: refactoring)
81
124
children. replaceSubrange ( i... i, with: replacementChildren)
82
125
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
+ }
89
134
}
90
135
}
91
136
@@ -108,11 +153,13 @@ public struct CompatibilityLayers /*: Sendable*/ {
108
153
// 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.
109
154
vars += children. filter { knownVars. insert ( $0) . inserted }
110
155
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
+ }
112
160
}
113
161
114
- deprecatedVarsByNode [ node. syntaxNodeKind] = vars
115
- deprecatedInitSignaturesByNode [ node. syntaxNodeKind] = initSignatures
162
+ return ( vars, initSignatures)
116
163
}
117
164
}
118
165
0 commit comments