@@ -134,4 +134,45 @@ class SymUtils(val self: Symbol) extends AnyVal {
134134 }
135135 }
136136 }
137+
138+ /** If this symbol is an enum value or a named class, register it as a child
139+ * in all direct parent classes which are sealed.
140+ * @param @late If true, register only inaccessible children (all others are already
141+ * entered at this point).
142+ */
143+ def registerIfChild (late : Boolean = false )(implicit ctx : Context ): Unit = {
144+ def register (child : Symbol , parent : Type ) = {
145+ val cls = parent.classSymbol
146+ if (cls.is(Sealed ) && (! late || child.isInaccessibleChildOf(cls)))
147+ cls.addAnnotation(Annotation .Child (child))
148+ }
149+ if (self.isClass && ! self.isAnonymousClass)
150+ self.asClass.classParents.foreach { parent =>
151+ val child = if (self.is(Module )) self.sourceModule else self
152+ register(child, parent)
153+ }
154+ else if (self.is(CaseVal , butNot = Method | Module ))
155+ register(self, self.info)
156+ }
157+
158+ /** Is this symbol defined locally (i.e. at some level owned by a term) and
159+ * defined in a different toplevel class than its supposed parent class `cls`?
160+ * Such children are not pickled, and have to be reconstituted manually.
161+ */
162+ def isInaccessibleChildOf (cls : Symbol )(implicit ctx : Context ) =
163+ self.isLocal && ! cls.topLevelClass.isLinkedWith(self.topLevelClass)
164+
165+ /** If this is a sealed class, its known children */
166+ def children (implicit ctx : Context ): List [Symbol ] =
167+ self.annotations.collect {
168+ case Annotation .Child (child) => child
169+ }
170+
171+ /** Is symbol directly or indirectly owned by a term symbol? */
172+ @ tailrec def isLocal (implicit ctx : Context ): Boolean = {
173+ val owner = self.owner
174+ if (owner.isTerm) true
175+ else if (owner.is(Package )) false
176+ else owner.isLocal
177+ }
137178}
0 commit comments