From 5ed4364149eecc61ed89343e6cc0994ea512e749 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 5 Jul 2016 18:55:30 +0200 Subject: [PATCH] avoid qualified name destructuring during stub hierarchy resolve in src file data --- .../stubsHierarchy/impl/NameEnvironment.java | 4 +- .../stubsHierarchy/impl/QualifiedName.java | 69 +++++++++++++++---- .../stubsHierarchy/impl/SerializedUnit.java | 27 ++++++-- .../psi/stubsHierarchy/impl/StubEnter.java | 26 +++---- .../impl/StubHierarchyConnector.java | 21 +----- .../psi/stubsHierarchy/impl/StubResolver.java | 35 ++++++---- 6 files changed, 111 insertions(+), 71 deletions(-) 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 048d6fbc9682..05683a9c4f1f 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 @@ -42,8 +42,8 @@ class NameEnvironment extends UserDataHolderBase { myStems.add(0); java_lang = fromString("java.lang"); - java_lang_Enum = new QualifiedName(fromString(CommonClassNames.JAVA_LANG_ENUM)); - java_lang_annotation_Annotation = new QualifiedName(fromString(CommonClassNames.JAVA_LANG_ANNOTATION_ANNOTATION)); + java_lang_Enum = new QualifiedName.Interned(fromString(CommonClassNames.JAVA_LANG_ENUM)); + java_lang_annotation_Annotation = new QualifiedName.Interned(fromString(CommonClassNames.JAVA_LANG_ANNOTATION_ANNOTATION)); } @QNameId diff --git a/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/QualifiedName.java b/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/QualifiedName.java index 575bb59f7b8c..d83a05d50d8a 100644 --- a/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/QualifiedName.java +++ b/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/QualifiedName.java @@ -15,25 +15,66 @@ */ package com.intellij.psi.stubsHierarchy.impl; -final class QualifiedName { - public final int myId; +import java.util.Collections; +import java.util.Set; - QualifiedName(int id) { - this.myId = id; +abstract class QualifiedName { + + abstract void resolveCandidates(StubResolver resolver, Symbol.ClassSymbol place, Set result) + throws IncompleteHierarchyException; + + static class OfComponents extends QualifiedName { + @ShortName final int[] components; + + OfComponents(int[] components) { + this.components = components; + } + + @Override + void resolveCandidates(StubResolver resolver, Symbol.ClassSymbol place, Set result) + throws IncompleteHierarchyException { + for (Symbol symbol : resolver.resolveBase(place, components)) { + if (symbol instanceof Symbol.ClassSymbol) { + result.add((Symbol.ClassSymbol)symbol); + } + } + } } - public boolean isEmpty() { - return myId == 0; + static class OfSingleComponent extends QualifiedName { + @ShortName final int shortName; + + OfSingleComponent(@ShortName int shortName) { + this.shortName = shortName; + } + + @Override + void resolveCandidates(StubResolver resolver, Symbol.ClassSymbol place, Set result) + throws IncompleteHierarchyException { + for (Symbol symbol : resolver.resolveUnqualified(place, shortName, false)) { + if (symbol instanceof Symbol.ClassSymbol) { + result.add((Symbol.ClassSymbol)symbol); + } + } + } } - @Override - public boolean equals(Object o) { - if (this == o) return true; - return o instanceof QualifiedName && myId == ((QualifiedName)o).myId; - } + static class Interned extends QualifiedName { + @QNameId final int id; - @Override - public int hashCode() { - return myId; + Interned(int id) { + this.id = id; + } + + @Override + void resolveCandidates(StubResolver resolver, Symbol.ClassSymbol place, Set result) + throws IncompleteHierarchyException { + Symbol.ClassSymbol[] candidates = resolver.findGlobalType(id); + if (candidates.length == 0) { + throw new IncompleteHierarchyException(); + } + + Collections.addAll(result, candidates); + } } } 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 ee81c77855d6..e4875a113fa6 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 @@ -76,6 +76,17 @@ class SerializedUnit { } } + static QualifiedName readNameComponents(DataInput in) throws IOException { + int length = DataInputOutputUtil.readINT(in); + if (length == 1) return new QualifiedName.OfSingleComponent(in.readInt()); + + int[] result = new int[length]; + for (int i = 0; i < length; i++) { + result[i] = in.readInt(); + } + return new QualifiedName.OfComponents(result); + } + // unit private static void writeUnit(@NotNull DataOutput out, IndexTree.Unit value) throws IOException { @@ -117,7 +128,7 @@ class SerializedUnit { int stubId = DataInputOutputUtil.readINT(in); int mods = DataInputOutputUtil.readINT(in); @ShortName int name = in.readInt(); - @QNameId int[] superNames = readSupers(in); + @CompactArray(QualifiedName.class) Object superNames = readSupers(in, info.getType() == IndexTree.BYTECODE); @QNameId int qname = in.names.memberQualifiedName(ownerName, name); ClassSymbol symbol = in.stubEnter.classEnter(info, owner, stubId, mods, name, superNames, qname, in.fileId); @@ -135,14 +146,22 @@ class SerializedUnit { } } - private static @QNameId int[] readSupers(UnitInputStream in) throws IOException { - @QNameId int[] superNames = new int[DataInputOutputUtil.readINT(in)]; + private static @CompactArray(QualifiedName.class) Object readSupers(UnitInputStream in, boolean intern) throws IOException { + int length = DataInputOutputUtil.readINT(in); + if (length == 0) return null; + if (length == 1) return readSuperName(in, intern); + + QualifiedName[] superNames = new QualifiedName[length]; for (int i = 0; i < superNames.length; i++) { - superNames[i] = in.names.readQualifiedName(in); + superNames[i] = readSuperName(in, intern); } return superNames; } + private static QualifiedName readSuperName(UnitInputStream in, boolean intern) throws IOException { + return intern ? new QualifiedName.Interned(in.names.readQualifiedName(in)) : readNameComponents(in); + } + // members private static void writeMembers(@NotNull DataOutput out, IndexTree.Decl[] decls) throws IOException { 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 55d131ee588e..9a90f63e2f6f 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 @@ -16,6 +16,7 @@ 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 org.jetbrains.annotations.Nullable; @@ -57,10 +58,10 @@ public class StubEnter { int stubId, int mods, @ShortName int name, - @QNameId int[] superNames, + @CompactArray(QualifiedName.class) Object superNames, @QNameId int qname, int fileId) throws IOException { int flags = checkFlags(mods, owner, info.getType() == IndexTree.BYTECODE); - @CompactArray(QualifiedName.class) Object supers = internSupers(mods, superNames); + @CompactArray(QualifiedName.class) Object supers = handleSpecialSupers(mods, superNames); ClassSymbol classSymbol = mySymbols.enterClass(fileId, stubId, flags, name, owner, info, supers, qname); if (uncompleted != null) { @@ -71,27 +72,18 @@ public class StubEnter { @Nullable @CompactArray(QualifiedName.class) - Object internSupers(int flags, int[] superNames) { + Object handleSpecialSupers(int flags, @CompactArray(QualifiedName.class) Object superNames) { if (BitUtil.isSet(flags, IndexTree.ANNOTATION)) { return myNameEnvironment.java_lang_annotation_Annotation; } - boolean isEnum = BitUtil.isSet(flags, IndexTree.ENUM); - if (superNames.length == 0) { - return isEnum ? myNameEnvironment.java_lang_Enum : null; - } - if (superNames.length == 1 && !isEnum) { - return new QualifiedName(superNames[0]); + if (BitUtil.isSet(flags, IndexTree.ENUM)) { + if (superNames == null) return myNameEnvironment.java_lang_Enum; + if (superNames instanceof QualifiedName) return new QualifiedName[]{(QualifiedName)superNames, myNameEnvironment.java_lang_Enum}; + return ArrayUtil.append((QualifiedName[])superNames, myNameEnvironment.java_lang_Enum); } - QualifiedName[] array = new QualifiedName[superNames.length + (isEnum ? 1 : 0)]; - for (int i = 0; i < superNames.length; i++) { - array[i] = new QualifiedName(superNames[i]); - } - if (isEnum) { - array[array.length - 1] = myNameEnvironment.java_lang_Enum; - } - return array; + return superNames; } public void connect1() { diff --git a/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/StubHierarchyConnector.java b/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/StubHierarchyConnector.java index 2373dcc3a28f..8d8112ddec82 100644 --- a/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/StubHierarchyConnector.java +++ b/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/StubHierarchyConnector.java @@ -29,23 +29,6 @@ public class StubHierarchyConnector { myResolve = new StubResolver(symbols, this); } - private void resolveName(Symbol.ClassSymbol place, QualifiedName name, Set result) throws IncompleteHierarchyException { - if (place.isCompiled()) { - Symbol.ClassSymbol[] candidates = myResolve.findGlobalType(name.myId); - if (candidates.length == 0) { - throw new IncompleteHierarchyException(); - } - - Collections.addAll(result, candidates); - } else { - for (Symbol symbol : myResolve.resolveBase(place, name.myId, false)) { - if (symbol instanceof Symbol.ClassSymbol) { - result.add((Symbol.ClassSymbol)symbol); - } - } - } - } - void connect(Symbol sym) { Symbol.ClassSymbol c = (Symbol.ClassSymbol) sym; @@ -65,10 +48,10 @@ public class StubHierarchyConnector { try { if (supers instanceof QualifiedName[]) { for (QualifiedName name : (QualifiedName[])supers) { - resolveName(c, name, supertypes); + name.resolveCandidates(myResolve, c, supertypes); } } else { - resolveName(c, (QualifiedName)supers, supertypes); + ((QualifiedName)supers).resolveCandidates(myResolve, c, supertypes); } } catch (IncompleteHierarchyException ignore) { 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 a2320eb8334d..3d65c3e2ecbb 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 @@ -35,21 +35,10 @@ public class StubResolver { } // resolve class `sym` extends/implements `baseId` - Set resolveBase(Symbol.ClassSymbol sym, @QNameId int name, boolean processPackages) throws IncompleteHierarchyException { - @QNameId int prefix = myNameEnvironment.prefixId(name); - @ShortName int shortName = myNameEnvironment.shortName(name); - if (prefix == NameEnvironment.NO_NAME) { - Set result = findIdent(sym.myOwner, sym.myUnitInfo, shortName, processPackages); - if (result.isEmpty()) { - throw IncompleteHierarchyException.INSTANCE; - } - return result; - } - - Set prev = resolveBase(sym, prefix, true); - Set result = new HashSet<>(); - for (Symbol symbol : prev) { - selectSym(symbol, shortName, processPackages, result); + Set resolveBase(Symbol.ClassSymbol sym, @ShortName int[] qname) throws IncompleteHierarchyException { + Set result = resolveUnqualified(sym, qname[0], qname.length > 1); + for (int i = 1; i < qname.length; i++) { + result = processQualifier(result, qname[i], i != qname.length - 1); } if (result.isEmpty()) { throw IncompleteHierarchyException.INSTANCE; @@ -57,6 +46,22 @@ public class StubResolver { return result; } + Set resolveUnqualified(Symbol.ClassSymbol sym, @ShortName final int shortName, boolean processPackages) throws IncompleteHierarchyException { + Set symbols = findIdent(sym.myOwner, sym.myUnitInfo, shortName, processPackages); + if (symbols.isEmpty()) { + throw IncompleteHierarchyException.INSTANCE; + } + return symbols; + } + + private Set processQualifier(Set contextResults, @ShortName final int shortName, final boolean processPackages) throws IncompleteHierarchyException { + Set result = new HashSet<>(); + for (Symbol symbol : contextResults) { + selectSym(symbol, shortName, processPackages, result); + } + return result; + } + @NotNull private Set findIdent(Symbol startScope, UnitInfo info, @ShortName int name, boolean processPackages) throws IncompleteHierarchyException { Set result = new HashSet();