avoid qualified name destructuring during stub hierarchy resolve in src file data

This commit is contained in:
peter
2016-07-05 19:26:12 +02:00
parent 9747035c79
commit 5ed4364149
6 changed files with 111 additions and 71 deletions
@@ -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
@@ -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<Symbol.ClassSymbol> 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<Symbol.ClassSymbol> 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<Symbol.ClassSymbol> 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<Symbol.ClassSymbol> result)
throws IncompleteHierarchyException {
Symbol.ClassSymbol[] candidates = resolver.findGlobalType(id);
if (candidates.length == 0) {
throw new IncompleteHierarchyException();
}
Collections.addAll(result, candidates);
}
}
}
@@ -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 {
@@ -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() {
@@ -29,23 +29,6 @@ public class StubHierarchyConnector {
myResolve = new StubResolver(symbols, this);
}
private void resolveName(Symbol.ClassSymbol place, QualifiedName name, Set<Symbol.ClassSymbol> 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) {
@@ -35,21 +35,10 @@ public class StubResolver {
}
// resolve class `sym` extends/implements `baseId`
Set<Symbol> 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<Symbol> result = findIdent(sym.myOwner, sym.myUnitInfo, shortName, processPackages);
if (result.isEmpty()) {
throw IncompleteHierarchyException.INSTANCE;
}
return result;
}
Set<Symbol> prev = resolveBase(sym, prefix, true);
Set<Symbol> result = new HashSet<>();
for (Symbol symbol : prev) {
selectSym(symbol, shortName, processPackages, result);
Set<Symbol> resolveBase(Symbol.ClassSymbol sym, @ShortName int[] qname) throws IncompleteHierarchyException {
Set<Symbol> 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<Symbol> resolveUnqualified(Symbol.ClassSymbol sym, @ShortName final int shortName, boolean processPackages) throws IncompleteHierarchyException {
Set<Symbol> symbols = findIdent(sym.myOwner, sym.myUnitInfo, shortName, processPackages);
if (symbols.isEmpty()) {
throw IncompleteHierarchyException.INSTANCE;
}
return symbols;
}
private Set<Symbol> processQualifier(Set<Symbol> contextResults, @ShortName final int shortName, final boolean processPackages) throws IncompleteHierarchyException {
Set<Symbol> result = new HashSet<>();
for (Symbol symbol : contextResults) {
selectSym(symbol, shortName, processPackages, result);
}
return result;
}
@NotNull
private Set<Symbol> findIdent(Symbol startScope, UnitInfo info, @ShortName int name, boolean processPackages) throws IncompleteHierarchyException {
Set<Symbol> result = new HashSet<Symbol>();