@@ -150,29 +150,44 @@ public class Child: NodeChoiceConvertible {
150
150
/// For any other kind of child nodes, accessing this property crashes.
151
151
public var syntaxChoicesType : TypeSyntax {
152
152
precondition ( kind. isNodeChoices, " Cannot get `syntaxChoicesType` for node that doesn’t have nodeChoices " )
153
- return " \( raw: name . withFirstCharacterUppercased) "
153
+ return " \( raw: newestName . withFirstCharacterUppercased) "
154
154
}
155
155
156
156
/// If this child only has tokens, the type that the generated `TokenSpecSet` should get.
157
157
///
158
158
/// For any other kind of child nodes, accessing this property crashes.
159
159
public var tokenSpecSetType : TypeSyntax {
160
160
precondition ( kind. isToken, " Cannot get `tokenSpecSetType` for node that isn’t a token " )
161
- return " \( raw: name. withFirstCharacterUppercased) Options "
162
- }
163
-
164
- /// The deprecated name of this child that's suitable to be used for variable or enum case names.
165
- public var deprecatedVarName : TokenSyntax ? {
166
- guard let deprecatedName = deprecatedName else {
167
- return nil
168
- }
169
- return . identifier( lowercaseFirstWord ( name: deprecatedName) )
161
+ return " \( raw: newestName. withFirstCharacterUppercased) Options "
170
162
}
171
163
172
164
/// Determines if this child has a deprecated name
173
165
public var hasDeprecatedName : Bool {
174
166
return deprecatedName != nil
175
167
}
168
+
169
+ /// If this child is actually part of another child's history, links back
170
+ /// to that child. Nil if this is the newest version of the child.
171
+ public let newerChild : Child ?
172
+
173
+ /// True if this child was created by a `Refactoring`. Such children are part
174
+ /// of a compatibility layer and are therefore deprecated.
175
+ public var isHistorical : Bool {
176
+ newerChild != nil
177
+ }
178
+
179
+ /// Replaces the nodes in `newerChildPath` with their own `newerChildPath`s,
180
+ /// if any, to form a child path enitrely of non-historical nodes.
181
+ public func makeNewestChild( ) -> Child {
182
+ guard let newerChild else {
183
+ return self
184
+ }
185
+ return newerChild. makeNewestChild ( )
186
+ }
187
+
188
+ private var newestName : String {
189
+ return makeNewestChild ( ) . name
190
+ }
176
191
177
192
/// If the child ends with "token" in the kind, it's considered a token node.
178
193
/// Grab the existing reference to that token from the global list.
@@ -244,19 +259,15 @@ public class Child: NodeChoiceConvertible {
244
259
return AttributeListSyntax ( " @_spi(ExperimentalLanguageFeatures) " ) . with ( \. trailingTrivia, . newline)
245
260
}
246
261
247
- /// If a classification is passed, it specifies the color identifiers in
248
- /// that subtree should inherit for syntax coloring. Must be a member of
249
- /// ``SyntaxClassification``.
250
- /// If `forceClassification` is also set to true, all child nodes (not only
251
- /// identifiers) inherit the syntax classification.
252
262
init (
253
263
name: String ,
254
264
deprecatedName: String ? = nil ,
255
265
kind: ChildKind ,
256
266
experimentalFeature: ExperimentalFeature ? = nil ,
257
267
nameForDiagnostics: String ? = nil ,
258
268
documentation: String ? = nil ,
259
- isOptional: Bool = false
269
+ isOptional: Bool = false ,
270
+ newerChild: Child ? = nil
260
271
) {
261
272
precondition ( name. first? . isLowercase ?? true , " The first letter of a child’s name should be lowercase " )
262
273
precondition (
@@ -265,11 +276,62 @@ public class Child: NodeChoiceConvertible {
265
276
)
266
277
self . name = name
267
278
self . deprecatedName = deprecatedName
279
+ self . newerChild = newerChild
268
280
self . kind = kind
269
281
self . experimentalFeature = experimentalFeature
270
282
self . nameForDiagnostics = nameForDiagnostics
271
283
self . documentationSummary = SwiftSyntax . Trivia. docCommentTrivia ( from: documentation)
272
284
self . documentationAbstract = String ( documentation? . split ( whereSeparator: \. isNewline) . first ?? " " )
273
285
self . isOptional = isOptional
274
286
}
287
+
288
+ /// Create a node that is a copy of the last node in `newerChildPath`, but
289
+ /// with modifications.
290
+ init ( renamingTo replacementName: String ? = nil , newerChild other: Child ) {
291
+ self . name = replacementName ?? other. name
292
+ self . deprecatedName = nil
293
+ self . newerChild = other
294
+ self . kind = other. kind
295
+ self . experimentalFeature = other. experimentalFeature
296
+ self . nameForDiagnostics = other. nameForDiagnostics
297
+ self . documentationSummary = other. documentationSummary
298
+ self . documentationAbstract = other. documentationAbstract
299
+ self . isOptional = other. isOptional
300
+ }
301
+
302
+ /// Create a child for the unexpected nodes between two children (either or
303
+ /// both of which may be `nil`).
304
+ convenience init ( forUnexpectedBetween earlier: Child ? , and later: Child ? , newerChild: Child ? = nil ) {
305
+ let name = switch ( earlier, later) {
306
+ case ( nil , let later? ) :
307
+ " unexpectedBefore \( later. name. withFirstCharacterUppercased) "
308
+ case ( let earlier? , nil ) :
309
+ " unexpectedAfter \( earlier. name. withFirstCharacterUppercased) "
310
+ case ( let earlier? , let later? ) :
311
+ " unexpectedBetween \( earlier. name. withFirstCharacterUppercased) And \( later. name. withFirstCharacterUppercased) "
312
+ case ( nil , nil ) :
313
+ " unexpected "
314
+ }
315
+
316
+ self . init (
317
+ name: name,
318
+ deprecatedName: nil , // deprecation of unexpected nodes is handled in CompatibilityLayers
319
+ kind: . collection( kind: . unexpectedNodes, collectionElementName: name. withFirstCharacterUppercased) ,
320
+ experimentalFeature: earlier? . experimentalFeature ?? later? . experimentalFeature,
321
+ nameForDiagnostics: nil ,
322
+ documentation: nil ,
323
+ isOptional: true ,
324
+ newerChild: newerChild
325
+ )
326
+ }
327
+ }
328
+
329
+ extension Child : Hashable {
330
+ public static func == ( lhs: Child , rhs: Child ) -> Bool {
331
+ lhs === rhs
332
+ }
333
+
334
+ public func hash( into hasher: inout Hasher ) {
335
+ hasher. combine ( ObjectIdentifier ( self ) )
336
+ }
275
337
}
0 commit comments