diff --git a/internal/compiler-bridge/src/main/scala/xsbt/ExtractAPI.scala b/internal/compiler-bridge/src/main/scala/xsbt/ExtractAPI.scala index fca1abaa71..0bdd09e255 100644 --- a/internal/compiler-bridge/src/main/scala/xsbt/ExtractAPI.scala +++ b/internal/compiler-bridge/src/main/scala/xsbt/ExtractAPI.scala @@ -555,14 +555,14 @@ class ExtractAPI[GlobalType <: Global]( val acc = getAccess(c) val name = classNameAsSeenIn(in, c) val tParams = typeParameters(in, sym) // look at class symbol - val selfType = this.selfType(in, sym) - def constructClass(structure: Structure): ClassLike = { + val selfType = lzy(this.selfType(in, sym)) + def constructClass(structure: xsbti.api.Lazy[Structure]): ClassLike = { new xsbti.api.ClassLike(name, acc, modifiers, anns, defType, selfType, structure, emptyStringArray, childrenOfSealedClass, topLevel, tParams) // use original symbol (which is a term symbol when `c.isModule`) for `name` and other non-classy stuff } val info = viewer(in).memberInfo(sym) - val structure = structureWithInherited(info, sym) + val structure = lzy(structureWithInherited(info, sym)) val classWithMembers = constructClass(structure) allNonLocalClassesInSrc += classWithMembers diff --git a/internal/compiler-interface/src/main/contraband/definition.json b/internal/compiler-interface/src/main/contraband/definition.json index 2c81a58c1b..3da1d346e4 100644 --- a/internal/compiler-interface/src/main/contraband/definition.json +++ b/internal/compiler-interface/src/main/contraband/definition.json @@ -101,11 +101,11 @@ "type": "record", "fields": [ { "name": "definitionType", "type": "DefinitionType" }, - { "name": "selfType", "type": "Type" }, - { "name": "structure", "type": "Structure" }, + { "name": "selfType", "type": "lazy Type" }, + { "name": "structure", "type": "lazy Structure" }, { "name": "savedAnnotations", "type": "String*" }, { "name": "childrenOfSealedClass", "type": "Type*" }, - { "name": "topLevel", "type": "boolean" }, + { "name": "topLevel", "type": "Boolean" }, { "name": "typeParameters", "type": "TypeParameter*" } ] } diff --git a/internal/zinc-apiinfo/src/main/scala/sbt/internal/inc/ClassToAPI.scala b/internal/zinc-apiinfo/src/main/scala/sbt/internal/inc/ClassToAPI.scala index a730f1c97c..9e548a8da7 100644 --- a/internal/zinc-apiinfo/src/main/scala/sbt/internal/inc/ClassToAPI.scala +++ b/internal/zinc-apiinfo/src/main/scala/sbt/internal/inc/ClassToAPI.scala @@ -83,11 +83,11 @@ object ClassToAPI { val topLevel = c.getEnclosingClass == null val name = classCanonicalName(c) val tpe = if (Modifier.isInterface(c.getModifiers)) Trait else ClassDef - val (static, instance) = structure(c, enclPkg, cmap) - val cls = new api.ClassLike(name, acc, mods, annots, tpe, Empty, instance, emptyStringArray, children.toArray, + lazy val (static, instance) = structure(c, enclPkg, cmap) + val cls = new api.ClassLike(name, acc, mods, annots, tpe, lzyS(Empty), lzy(instance, cmap), emptyStringArray, children.toArray, topLevel, typeParameters(typeParameterTypes(c))) val clsDef = new api.ClassLikeDef(name, acc, mods, annots, typeParameters(typeParameterTypes(c)), tpe) - val stat = new api.ClassLike(name, acc, mods, annots, Module, Empty, static, emptyStringArray, emptyTypeArray, + val stat = new api.ClassLike(name, acc, mods, annots, Module, lzyS(Empty), lzy(static, cmap), emptyStringArray, emptyTypeArray, topLevel, emptyTypeParameterArray) val statDef = new api.ClassLikeDef(name, acc, mods, annots, emptyTypeParameterArray, Module) val defs = cls :: stat :: Nil @@ -120,12 +120,18 @@ object ClassToAPI { @inline private[this] def lzyS[T <: AnyRef](t: T): xsbti.api.Lazy[T] = SafeLazyProxy.strict(t) @inline final def lzy[T <: AnyRef](t: => T): xsbti.api.Lazy[T] = SafeLazyProxy(t) + private[this] def lzy[T <: AnyRef](t: => T, cmap: ClassMap): xsbti.api.Lazy[T] = { + val s = lzy(t) + cmap.lz += s + s + } private val emptyStringArray = new Array[String](0) private val emptyTypeArray = new Array[xsbti.api.Type](0) private val emptyAnnotationArray = new Array[xsbti.api.Annotation](0) private val emptyTypeParameterArray = new Array[xsbti.api.TypeParameter](0) private val emptyDefArray = new Array[xsbti.api.ClassDefinition](0) + private val lzyEmptyTpeArray = lzyS(emptyTypeArray) private val lzyEmptyDefArray = lzyS(emptyDefArray) private def allSuperTypes(t: Type): Seq[Type] = diff --git a/internal/zinc-apiinfo/src/main/scala/xsbt/api/APIUtil.scala b/internal/zinc-apiinfo/src/main/scala/xsbt/api/APIUtil.scala index f0e15cebdc..47ef781713 100644 --- a/internal/zinc-apiinfo/src/main/scala/xsbt/api/APIUtil.scala +++ b/internal/zinc-apiinfo/src/main/scala/xsbt/api/APIUtil.scala @@ -59,7 +59,7 @@ object APIUtil { val savedAnnotations = Discovery.defAnnotations(c.structure, (_: Any) => true).toArray[String] val struct = minimizeStructure(c.structure, c.definitionType == DefinitionType.Module) new ClassLike(c.name, c.access, c.modifiers, c.annotations, - c.definitionType, emptyType, struct, savedAnnotations, c.childrenOfSealedClass, + c.definitionType, lzy(emptyType), lzy(struct), savedAnnotations, c.childrenOfSealedClass, c.topLevel, c.typeParameters) } @@ -79,7 +79,7 @@ object APIUtil { private val emptyStructure = new Structure(Array.empty, Array.empty, lzy(Array.empty)) def emptyClassLike(name: String, definitionType: DefinitionType): ClassLike = new xsbti.api.ClassLike(name, new Public, emptyModifiers, Array.empty, - definitionType, emptyType, emptyStructure, Array.empty, Array.empty, true, Array.empty) + definitionType, lzy(emptyType), lzy(emptyStructure), Array.empty, Array.empty, true, Array.empty) private[this] def lzy[T <: AnyRef](t: T): Lazy[T] = SafeLazyProxy.strict(t) diff --git a/internal/zinc-apiinfo/src/test/scala/xsbt/api/NameHashingSpecification.scala b/internal/zinc-apiinfo/src/test/scala/xsbt/api/NameHashingSpecification.scala index 2f888334b4..ba0909de04 100644 --- a/internal/zinc-apiinfo/src/test/scala/xsbt/api/NameHashingSpecification.scala +++ b/internal/zinc-apiinfo/src/test/scala/xsbt/api/NameHashingSpecification.scala @@ -292,8 +292,8 @@ class NameHashingSpecification extends UnitSpec { private def simpleClassLike(name: String, structure: Structure, dt: DefinitionType = DefinitionType.ClassDef, topLevel: Boolean = true, access: Access = publicAccess): ClassLike = { - new ClassLike(name, access, defaultModifiers, Array.empty, dt, emptyType, - structure, Array.empty, Array.empty, topLevel, Array.empty) + new ClassLike(name, access, defaultModifiers, Array.empty, dt, lzy(emptyType), + lzy(structure), Array.empty, Array.empty, topLevel, Array.empty) } private val emptyType = new EmptyType diff --git a/internal/zinc-persist/src/test/scala/sbt/inc/TestCaseGenerators.scala b/internal/zinc-persist/src/test/scala/sbt/inc/TestCaseGenerators.scala index 87f9ff3878..589809d2fe 100644 --- a/internal/zinc-persist/src/test/scala/sbt/inc/TestCaseGenerators.scala +++ b/internal/zinc-persist/src/test/scala/sbt/inc/TestCaseGenerators.scala @@ -76,7 +76,7 @@ object TestCaseGenerators { // We need "proper" definitions with specific class names, as groupBy use these to pick a representative top-level class when splitting. private[this] def makeClassLike(name: String, definitionType: DefinitionType): ClassLike = new ClassLike(name, new Public(), APIs.emptyModifiers, Array(), - definitionType, new EmptyType(), emptyStructure, Array(), Array(), true, Array()) + definitionType, lzy(new EmptyType()), lzy(emptyStructure), Array(), Array(), true, Array()) private[this] def makeCompanions(name: String): Companions = new Companions(makeClassLike(name, DefinitionType.ClassDef), makeClassLike(name, DefinitionType.Module))