mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-18 09:34:34 +07:00
a more compact storage for stub hierarchy names
This commit is contained in:
@@ -30,11 +30,7 @@ public class Imports {
|
||||
return (int)(importMask >>> 32);
|
||||
}
|
||||
|
||||
public static QualifiedName getFullName(long importMask, NameEnvironment nameEnvironment) {
|
||||
return nameEnvironment.qualifiedName(getFullNameId(importMask));
|
||||
}
|
||||
|
||||
private static int getFullNameId(long importMask) {
|
||||
static int getFullNameId(long importMask) {
|
||||
int fullNameId = (int)importMask;
|
||||
fullNameId &= mask;
|
||||
return fullNameId;
|
||||
@@ -48,8 +44,8 @@ public class Imports {
|
||||
return BitUtil.isSet(importMask, staticMask);
|
||||
}
|
||||
|
||||
public static long mkImport(QualifiedName fullname, boolean importStatic, boolean onDemand, int alias) {
|
||||
long lower = fullname.myId;
|
||||
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;
|
||||
|
||||
@@ -16,60 +16,71 @@
|
||||
package com.intellij.psi.stubsHierarchy.impl;
|
||||
|
||||
import com.intellij.openapi.util.UserDataHolderBase;
|
||||
import com.intellij.psi.CommonClassNames;
|
||||
import com.intellij.psi.impl.java.stubs.hierarchy.IndexTree;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import gnu.trove.TIntArrayList;
|
||||
import gnu.trove.TLongIntHashMap;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class NameEnvironment extends UserDataHolderBase {
|
||||
class NameEnvironment extends UserDataHolderBase {
|
||||
public static final int OBJECT_NAME = IndexTree.hashIdentifier("Object");
|
||||
public final QualifiedName empty;
|
||||
public final QualifiedName java_lang;
|
||||
public static final int NO_NAME = 0;
|
||||
@QNameId public final int java_lang;
|
||||
public final QualifiedName java_lang_Enum;
|
||||
public final QualifiedName annotation;
|
||||
public final NamesEnumerator myNamesEnumerator;
|
||||
public final QualifiedName java_lang_annotation_Annotation;
|
||||
|
||||
public NameEnvironment() {
|
||||
myNamesEnumerator = new NamesEnumerator();
|
||||
empty = myNamesEnumerator.getFullName(new int[]{}, true);
|
||||
java_lang = fromString("java.lang", true);
|
||||
java_lang_Enum = fromString("java.lang.Enum", true);
|
||||
annotation = fromString("java.lang.annotation.Annotation", true);
|
||||
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(fromString(CommonClassNames.JAVA_LANG_ENUM));
|
||||
java_lang_annotation_Annotation = new QualifiedName(fromString(CommonClassNames.JAVA_LANG_ANNOTATION_ANNOTATION));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public QualifiedName fromString(String s, boolean create) {
|
||||
return myNamesEnumerator.getFullName(IndexTree.hashQualifiedName(s), create);
|
||||
@QNameId
|
||||
int fromString(String s) {
|
||||
return internQualifiedName(IndexTree.hashQualifiedName(s));
|
||||
}
|
||||
|
||||
public QualifiedName prefix(QualifiedName name) {
|
||||
if (name.myComponents.length <= 1) {
|
||||
return empty;
|
||||
@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;
|
||||
}
|
||||
|
||||
@QNameId int internQualifiedName(@ShortName int[] qname) {
|
||||
int id = 0;
|
||||
for (int shortName : qname) {
|
||||
id = qualifiedName(id, shortName);
|
||||
}
|
||||
return myNamesEnumerator.getFullName(Arrays.copyOf(name.myComponents, name.myComponents.length - 1), true);
|
||||
return id;
|
||||
}
|
||||
|
||||
public QualifiedName qualifiedName(int id) {
|
||||
return myNamesEnumerator.qualifiedName(id);
|
||||
@QNameId int qualifiedName(@QNameId int prefix, @ShortName int shortName) {
|
||||
int existing = findExistingName(prefix, shortName);
|
||||
return existing >= 0 ? existing : addName(prefix, shortName);
|
||||
}
|
||||
|
||||
public int shortName(QualifiedName name) {
|
||||
int[] ids = name.myComponents;
|
||||
return ids[ids.length - 1];
|
||||
private int addName(@QNameId int stemId, @ShortName int suffix) {
|
||||
int newId = mySuffixes.size();
|
||||
mySuffixes.add(suffix);
|
||||
myStems.add(stemId);
|
||||
myConcatenations.put(pack(stemId, suffix), newId);
|
||||
return newId;
|
||||
}
|
||||
|
||||
public QualifiedName qualifiedName(QualifiedName prefix, int shortName, boolean create) {
|
||||
if (shortName == NamesEnumerator.NO_NAME)
|
||||
return null;
|
||||
if (prefix == null || prefix.isEmpty())
|
||||
return myNamesEnumerator.getFullName(new int[]{shortName}, create);
|
||||
|
||||
int[] ids = Arrays.copyOf(prefix.myComponents, prefix.myComponents.length + 1);
|
||||
ids[ids.length - 1] = shortName;
|
||||
return myNamesEnumerator.getFullName(ids, create);
|
||||
}
|
||||
|
||||
QualifiedName concat(int[] ids, boolean create) {
|
||||
return myNamesEnumerator.getFullName(ids, create);
|
||||
private static long pack(@QNameId int stemId, @ShortName int suffix) {
|
||||
return ((long)suffix << 32) + stemId;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.psi.stubsHierarchy.impl;
|
||||
|
||||
import gnu.trove.TObjectHashingStrategy;
|
||||
import gnu.trove.TObjectIntHashMap;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class NamesEnumerator {
|
||||
final static int NO_NAME = 0;
|
||||
|
||||
private final TObjectIntHashMap<int[]> myFullNameMap = new TObjectIntHashMap<int[]>(new TObjectHashingStrategy<int[]>() {
|
||||
@Override
|
||||
public int computeHashCode(int[] object) {
|
||||
return Arrays.hashCode(object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(int[] o1, int[] o2) {
|
||||
return Arrays.equals(o1, o2);
|
||||
}
|
||||
});
|
||||
private QualifiedName[] myQualifiedNames = new QualifiedName[0x8000];
|
||||
|
||||
QualifiedName qualifiedName(int id) {
|
||||
return myQualifiedNames[id];
|
||||
}
|
||||
|
||||
public QualifiedName getFullName(int[] ids, boolean create) {
|
||||
int id = myFullNameMap.get(ids);
|
||||
if (id == 0 && create) {
|
||||
id = myFullNameMap.size() + 1;
|
||||
myFullNameMap.put(ids, id);
|
||||
ensureFullCapacity(id);
|
||||
myQualifiedNames[id] = new QualifiedName(id, ids);
|
||||
}
|
||||
return myQualifiedNames[id];
|
||||
}
|
||||
|
||||
|
||||
private void ensureFullCapacity(int maxIndex) {
|
||||
if (maxIndex >= myQualifiedNames.length) {
|
||||
int newLength = calculateNewLength(myQualifiedNames.length, maxIndex);
|
||||
QualifiedName[] names1 = new QualifiedName[newLength];
|
||||
System.arraycopy(myQualifiedNames, 0, names1, 0, myQualifiedNames.length);
|
||||
myQualifiedNames = names1;
|
||||
}
|
||||
}
|
||||
|
||||
private static int calculateNewLength(int currentLength, int maxIndex) {
|
||||
while (currentLength < maxIndex + 1)
|
||||
currentLength *= 2;
|
||||
return currentLength;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -15,33 +15,21 @@
|
||||
*/
|
||||
package com.intellij.psi.stubsHierarchy.impl;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public final class QualifiedName {
|
||||
public static final QualifiedName[] EMPTY_ARRAY = new QualifiedName[0];
|
||||
|
||||
// unique id of this full name
|
||||
final class QualifiedName {
|
||||
public final int myId;
|
||||
// ids of parts of this name
|
||||
public final int[] myComponents;
|
||||
|
||||
QualifiedName(int id, int[] components) {
|
||||
QualifiedName(int id) {
|
||||
this.myId = id;
|
||||
this.myComponents = components;
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return myComponents.length == 0;
|
||||
return myId == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o instanceof QualifiedName) {
|
||||
QualifiedName other = (QualifiedName)o;
|
||||
return myId == other.myId && Arrays.equals(myComponents, other.myComponents);
|
||||
}
|
||||
return false;
|
||||
return o instanceof QualifiedName && myId == ((QualifiedName)o).myId;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -71,7 +71,7 @@ public class SingleClassHierarchy extends ClassHierarchy {
|
||||
private static BitSet calcAnonymous(ClassSymbol[] classSymbols) {
|
||||
BitSet answer = new BitSet();
|
||||
for (ClassSymbol symbol : classSymbols) {
|
||||
if (!symbol.isHierarchyIncomplete() && symbol.myShortName == NamesEnumerator.NO_NAME) {
|
||||
if (!symbol.isHierarchyIncomplete() && symbol.myShortName == NameEnvironment.NO_NAME) {
|
||||
answer.set(symbol.myAnchorId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,10 +38,8 @@ public class StubEnter {
|
||||
}
|
||||
|
||||
void unitEnter(IndexTree.Unit unit, int fileId) {
|
||||
PackageSymbol pkg = unit.myPackageName.length > 0
|
||||
? mySymbols.enterPackage(myNameEnvironment.myNamesEnumerator.getFullName(unit.myPackageName, true))
|
||||
: mySymbols.myRootPackage;
|
||||
enter(unit.myDecls, UnitInfo.mkUnitInfo(unit.myUnitType, internImports(unit)), pkg, pkg.myQualifiedName, fileId);
|
||||
@QNameId int pkgName = unit.myPackageName.length > 0 ? myNameEnvironment.internQualifiedName(unit.myPackageName) : 0;
|
||||
enter(unit.myDecls, UnitInfo.mkUnitInfo(unit.myUnitType, internImports(unit)), mySymbols.enterPackage(pkgName), pkgName, fileId);
|
||||
}
|
||||
|
||||
private long[] internImports(IndexTree.Unit unit) {
|
||||
@@ -53,17 +51,17 @@ public class StubEnter {
|
||||
}
|
||||
|
||||
private long processImport(IndexTree.Import anImport) {
|
||||
QualifiedName fullname = myNameEnvironment.myNamesEnumerator.getFullName(anImport.myFullname, true);
|
||||
int fullname = myNameEnvironment.internQualifiedName(anImport.myFullname);
|
||||
return Imports.mkImport(fullname, anImport.myStaticImport, anImport.myOnDemand, anImport.myAlias);
|
||||
}
|
||||
|
||||
private void enter(IndexTree.ClassDecl[] trees, UnitInfo info, Symbol owner, @Nullable QualifiedName ownerName, int fileId) {
|
||||
private void enter(IndexTree.ClassDecl[] trees, UnitInfo info, Symbol owner, @QNameId int ownerName, int fileId) {
|
||||
for (IndexTree.ClassDecl tree : trees) {
|
||||
enter(tree, info, owner, ownerName, fileId);
|
||||
}
|
||||
}
|
||||
|
||||
private ClassSymbol[] enter(IndexTree.Decl[] trees, UnitInfo info, Symbol owner, @Nullable QualifiedName ownerName, int fileId) {
|
||||
private ClassSymbol[] enter(IndexTree.Decl[] trees, UnitInfo info, Symbol owner, @QNameId int ownerName, int fileId) {
|
||||
ClassSymbol[] members = new ClassSymbol[trees.length];
|
||||
int i = 0;
|
||||
for (IndexTree.Decl tree : trees) {
|
||||
@@ -81,7 +79,7 @@ public class StubEnter {
|
||||
return members;
|
||||
}
|
||||
|
||||
private ClassSymbol enter(IndexTree.Decl tree, UnitInfo info, Symbol owner, QualifiedName ownerName, int fileId) {
|
||||
private ClassSymbol enter(IndexTree.Decl tree, UnitInfo info, Symbol owner, @QNameId int ownerName, int fileId) {
|
||||
if (tree instanceof IndexTree.ClassDecl) {
|
||||
return classEnter((IndexTree.ClassDecl)tree, info, owner, ownerName, fileId);
|
||||
}
|
||||
@@ -92,20 +90,20 @@ public class StubEnter {
|
||||
return null;
|
||||
}
|
||||
|
||||
private void memberEnter(IndexTree.MemberDecl tree, UnitInfo info, Symbol owner, @Nullable QualifiedName ownerName, int fileId) {
|
||||
private void memberEnter(IndexTree.MemberDecl tree, UnitInfo info, Symbol owner, @QNameId int ownerName, int fileId) {
|
||||
MemberSymbol mc = new MemberSymbol(owner);
|
||||
mc.setMembers(enter(tree.myDecls, info, mc, ownerName, fileId));
|
||||
}
|
||||
|
||||
private ClassSymbol classEnter(IndexTree.ClassDecl tree, UnitInfo info, Symbol owner, @Nullable QualifiedName ownerName, int fileId) {
|
||||
private ClassSymbol classEnter(IndexTree.ClassDecl tree, UnitInfo info, Symbol owner, @QNameId int ownerName, int fileId) {
|
||||
int flags = checkFlags(tree.myMods, owner);
|
||||
if (info.getType() == IndexTree.BYTECODE) {
|
||||
flags |= IndexTree.COMPILED;
|
||||
}
|
||||
|
||||
int name = tree.myName;
|
||||
QualifiedName qname = name == NamesEnumerator.NO_NAME || ownerName == null ? null
|
||||
: myNameEnvironment.qualifiedName(ownerName, name, true);
|
||||
@QNameId int qname = name == NameEnvironment.NO_NAME || ownerName < 0 ? -1
|
||||
: myNameEnvironment.qualifiedName(ownerName, name);
|
||||
@CompactArray(QualifiedName.class) Object supers = internSupers(tree.myMods, tree.mySupers);
|
||||
ClassSymbol classSymbol = mySymbols.enterClass(fileId, tree.myStubId, flags, name, owner, info, supers, qname);
|
||||
|
||||
@@ -122,7 +120,7 @@ public class StubEnter {
|
||||
@CompactArray(QualifiedName.class)
|
||||
private Object internSupers(int flags, int[][] superNames) {
|
||||
if (BitUtil.isSet(flags, IndexTree.ANNOTATION)) {
|
||||
return myNameEnvironment.annotation;
|
||||
return myNameEnvironment.java_lang_annotation_Annotation;
|
||||
}
|
||||
|
||||
boolean isEnum = BitUtil.isSet(flags, IndexTree.ENUM);
|
||||
@@ -130,12 +128,12 @@ public class StubEnter {
|
||||
return isEnum ? myNameEnvironment.java_lang_Enum : null;
|
||||
}
|
||||
if (superNames.length == 1 && !isEnum) {
|
||||
return myNameEnvironment.concat(superNames[0], true);
|
||||
return new QualifiedName(myNameEnvironment.internQualifiedName(superNames[0]));
|
||||
}
|
||||
|
||||
QualifiedName[] array = new QualifiedName[superNames.length + (isEnum ? 1 : 0)];
|
||||
for (int i = 0; i < superNames.length; i++) {
|
||||
array[i] = myNameEnvironment.concat(superNames[i], true);
|
||||
array[i] = new QualifiedName(myNameEnvironment.internQualifiedName(superNames[i]));
|
||||
}
|
||||
if (isEnum) {
|
||||
array[array.length - 1] = myNameEnvironment.java_lang_Enum;
|
||||
|
||||
@@ -31,14 +31,14 @@ public class StubHierarchyConnector {
|
||||
|
||||
private void resolveName(Symbol.ClassSymbol place, QualifiedName name, Set<Symbol.ClassSymbol> result) throws IncompleteHierarchyException {
|
||||
if (place.isCompiled()) {
|
||||
Symbol.ClassSymbol[] candidates = myResolve.findGlobalType(name);
|
||||
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.myComponents)) {
|
||||
for (Symbol symbol : myResolve.resolveBase(place, name.myId, false)) {
|
||||
if (symbol instanceof Symbol.ClassSymbol) {
|
||||
result.add((Symbol.ClassSymbol)symbol);
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ package com.intellij.psi.stubsHierarchy.impl;
|
||||
|
||||
import com.intellij.psi.impl.java.stubs.hierarchy.IndexTree;
|
||||
import com.intellij.util.BitUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -36,16 +37,22 @@ public class StubResolver {
|
||||
}
|
||||
|
||||
// resolve class `sym` extends/implements `baseId`
|
||||
Set<Symbol> resolveBase(Symbol.ClassSymbol sym, int[] baseId) throws IncompleteHierarchyException {
|
||||
Set<Symbol> result = findIdent(sym.myOwner, sym.myUnitInfo, baseId[0], baseId.length > 1);
|
||||
for (int i = 1; i < baseId.length; i++) {
|
||||
Set<Symbol> prev = result;
|
||||
int k = (i == baseId.length - 1) ? IndexTree.CLASS : IndexTree.CLASS | IndexTree.PACKAGE;
|
||||
|
||||
result = new HashSet<>();
|
||||
for (Symbol symbol : prev) {
|
||||
selectSym(symbol, baseId[i], k, result);
|
||||
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;
|
||||
}
|
||||
|
||||
int k = processPackages ? IndexTree.CLASS | IndexTree.PACKAGE : IndexTree.CLASS;
|
||||
Set<Symbol> prev = resolveBase(sym, prefix, true);
|
||||
Set<Symbol> result = new HashSet<>();
|
||||
for (Symbol symbol : prev) {
|
||||
selectSym(symbol, shortName, k, result);
|
||||
}
|
||||
if (result.isEmpty()) {
|
||||
throw IncompleteHierarchyException.INSTANCE;
|
||||
@@ -54,15 +61,15 @@ public class StubResolver {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Set<Symbol> findIdent(Symbol startScope, UnitInfo info, int name, boolean processPackages) throws IncompleteHierarchyException {
|
||||
private Set<Symbol> findIdent(Symbol startScope, UnitInfo info, @ShortName int name, boolean processPackages) throws IncompleteHierarchyException {
|
||||
Set<Symbol> result = new HashSet<Symbol>();
|
||||
findType(startScope, name, result);
|
||||
findGlobalType(info, name, result);
|
||||
|
||||
if (processPackages) {
|
||||
Symbol.PackageSymbol pkg = mySymbols.getPackage(myNameEnvironment.qualifiedName(null, name, false));
|
||||
if (pkg != null)
|
||||
result.add(pkg);
|
||||
@QNameId int nameId = myNameEnvironment.findExistingName(0, name);
|
||||
Symbol.PackageSymbol pkg = nameId < 0 ? null : mySymbols.getPackage(nameId);
|
||||
ContainerUtil.addIfNotNull(result, pkg);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -76,16 +83,16 @@ public class StubResolver {
|
||||
}
|
||||
|
||||
// resolving `receiver.name`
|
||||
private void selectSym(Symbol receiver, int name, int kind, Set<Symbol> symbols) throws IncompleteHierarchyException {
|
||||
private void selectSym(Symbol receiver, @ShortName int name, int kind, Set<Symbol> symbols) throws IncompleteHierarchyException {
|
||||
if (receiver.isPackage())
|
||||
findIdentInPackage((Symbol.PackageSymbol)receiver, name, kind, symbols);
|
||||
else
|
||||
findMemberType(receiver, name, symbols);
|
||||
}
|
||||
|
||||
private void findIdentInPackage(Symbol.PackageSymbol pck, int name, int kind, Set<Symbol> symbols) {
|
||||
QualifiedName fullname = mySymbols.myNameEnvironment.qualifiedName(pck.myQualifiedName, name, false);
|
||||
if (fullname == null) {
|
||||
private void findIdentInPackage(Symbol.PackageSymbol pck, @ShortName int name, int kind, Set<Symbol> symbols) {
|
||||
@QNameId int fullname = mySymbols.myNameEnvironment.findExistingName(pck.myQualifiedName, name);
|
||||
if (fullname < 0) {
|
||||
return;
|
||||
}
|
||||
if (BitUtil.isSet(kind, IndexTree.PACKAGE)) {
|
||||
@@ -94,11 +101,11 @@ public class StubResolver {
|
||||
symbols.add(pkg);
|
||||
}
|
||||
if (BitUtil.isSet(kind, IndexTree.CLASS)) {
|
||||
Collections.addAll(symbols, loadClass(fullname));
|
||||
Collections.addAll(symbols, findGlobalType(fullname));
|
||||
}
|
||||
}
|
||||
|
||||
private void findMemberType(Symbol s, int name, Set<Symbol> symbols) throws IncompleteHierarchyException {
|
||||
private void findMemberType(Symbol s, @ShortName int name, Set<Symbol> symbols) throws IncompleteHierarchyException {
|
||||
if (s.isClass()) {
|
||||
processInheritedMembers((Symbol.ClassSymbol)s, name, false, symbols, null);
|
||||
} else {
|
||||
@@ -107,7 +114,7 @@ public class StubResolver {
|
||||
}
|
||||
|
||||
private void processInheritedMembers(Symbol.ClassSymbol s,
|
||||
int name,
|
||||
@ShortName int name,
|
||||
boolean requireStatic,
|
||||
Set<Symbol> symbols,
|
||||
@Nullable Set<Symbol> processed) throws IncompleteHierarchyException {
|
||||
@@ -128,23 +135,19 @@ public class StubResolver {
|
||||
}
|
||||
}
|
||||
|
||||
private Symbol.ClassSymbol[] loadClass(@NotNull QualifiedName fqn) {
|
||||
return mySymbols.loadClass(fqn);
|
||||
public Symbol.ClassSymbol[] findGlobalType(@QNameId int nameId) {
|
||||
return mySymbols.loadClass(nameId);
|
||||
}
|
||||
|
||||
public Symbol.ClassSymbol[] findGlobalType(@NotNull QualifiedName name) {
|
||||
return loadClass(name);
|
||||
}
|
||||
|
||||
private void findGlobalType(UnitInfo info, int name, Set<Symbol> symbols) throws IncompleteHierarchyException {
|
||||
private void findGlobalType(UnitInfo info, @ShortName int name, Set<Symbol> symbols) throws IncompleteHierarchyException {
|
||||
for (long anImport : Translator.getDefaultImports(info.getType(), myNameEnvironment))
|
||||
handleImport(anImport, name, symbols);
|
||||
for (long anImport : info.getImports())
|
||||
handleImport(anImport, name, symbols);
|
||||
}
|
||||
|
||||
public void handleImport(long tree, int name, Set<Symbol> symbols) throws IncompleteHierarchyException {
|
||||
QualifiedName fullname = Imports.getFullName(tree, myNameEnvironment);
|
||||
public void handleImport(long tree, @ShortName int name, Set<Symbol> symbols) throws IncompleteHierarchyException {
|
||||
@QNameId int fullname = Imports.getFullNameId(tree);
|
||||
if (Imports.isOnDemand(tree)) {
|
||||
if (Imports.isStatic(tree)) {
|
||||
for (Symbol.ClassSymbol p : findGlobalType(fullname))
|
||||
@@ -155,12 +158,12 @@ public class StubResolver {
|
||||
}
|
||||
}
|
||||
else {
|
||||
QualifiedName prefix = myNameEnvironment.prefix(fullname);
|
||||
if (prefix.isEmpty()) {
|
||||
@QNameId int prefix = myNameEnvironment.prefixId(fullname);
|
||||
if (prefix == 0) {
|
||||
return;
|
||||
}
|
||||
int shortName = myNameEnvironment.shortName(fullname);
|
||||
int alias = Imports.getAlias(tree);
|
||||
@ShortName int shortName = myNameEnvironment.shortName(fullname);
|
||||
@ShortName int alias = Imports.getAlias(tree);
|
||||
boolean shouldImport = ((alias & name) == name) || shortName == name;
|
||||
if (!shouldImport)
|
||||
return;
|
||||
@@ -175,22 +178,19 @@ public class StubResolver {
|
||||
}
|
||||
|
||||
// handling of `import prefix.*`
|
||||
private void importAll(@NotNull final QualifiedName prefix, int suffix, final Set<Symbol> symbols) {
|
||||
|
||||
QualifiedName fullname = myNameEnvironment.qualifiedName(prefix, suffix, false);
|
||||
// existing only
|
||||
if (fullname != null) {
|
||||
Symbol.ClassSymbol[] ss = findGlobalType(fullname);
|
||||
Collections.addAll(symbols, ss);
|
||||
}
|
||||
private void importAll(@QNameId int prefix, @ShortName int suffix, final Set<Symbol> symbols) {
|
||||
@QNameId int fullname = myNameEnvironment.findExistingName(prefix, suffix);
|
||||
if (fullname >= 0) {
|
||||
Collections.addAll(symbols, findGlobalType(fullname));
|
||||
}
|
||||
}
|
||||
|
||||
// handling of import static `tsym.name` as
|
||||
private void importNamedStatic(final Symbol.ClassSymbol tsym, final int name, final Set<Symbol> symbols) throws IncompleteHierarchyException {
|
||||
private void importNamedStatic(final Symbol.ClassSymbol tsym, @ShortName final int name, final Set<Symbol> symbols) throws IncompleteHierarchyException {
|
||||
processInheritedMembers(tsym, name, true, symbols, null);
|
||||
}
|
||||
|
||||
private static void processMembers(Symbol.ClassSymbol[] members, int name, Set<Symbol> symbols, boolean requireStatic) {
|
||||
private static void processMembers(Symbol.ClassSymbol[] members, @ShortName int name, Set<Symbol> symbols, boolean requireStatic) {
|
||||
int index = getIndex(name, members);
|
||||
if (index < 0) return;
|
||||
|
||||
|
||||
@@ -74,9 +74,9 @@ public abstract class Symbol {
|
||||
}
|
||||
|
||||
public static class PackageSymbol extends Symbol {
|
||||
final QualifiedName myQualifiedName;
|
||||
@QNameId final int myQualifiedName;
|
||||
|
||||
public PackageSymbol(Symbol owner, QualifiedName fullname, int name) {
|
||||
public PackageSymbol(Symbol owner, @QNameId int fullname, int name) {
|
||||
super(IndexTree.PACKAGE, owner, name);
|
||||
myQualifiedName = fullname;
|
||||
}
|
||||
@@ -186,7 +186,7 @@ public abstract class Symbol {
|
||||
@CompactArray(ClassSymbol.class) private Object myMembers = null;
|
||||
|
||||
MemberSymbol(Symbol owner) {
|
||||
super(IndexTree.MEMBER, owner, NamesEnumerator.NO_NAME);
|
||||
super(IndexTree.MEMBER, owner, NameEnvironment.NO_NAME);
|
||||
}
|
||||
|
||||
MemberSymbol(int flags, Symbol owner, int name) {
|
||||
|
||||
@@ -21,35 +21,29 @@ public class Symbols {
|
||||
private Object[] myClassSymbolsByNameId = new Object[0x8000];
|
||||
|
||||
protected Symbols() {
|
||||
myRootPackage = new PackageSymbol(null, myNameEnvironment.empty, NamesEnumerator.NO_NAME);
|
||||
myPackages.put(myNameEnvironment.empty.myId, myRootPackage);
|
||||
myRootPackage = new PackageSymbol(null, 0, NameEnvironment.NO_NAME);
|
||||
myPackages.put(0, myRootPackage);
|
||||
}
|
||||
|
||||
public PackageSymbol enterPackage(QualifiedName qualifiedName) {
|
||||
PackageSymbol p = myPackages.get(qualifiedName.myId);
|
||||
public PackageSymbol enterPackage(@QNameId int qualifiedName) {
|
||||
PackageSymbol p = myPackages.get(qualifiedName);
|
||||
if (p == null) {
|
||||
PackageSymbol owner = enterPackage(myNameEnvironment.prefix(qualifiedName));
|
||||
PackageSymbol owner = enterPackage(myNameEnvironment.prefixId(qualifiedName));
|
||||
int shortName = myNameEnvironment.shortName(qualifiedName);
|
||||
p = new PackageSymbol(owner, qualifiedName, shortName);
|
||||
myPackages.put(qualifiedName.myId, p);
|
||||
myPackages.put(qualifiedName, p);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PackageSymbol getPackage(QualifiedName qualifiedName) {
|
||||
if (qualifiedName == null)
|
||||
return null;
|
||||
return myPackages.get(qualifiedName.myId);
|
||||
PackageSymbol getPackage(@QNameId int qualifiedName) {
|
||||
return myPackages.get(qualifiedName);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ClassSymbol[] loadClass(@NotNull QualifiedName qualifiedName) {
|
||||
int i = qualifiedName.myId;
|
||||
if (i >= myClassSymbolsByNameId.length) {
|
||||
return ClassSymbol.EMPTY_ARRAY;
|
||||
}
|
||||
return getClassSymbols(i);
|
||||
ClassSymbol[] loadClass(@QNameId int name) {
|
||||
return name >= myClassSymbolsByNameId.length ? ClassSymbol.EMPTY_ARRAY : getClassSymbols(name);
|
||||
}
|
||||
|
||||
private ClassSymbol[] getClassSymbols(int id) {
|
||||
@@ -70,12 +64,12 @@ public class Symbols {
|
||||
Symbol owner,
|
||||
UnitInfo info,
|
||||
@CompactArray(QualifiedName.class) Object supers,
|
||||
@Nullable QualifiedName qualifiedName) {
|
||||
@QNameId int qualifiedName) {
|
||||
int anchorId = myClassAnchors.registerClass(fileId, stubId);
|
||||
ClassSymbol c = new ClassSymbol(anchorId, flags, owner, shortName, info, supers);
|
||||
myClassSymbols.add(c);
|
||||
if (qualifiedName != null) {
|
||||
putClassByName(c, qualifiedName.myId);
|
||||
if (qualifiedName >= 0) {
|
||||
putClassByName(c, qualifiedName);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ public class Translator {
|
||||
|
||||
private static long[] createDefaultJavaImports(NameEnvironment nameEnvironment) {
|
||||
return new long[]{
|
||||
Imports.mkImport(nameEnvironment.fromString("java.lang", true), false, true, 0)
|
||||
Imports.mkImport(nameEnvironment.fromString("java.lang"), false, true, 0)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -48,14 +48,14 @@ public class Translator {
|
||||
|
||||
private static long[] createDefaultGroovyImports(NameEnvironment nameEnvironment) {
|
||||
return new long[] {
|
||||
Imports.mkImport(nameEnvironment.fromString("java.lang", true), false, true, 0),
|
||||
Imports.mkImport(nameEnvironment.fromString("java.util", true), false, true, 0),
|
||||
Imports.mkImport(nameEnvironment.fromString("java.io", true), false, true, 0),
|
||||
Imports.mkImport(nameEnvironment.fromString("java.net", true), false, true, 0),
|
||||
Imports.mkImport(nameEnvironment.fromString("groovy.lang", true), false, true, 0),
|
||||
Imports.mkImport(nameEnvironment.fromString("groovy.util", true), false, true, 0),
|
||||
Imports.mkImport(nameEnvironment.fromString("java.math.BigInteger", true), false, true, 0),
|
||||
Imports.mkImport(nameEnvironment.fromString("java.math.BigDecimal", true), false, true, 0),
|
||||
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),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
+20
-3
@@ -15,8 +15,12 @@
|
||||
*/
|
||||
package com.intellij.psi.stubsHierarchy.impl;
|
||||
|
||||
import com.intellij.psi.impl.java.stubs.hierarchy.IndexTree;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* This annotation exists for documentation purposes only.<p/>
|
||||
@@ -24,10 +28,23 @@ import java.lang.annotation.RetentionPolicy;
|
||||
* The value annotated with this annotation is used to save memory when storing mostly-singular or empty collections.
|
||||
* For empty collection, 'null' value is used. For one-element collection, the value is the single element. Otherwise,
|
||||
* an array is used. Possible component types are specified in the annotation value.
|
||||
*
|
||||
* @author peter
|
||||
*/
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface CompactArray {
|
||||
@Target(ElementType.TYPE_USE)
|
||||
@interface CompactArray {
|
||||
Class[] value();
|
||||
}
|
||||
|
||||
/**
|
||||
* int id of a qualified name in a {@link NameEnvironment}
|
||||
*/
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@Target(ElementType.TYPE_USE)
|
||||
@interface QNameId { }
|
||||
|
||||
/**
|
||||
* int hash of a qualified name part, produced by {@link IndexTree#hashIdentifier(String)}
|
||||
*/
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@Target(ElementType.TYPE_USE)
|
||||
@interface ShortName { }
|
||||
Reference in New Issue
Block a user