@@ -140,6 +140,19 @@ public class Child: NodeChoiceConvertible {
140140 }
141141 }
142142
143+ /// Should this child be hidden?
144+ ///
145+ /// A hidden child is one that is not accessible in any way at a specific point in the history, but still needs to be
146+ /// (default) initialized. As always, its `newestChildPath` indicates the current way to access it.
147+ ///
148+ /// Hidden children are used for `Refactoring.introduced` and for the implicit changeset that creates
149+ /// non-experimental APIs that ignore experimental children.
150+ public let isHidden : Bool
151+
152+ /// True if this child was created by a `childHistory` change set. Such children
153+ /// are part of the compatibility layer and are therefore deprecated.
154+ public var isHistorical : Bool
155+
143156 /// A name of this child as an identifier.
144157 public var identifier : TokenSyntax {
145158 return . identifier( lowercaseFirstWord ( name: name) )
@@ -161,8 +174,8 @@ public class Child: NodeChoiceConvertible {
161174 return " \( raw: newestName. withFirstCharacterUppercased) Options "
162175 }
163176
164- /// If this child is deprecated , describes the sequence of accesses necessary
165- /// to reach the equivalent value using non-deprecated children; if the child
177+ /// If this child is part of a compatibility layer , describes the sequence of accesses necessary
178+ /// to reach the equivalent value using non-compatibility-layer children; if the child
166179 /// is not deprecated, this array is empty.
167180 ///
168181 /// Think of the elements of this array like components in a key path:
@@ -199,12 +212,6 @@ public class Child: NodeChoiceConvertible {
199212 /// of the child. That information is not directly available anywhere.
200213 public let newestChildPath : [ Child ]
201214
202- /// True if this child was created by a `Child.Refactoring`. Such children
203- /// are part of the compatibility layer and are therefore deprecated.
204- public var isHistorical : Bool {
205- !newestChildPath. isEmpty
206- }
207-
208215 /// Replaces the nodes in `newerChildPath` with their own `newerChildPath`s,
209216 /// if any, to form a child path enitrely of non-historical nodes.
210217 static private func makeNewestChildPath( from newerChildPath: [ Child ] ) -> [ Child ] {
@@ -214,7 +221,7 @@ public class Child: NodeChoiceConvertible {
214221 var workStack = Array ( newerChildPath. reversed ( ) )
215222
216223 while let elem = workStack. popLast ( ) {
217- if elem. isHistorical {
224+ if ! elem. newestChildPath . isEmpty {
218225 // There's an even newer version. Start working on that.
219226 workStack. append ( contentsOf: elem. newestChildPath. reversed ( ) )
220227 } else {
@@ -308,7 +315,8 @@ public class Child: NodeChoiceConvertible {
308315 documentation: String ? = nil ,
309316 isOptional: Bool = false ,
310317 providesDefaultInitialization: Bool = true ,
311- newerChildPath: [ Child ] = [ ]
318+ newerChildPath: [ Child ] = [ ] ,
319+ isHistorical: Bool = false
312320 ) {
313321 precondition ( name. first? . isLowercase ?? true , " The first letter of a child’s name should be lowercase " )
314322 self . name = name
@@ -320,11 +328,18 @@ public class Child: NodeChoiceConvertible {
320328 self . documentationAbstract = String ( documentation? . split ( whereSeparator: \. isNewline) . first ?? " " )
321329 self . isOptional = isOptional
322330 self . providesDefaultInitialization = providesDefaultInitialization
331+ self . isHidden = false
332+ self . isHistorical = isHistorical
323333 }
324334
325335 /// Create a node that is a copy of the last node in `newerChildPath`, but
326336 /// with modifications.
327- init ( renamingTo replacementName: String ? = nil , newerChildPath: [ Child ] ) {
337+ init (
338+ renamingTo replacementName: String ? = nil ,
339+ makingHistorical: Bool = false ,
340+ makingHidden: Bool = false ,
341+ newerChildPath: [ Child ]
342+ ) {
328343 let other = newerChildPath. last!
329344
330345 self . name = replacementName ?? other. name
@@ -336,6 +351,8 @@ public class Child: NodeChoiceConvertible {
336351 self . documentationAbstract = other. documentationAbstract
337352 self . isOptional = other. isOptional
338353 self . providesDefaultInitialization = other. providesDefaultInitialization
354+ self . isHidden = makingHidden || other. isHidden
355+ self . isHistorical = makingHistorical || other. isHistorical
339356 }
340357
341358 /// Create a child for the unexpected nodes between two children (either or
@@ -361,7 +378,8 @@ public class Child: NodeChoiceConvertible {
361378 documentation: nil ,
362379 isOptional: true ,
363380 providesDefaultInitialization: true ,
364- newerChildPath: newerChildPath
381+ newerChildPath: newerChildPath,
382+ isHistorical: ( earlier? . isHistorical ?? false ) || ( later? . isHistorical ?? false )
365383 )
366384 }
367385}
@@ -417,5 +435,8 @@ extension Child {
417435 /// point in the past, so deprecated aliases that flatten the other node's
418436 /// children into this node should be provided.
419437 case extracted
438+
439+ /// A new child was added (and it's important to preserve the names around it).
440+ case introduced
420441 }
421442}
0 commit comments