From b908d5f2c244c4283364f624ad08640a7842c11c Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 5 Jul 2016 21:11:53 +0200 Subject: [PATCH] stub hierarchy: process imports without destructuring qualified names, remove memory structures needed for now unused destructuring --- .../psi/stubsHierarchy/impl/Imports.java | 118 ++++++++++++------ .../stubsHierarchy/impl/JavaStubIndexer.java | 12 +- .../stubsHierarchy/impl/NameEnvironment.java | 18 +-- .../stubsHierarchy/impl/SerializedUnit.java | 4 +- .../psi/stubsHierarchy/impl/StubEnter.java | 5 +- .../psi/stubsHierarchy/impl/StubResolver.java | 35 +++--- .../psi/stubsHierarchy/impl/Translator.java | 44 ++++--- .../psi/stubsHierarchy/impl/UnitInfo.java | 82 +++--------- 8 files changed, 145 insertions(+), 173 deletions(-) diff --git a/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/Imports.java b/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/Imports.java index baded25636ca..8aa45819e61a 100644 --- a/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/Imports.java +++ b/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/Imports.java @@ -16,46 +16,17 @@ package com.intellij.psi.stubsHierarchy.impl; import com.intellij.psi.impl.java.stubs.hierarchy.IndexTree; -import com.intellij.util.ArrayUtil; import com.intellij.util.BitUtil; import com.intellij.util.io.DataInputOutputUtil; +import gnu.trove.TIntObjectHashMap; import org.jetbrains.annotations.NotNull; import java.io.DataOutput; import java.io.IOException; class Imports { - public final static long[] EMPTY_ARRAY = ArrayUtil.EMPTY_LONG_ARRAY; - - public static final int onDemandMask = 1 << 29; - public static final int staticMask = 1 << 30; - - public static int mask = ~(onDemandMask | staticMask); - - public static int getAlias(long importMask) { - return (int)(importMask >>> 32); - } - - static int getFullNameId(long importMask) { - int fullNameId = (int)importMask; - fullNameId &= mask; - return fullNameId; - } - - public static boolean isOnDemand(long importMask) { - return BitUtil.isSet(importMask, onDemandMask); - } - - public static boolean isStatic(long importMask) { - return BitUtil.isSet(importMask, staticMask); - } - - public static long mkImport(@QNameId int fullname, boolean importStatic, boolean onDemand, int alias) { - long lower = fullname; - if (importStatic) lower |= staticMask; - if (onDemand) lower |= onDemandMask; - return (((long)alias) << 32) | lower; - } + public final static Import[] EMPTY_ARRAY = new Import[0]; + private final TIntObjectHashMap myNonStaticPackageImports = new TIntObjectHashMap<>(); private final static int IS_STATIC = 1; private final static int IS_ON_DEMAND = 2; @@ -68,9 +39,9 @@ class Imports { } } - static long[] readImports(UnitInputStream in) throws IOException { + Import[] readImports(UnitInputStream in) throws IOException { int importCount = DataInputOutputUtil.readINT(in); - long[] imports = importCount == 0 ? EMPTY_ARRAY : new long[importCount]; + Import[] imports = importCount == 0 ? EMPTY_ARRAY : new Import[importCount]; for (int i = 0; i < importCount; i++) { imports[i] = readImport(in); } @@ -90,12 +61,81 @@ class Imports { } } - private static long readImport(UnitInputStream in) throws IOException { - int fullname = in.names.readQualifiedName(in); + private Import readImport(UnitInputStream in) throws IOException { + int qualifier = 0; + int len = DataInputOutputUtil.readINT(in); + for (int i = 0; i < len - 1; i++) { + qualifier = in.names.qualifiedName(qualifier, in.readInt()); + } + int lastId = in.readInt(); int flags = in.readByte(); - return mkImport(fullname, - BitUtil.isSet(flags, IS_STATIC), BitUtil.isSet(flags, IS_ON_DEMAND), - BitUtil.isSet(flags, HAS_ALIAS) ? in.readInt() : 0); + int alias = BitUtil.isSet(flags, HAS_ALIAS) ? in.readInt() : 0; + + boolean onDemand = BitUtil.isSet(flags, IS_ON_DEMAND); + boolean isStatic = BitUtil.isSet(flags, IS_STATIC); + + int shortName; + if (onDemand) { + shortName = 0; + qualifier = in.names.qualifiedName(qualifier, lastId); + } else { + shortName = lastId; + } + + return obtainImport(qualifier, shortName, alias, isStatic); + } + + private Import obtainImport(int qualifier, int shortName, int alias, boolean isStatic) { + boolean shouldIntern = shortName == 0 && alias == 0 && !isStatic; + if (shouldIntern) { + Import existing = myNonStaticPackageImports.get(qualifier); + if (existing != null) { + return existing; + } + } + + Import anImport = alias != 0 ? new AliasedImport(qualifier, shortName, isStatic, alias) : new Import(qualifier, shortName, isStatic); + if (shouldIntern) { + myNonStaticPackageImports.put(qualifier, anImport); + } + return anImport; + } +} + +class Import { + @QNameId final int qualifier; + @ShortName final int importedName; // 0 for on-demand + final boolean isStatic; + + Import(@QNameId int qualifier, @ShortName int importedName, boolean isStatic) { + this.qualifier = qualifier; + this.importedName = importedName; + this.isStatic = isStatic; + } + + boolean isOnDemand() { + return importedName == 0; + } + + @ShortName int getAlias() { + return 0; } } + +class AliasedImport extends Import { + private final @ShortName int alias; + + public AliasedImport(@QNameId int qualifier, + @ShortName int importedName, + boolean isStatic, + @ShortName int alias) { + super(qualifier, importedName, isStatic); + this.alias = alias; + } + + @Override + int getAlias() { + return alias; + } +} \ No newline at end of file diff --git a/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/JavaStubIndexer.java b/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/JavaStubIndexer.java index ea78d80c0634..3d8bad16e21c 100644 --- a/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/JavaStubIndexer.java +++ b/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/JavaStubIndexer.java @@ -80,14 +80,14 @@ public class JavaStubIndexer extends StubHierarchyIndexer { } } } - ArrayList importList = new ArrayList(); + ArrayList importList = new ArrayList<>(); for (StubElement el : javaFileStub.getChildrenStubs()) { if (el instanceof PsiImportListStub) { processImport((PsiImportListStub) el, importList, usedNames); } } ClassDecl[] classes = classList.isEmpty() ? ClassDecl.EMPTY_ARRAY : classList.toArray(new ClassDecl[classList.size()]); - Import[] imports = importList.isEmpty() ? Import.EMPTY_ARRAY : importList.toArray(new Import[importList.size()]); + IndexTree.Import[] imports = importList.isEmpty() ? IndexTree.Import.EMPTY_ARRAY : importList.toArray(new IndexTree.Import[importList.size()]); byte type = javaFileStub.isCompiled() ? IndexTree.BYTECODE : IndexTree.JAVA; return new Unit(javaFileStub.getPackageName(), type, imports, classes); } @@ -142,7 +142,7 @@ public class JavaStubIndexer extends StubHierarchyIndexer { } } - int flags = translateFlags(classStub, accessModifiers); + int flags = translateFlags(classStub); if (classStub.isAnonymousInQualifiedNew()) { flags |= IndexTree.SUPERS_UNRESOLVED; } @@ -151,21 +151,21 @@ public class JavaStubIndexer extends StubHierarchyIndexer { return new ClassDecl(classStub.id, flags, classStub.getName(), supers, inners); } - private static int translateFlags(PsiClassStubImpl classStub, int accessModifiers) { + private static int translateFlags(PsiClassStubImpl classStub) { int flags = 0; flags = BitUtil.set(flags, IndexTree.ENUM, classStub.isEnum()); flags = BitUtil.set(flags, IndexTree.ANNOTATION, classStub.isAnnotationType()); return flags; } - private static void processImport(PsiImportListStub el, List imports, Set namesCache) { + private static void processImport(PsiImportListStub el, List imports, Set namesCache) { for (StubElement importElem : el.getChildrenStubs()) { PsiImportStatementStub imp = (PsiImportStatementStub)importElem; String importReferenceText = imp.getImportReferenceText(); if (importReferenceText != null) { String fullName = PsiNameHelper.getQualifiedClassName(importReferenceText, true); if (imp.isOnDemand() || namesCache.contains(shortName(fullName))) { - imports.add(new Import(fullName, imp.isStatic(), imp.isOnDemand(), null)); + imports.add(new IndexTree.Import(fullName, imp.isStatic(), imp.isOnDemand(), null)); } } } diff --git a/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/NameEnvironment.java b/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/NameEnvironment.java index 05683a9c4f1f..c2108467c649 100644 --- a/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/NameEnvironment.java +++ b/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/NameEnvironment.java @@ -19,7 +19,6 @@ import com.intellij.openapi.util.UserDataHolderBase; import com.intellij.psi.CommonClassNames; import com.intellij.psi.impl.java.stubs.hierarchy.IndexTree; import com.intellij.util.io.DataInputOutputUtil; -import gnu.trove.TIntArrayList; import gnu.trove.TLongIntHashMap; import java.io.DataInput; @@ -33,14 +32,9 @@ class NameEnvironment extends UserDataHolderBase { public final QualifiedName java_lang_Enum; public final QualifiedName java_lang_annotation_Annotation; - private final TIntArrayList mySuffixes = new TIntArrayList(); - private final TIntArrayList myStems = new TIntArrayList(); private final TLongIntHashMap myConcatenations = new TLongIntHashMap(); NameEnvironment() { - mySuffixes.add(0); - myStems.add(0); - java_lang = fromString("java.lang"); java_lang_Enum = new QualifiedName.Interned(fromString(CommonClassNames.JAVA_LANG_ENUM)); java_lang_annotation_Annotation = new QualifiedName.Interned(fromString(CommonClassNames.JAVA_LANG_ANNOTATION_ANNOTATION)); @@ -51,14 +45,6 @@ class NameEnvironment extends UserDataHolderBase { return internQualifiedName(IndexTree.hashQualifiedName(s)); } - @QNameId int prefixId(@QNameId int nameId) { - return myStems.get(nameId); - } - - @ShortName int shortName(@QNameId int id) { - return mySuffixes.get(id); - } - @QNameId int findExistingName(@QNameId int stemId, @ShortName int suffix) { int existing = myConcatenations.get(pack(stemId, suffix)); return existing > 0 ? existing : -1; @@ -94,9 +80,7 @@ class NameEnvironment extends UserDataHolderBase { } private int addName(@QNameId int stemId, @ShortName int suffix) { - int newId = mySuffixes.size(); - mySuffixes.add(suffix); - myStems.add(stemId); + int newId = myConcatenations.size(); myConcatenations.put(pack(stemId, suffix), newId); return newId; } diff --git a/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/SerializedUnit.java b/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/SerializedUnit.java index e4875a113fa6..b35dcdd106b8 100644 --- a/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/SerializedUnit.java +++ b/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/SerializedUnit.java @@ -105,7 +105,7 @@ class SerializedUnit { private static void enterUnit(UnitInputStream in) throws IOException { PackageSymbol pkg = in.stubEnter.readPackageName(in); byte type = in.readByte(); - long[] imports = type == IndexTree.BYTECODE ? Imports.EMPTY_ARRAY : Imports.readImports(in); + Import[] imports = type == IndexTree.BYTECODE ? Imports.EMPTY_ARRAY : in.stubEnter.imports.readImports(in); UnitInfo unitInfo = UnitInfo.mkUnitInfo(type, imports); int classCount = DataInputOutputUtil.readINT(in); @@ -128,7 +128,7 @@ class SerializedUnit { int stubId = DataInputOutputUtil.readINT(in); int mods = DataInputOutputUtil.readINT(in); @ShortName int name = in.readInt(); - @CompactArray(QualifiedName.class) Object superNames = readSupers(in, info.getType() == IndexTree.BYTECODE); + @CompactArray(QualifiedName.class) Object superNames = readSupers(in, info.isCompiled()); @QNameId int qname = in.names.memberQualifiedName(ownerName, name); ClassSymbol symbol = in.stubEnter.classEnter(info, owner, stubId, mods, name, superNames, qname, in.fileId); diff --git a/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/StubEnter.java b/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/StubEnter.java index 9a90f63e2f6f..3f04a62e199e 100644 --- a/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/StubEnter.java +++ b/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/StubEnter.java @@ -30,6 +30,7 @@ import static com.intellij.psi.stubsHierarchy.impl.Symbol.PackageSymbol; public class StubEnter { final NameEnvironment myNameEnvironment; + final Imports imports = new Imports(); private final Symbols mySymbols; private final StubHierarchyConnector myStubHierarchyConnector; @@ -60,7 +61,7 @@ public class StubEnter { @ShortName int name, @CompactArray(QualifiedName.class) Object superNames, @QNameId int qname, int fileId) throws IOException { - int flags = checkFlags(mods, owner, info.getType() == IndexTree.BYTECODE); + int flags = checkFlags(mods, info.isCompiled()); @CompactArray(QualifiedName.class) Object supers = handleSpecialSupers(mods, superNames); ClassSymbol classSymbol = mySymbols.enterClass(fileId, stubId, flags, name, owner, info, supers, qname); @@ -100,7 +101,7 @@ public class StubEnter { uncompleted = null; } - private static int checkFlags(long flags, Symbol owner, boolean compiled) { + private static int checkFlags(long flags, boolean compiled) { int mask = 0; if ((flags & IndexTree.SUPERS_UNRESOLVED) != 0) { mask |= IndexTree.SUPERS_UNRESOLVED; diff --git a/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/StubResolver.java b/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/StubResolver.java index 3d65c3e2ecbb..692733680b32 100644 --- a/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/StubResolver.java +++ b/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/StubResolver.java @@ -137,39 +137,32 @@ public class StubResolver { } private void findGlobalType(UnitInfo info, @ShortName int name, Set symbols) throws IncompleteHierarchyException { - for (long anImport : Translator.getDefaultImports(info.getType(), myNameEnvironment)) + for (Import anImport : Translator.getDefaultImports(info.type, myNameEnvironment)) handleImport(anImport, name, symbols); - for (long anImport : info.getImports()) + for (Import anImport : info.imports) handleImport(anImport, name, symbols); } - public void handleImport(long tree, @ShortName int name, Set symbols) throws IncompleteHierarchyException { - @QNameId int fullname = Imports.getFullNameId(tree); - if (Imports.isOnDemand(tree)) { - if (Imports.isStatic(tree)) { - for (Symbol.ClassSymbol p : findGlobalType(fullname)) + public void handleImport(Import anImport, @ShortName int name, Set symbols) throws IncompleteHierarchyException { + if (anImport.isOnDemand()) { + if (anImport.isStatic) { + for (Symbol.ClassSymbol p : findGlobalType(anImport.qualifier)) importNamedStatic(p, name, symbols); } else { - importAll(fullname, name, symbols); + importAll(anImport.qualifier, name, symbols); } } else { - @QNameId int prefix = myNameEnvironment.prefixId(fullname); - if (prefix == 0) { - return; - } - @ShortName int shortName = myNameEnvironment.shortName(fullname); - @ShortName int alias = Imports.getAlias(tree); - boolean shouldImport = ((alias & name) == name) || shortName == name; - if (!shouldImport) - return; - if (Imports.isStatic(tree)) { - for (Symbol.ClassSymbol s : findGlobalType(prefix)) - importNamedStatic(s, shortName, symbols); + @ShortName int importedName = anImport.getAlias() != 0 ? anImport.getAlias() : anImport.importedName; + if (name != importedName) return; + + if (anImport.isStatic) { + for (Symbol.ClassSymbol s : findGlobalType(anImport.qualifier)) + importNamedStatic(s, anImport.importedName, symbols); } else { - Collections.addAll(symbols, findGlobalType(fullname)); + Collections.addAll(symbols, findGlobalType(myNameEnvironment.qualifiedName(anImport.qualifier, anImport.importedName))); } } } diff --git a/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/Translator.java b/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/Translator.java index c1e3fff734da..107ec71ded99 100644 --- a/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/Translator.java +++ b/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/Translator.java @@ -19,11 +19,11 @@ import com.intellij.openapi.util.Key; import com.intellij.psi.impl.java.stubs.hierarchy.IndexTree; public class Translator { - private static final Key DEFAULT_JAVA_IMPORTS_KEY = Key.create("java_imports"); - private static final Key DEFAULT_GROOVY_IMPORTS_KEY = Key.create("groovy_imports"); + private static final Key DEFAULT_JAVA_IMPORTS_KEY = Key.create("java_imports"); + private static final Key DEFAULT_GROOVY_IMPORTS_KEY = Key.create("groovy_imports"); - private static long[] getDefaultJavaImports(NameEnvironment nameEnvironment) { - long[] imports = nameEnvironment.getUserData(DEFAULT_JAVA_IMPORTS_KEY); + private static Import[] getDefaultJavaImports(NameEnvironment nameEnvironment) { + Import[] imports = nameEnvironment.getUserData(DEFAULT_JAVA_IMPORTS_KEY); if (imports == null) { imports = createDefaultJavaImports(nameEnvironment); nameEnvironment.putUserData(DEFAULT_JAVA_IMPORTS_KEY, imports); @@ -31,14 +31,14 @@ public class Translator { return imports; } - private static long[] createDefaultJavaImports(NameEnvironment nameEnvironment) { - return new long[]{ - Imports.mkImport(nameEnvironment.fromString("java.lang"), false, true, 0) + private static Import[] createDefaultJavaImports(NameEnvironment nameEnvironment) { + return new Import[]{ + importPackage(nameEnvironment, "java.lang") }; } - private static long[] getDefaultGroovyImports(NameEnvironment nameEnvironment) { - long[] imports = nameEnvironment.getUserData(DEFAULT_GROOVY_IMPORTS_KEY); + private static Import[] getDefaultGroovyImports(NameEnvironment nameEnvironment) { + Import[] imports = nameEnvironment.getUserData(DEFAULT_GROOVY_IMPORTS_KEY); if (imports == null) { imports = createDefaultGroovyImports(nameEnvironment); nameEnvironment.putUserData(DEFAULT_GROOVY_IMPORTS_KEY, imports); @@ -46,20 +46,24 @@ public class Translator { return imports; } - private static long[] createDefaultGroovyImports(NameEnvironment nameEnvironment) { - return new long[] { - Imports.mkImport(nameEnvironment.fromString("java.lang"), false, true, 0), - Imports.mkImport(nameEnvironment.fromString("java.util"), false, true, 0), - Imports.mkImport(nameEnvironment.fromString("java.io"), false, true, 0), - Imports.mkImport(nameEnvironment.fromString("java.net"), false, true, 0), - Imports.mkImport(nameEnvironment.fromString("groovy.lang"), false, true, 0), - Imports.mkImport(nameEnvironment.fromString("groovy.util"), false, true, 0), - Imports.mkImport(nameEnvironment.fromString("java.math.BigInteger"), false, true, 0), - Imports.mkImport(nameEnvironment.fromString("java.math.BigDecimal"), false, true, 0), + private static Import[] createDefaultGroovyImports(NameEnvironment nameEnvironment) { + return new Import[] { + importPackage(nameEnvironment, "java.lang"), + importPackage(nameEnvironment, "java.util"), + importPackage(nameEnvironment, "java.io"), + importPackage(nameEnvironment, "java.net"), + importPackage(nameEnvironment, "groovy.lang"), + importPackage(nameEnvironment, "groovy.util"), + new Import(nameEnvironment.fromString("java.math"), IndexTree.hashIdentifier("BigInteger"), false), + new Import(nameEnvironment.fromString("java.math"), IndexTree.hashIdentifier("BigDecimal"), false), }; } - public static long[] getDefaultImports(byte type, NameEnvironment nameEnvironment) { + private static Import importPackage(NameEnvironment nameEnvironment, String qname) { + return new Import(nameEnvironment.fromString(qname), 0, false); + } + + public static Import[] getDefaultImports(byte type, NameEnvironment nameEnvironment) { if (type == IndexTree.JAVA) return getDefaultJavaImports(nameEnvironment); if (type == IndexTree.GROOVY) diff --git a/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/UnitInfo.java b/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/UnitInfo.java index 6106dc19a4ec..1e296987dbdc 100644 --- a/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/UnitInfo.java +++ b/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/UnitInfo.java @@ -17,78 +17,28 @@ package com.intellij.psi.stubsHierarchy.impl; import com.intellij.psi.impl.java.stubs.hierarchy.IndexTree; -public abstract class UnitInfo { +final class UnitInfo { private static final UnitInfo[] EMPTY_INFOS = new UnitInfo[]{ - new LongUnitInfo(IndexTree.BYTECODE, Imports.EMPTY_ARRAY), - new LongUnitInfo(IndexTree.JAVA, Imports.EMPTY_ARRAY), - new LongUnitInfo(IndexTree.GROOVY, Imports.EMPTY_ARRAY) + new UnitInfo(IndexTree.BYTECODE, Imports.EMPTY_ARRAY), + new UnitInfo(IndexTree.JAVA, Imports.EMPTY_ARRAY), + new UnitInfo(IndexTree.GROOVY, Imports.EMPTY_ARRAY) }; - static UnitInfo mkUnitInfo(byte unitType, long[] imports) { - if (imports.length == 0) { - return EMPTY_INFOS[unitType]; - } - for (long anImport : imports) { - if (Imports.getAlias(anImport) != 0) { - return new LongUnitInfo(unitType, imports); - } - } - return new IntUnitInfo(unitType, imports); - } - /* IndexTree.BYTECODE, IndexTree.JAVA, IndexTree.GROOVY */ - public abstract byte getType(); + final byte type; + final Import[] imports; - public abstract long[] getImports(); - - static class LongUnitInfo extends UnitInfo { - public final byte type; - - @Override - public byte getType() { - return type; - } - - public long[] getImports() { - return imports; - } - private long[] imports; - public LongUnitInfo(byte type, long[] imports) { - this.type = type; - this.imports = imports; - } + private UnitInfo(byte type, Import[] imports) { + this.type = type; + this.imports = imports; } - static class IntUnitInfo extends UnitInfo { - public final byte type; - private int[] imports; - - @Override - public byte getType() { - return type; - } - public long[] getImports() { - return convert(imports); - } - public IntUnitInfo(byte type, long[] imports) { - this.type = type; - this.imports = convert(imports); - } - - private static int[] convert(long[] ar) { - int[] result = new int[ar.length]; - for (int i = 0; i < ar.length; i++) { - result[i] = (int)ar[i]; - } - return result; - } - - private static long[] convert(int[] ar) { - long[] result = new long[ar.length]; - for (int i = 0; i < ar.length; i++) { - result[i] = ar[i]; - } - return result; - } + static UnitInfo mkUnitInfo(byte unitType, Import[] imports) { + return imports.length == 0 ? EMPTY_INFOS[unitType] : new UnitInfo(unitType, imports); } + + boolean isCompiled() { + return type == IndexTree.BYTECODE; + } + }