mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-18 09:34:34 +07:00
stub hierarchy: mark classes where we can't fully resolve hierarchy
they should be excluded from the hierarchy scope and usual PSI-based search should be used for them (in case they reference some JVM language unsupported by stub hierarchy)
This commit is contained in:
+12
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
* Copyright 2000-2016 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.
|
||||
@@ -15,6 +15,15 @@
|
||||
*/
|
||||
package com.intellij.psi.stubsHierarchy.impl;
|
||||
|
||||
public interface HierarchyConnector {
|
||||
void connect(Symbol sym);
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
class IncompleteHierarchyException extends Exception {
|
||||
@SuppressWarnings("ThrowableInstanceNeverThrown")
|
||||
public static final IncompleteHierarchyException INSTANCE = new IncompleteHierarchyException();
|
||||
|
||||
@Override
|
||||
public synchronized Throwable fillInStackTrace() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,6 @@ import gnu.trove.TIntHashSet;
|
||||
import gnu.trove.TIntStack;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
|
||||
/**
|
||||
* Compact representation of total hierarchy of JVM classes.
|
||||
@@ -144,7 +143,7 @@ public class SingleClassHierarchy {
|
||||
|
||||
for (int subTypeId = 0; subTypeId < n; subTypeId++) {
|
||||
ClassSymbol subType = classSymbols[subTypeId];
|
||||
for (ClassSymbol superType : subType.getSuperClasses()) {
|
||||
for (ClassSymbol superType : subType.rawSuperClasses()) {
|
||||
int superTypeId = superType.myClassAnchor.myId;
|
||||
subtypes[starts[superTypeId] + filled[superTypeId]] = subTypeId;
|
||||
filled[superTypeId] += 1;
|
||||
@@ -159,7 +158,7 @@ public class SingleClassHierarchy {
|
||||
int[] sizes = new int[n];
|
||||
for (int i = 1; i < n; i++) {
|
||||
ClassSymbol subType = classSymbols[i];
|
||||
for (ClassSymbol superType : subType.getSuperClasses()) {
|
||||
for (ClassSymbol superType : subType.rawSuperClasses()) {
|
||||
int superTypeId = superType.myClassAnchor.myId;
|
||||
sizes[superTypeId] += 1;
|
||||
}
|
||||
|
||||
+10
-5
@@ -20,7 +20,7 @@ import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
public class StubHierarchyConnector implements HierarchyConnector {
|
||||
public class StubHierarchyConnector {
|
||||
private final NameEnvironment myNameEnvironment;
|
||||
private final StubResolver myResolve;
|
||||
|
||||
@@ -29,7 +29,7 @@ public class StubHierarchyConnector implements HierarchyConnector {
|
||||
myResolve = new StubResolver(symbols);
|
||||
}
|
||||
|
||||
public void connect(Symbol sym) {
|
||||
void connect(Symbol sym) {
|
||||
Symbol.ClassSymbol c = (Symbol.ClassSymbol) sym;
|
||||
|
||||
if (c.myOwner instanceof Symbol.ClassSymbol) {
|
||||
@@ -44,12 +44,17 @@ public class StubHierarchyConnector implements HierarchyConnector {
|
||||
Collections.addAll(supertypes, myResolve.findGlobalType(name));
|
||||
}
|
||||
} else {
|
||||
Set<Symbol> based = myResolve.resolveBase(c, name.myComponents);
|
||||
supertypes.addAll(based);
|
||||
try {
|
||||
supertypes.addAll(myResolve.resolveBase(c, name.myComponents));
|
||||
}
|
||||
catch (IncompleteHierarchyException ignore) {
|
||||
c.markHierarchyIncomplete();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (c.myQualifiedName == myNameEnvironment.java_lang_Object) {
|
||||
if (c.myQualifiedName == myNameEnvironment.java_lang_Object || c.isHierarchyIncomplete()) {
|
||||
c.mySuperClasses = Symbol.ClassSymbol.EMPTY_ARRAY;
|
||||
} else {
|
||||
for (Iterator<Symbol> iter = supertypes.iterator(); iter.hasNext();) {
|
||||
|
||||
@@ -35,36 +35,30 @@ public class StubResolver {
|
||||
}
|
||||
|
||||
// resolve class `sym` extends/implements `baseId`
|
||||
public Set<Symbol> resolveBase(Symbol.ClassSymbol sym, int[] baseId) {
|
||||
Set<Symbol> prev = null;
|
||||
Set<Symbol> result = null;
|
||||
for (int i = 0; i < baseId.length; i++) {
|
||||
int name = baseId[i];
|
||||
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;
|
||||
if (i == 0) {
|
||||
result = findIdent(sym.myOwner, sym.myUnitInfo, name, k);
|
||||
} else {
|
||||
Set<Symbol> acc = new HashSet<Symbol>();
|
||||
for (Symbol symbol : prev) {
|
||||
selectSym(symbol, name, k, acc);;
|
||||
}
|
||||
result = acc;
|
||||
}
|
||||
prev = result;
|
||||
|
||||
result = new HashSet<>();
|
||||
for (Symbol symbol : prev) {
|
||||
selectSym(symbol, baseId[i], k, result);
|
||||
}
|
||||
}
|
||||
if (result.isEmpty()) {
|
||||
throw IncompleteHierarchyException.INSTANCE;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Set<Symbol> findIdent(Symbol startScope, UnitInfo info, int name, int kind) {
|
||||
private Set<Symbol> findIdent(Symbol startScope, UnitInfo info, int name, boolean processPackages) throws IncompleteHierarchyException {
|
||||
Set<Symbol> result = new HashSet<Symbol>();
|
||||
if (BitUtil.isSet(kind, IndexTree.CLASS)) {
|
||||
findType(startScope, name, result);
|
||||
findGlobalType(info, name, result);
|
||||
}
|
||||
findType(startScope, name, result);
|
||||
findGlobalType(info, name, result);
|
||||
|
||||
if (BitUtil.isSet(kind, IndexTree.PACKAGE)) {
|
||||
if (processPackages) {
|
||||
Symbol.PackageSymbol pkg = mySymbols.getPackage(myNameEnvironment.qualifiedName(null, name, false));
|
||||
if (pkg != null)
|
||||
result.add(pkg);
|
||||
@@ -72,7 +66,7 @@ public class StubResolver {
|
||||
return result;
|
||||
}
|
||||
|
||||
private void findType(Symbol startScope, int name, Set<Symbol> symbols) {
|
||||
private void findType(Symbol startScope, int name, Set<Symbol> symbols) throws IncompleteHierarchyException {
|
||||
// looking up
|
||||
for (Symbol s = startScope; s != null; s = s.myOwner)
|
||||
findMemberType(s, name, symbols, new HashSet<Symbol>());
|
||||
@@ -81,7 +75,7 @@ public class StubResolver {
|
||||
}
|
||||
|
||||
// resolving `receiver.name`
|
||||
private void selectSym(Symbol receiver, int name, int kind, Set<Symbol> symbols) {
|
||||
private void selectSym(Symbol receiver, int name, int kind, Set<Symbol> symbols) throws IncompleteHierarchyException {
|
||||
if (receiver.isPackage())
|
||||
findIdentInPackage((Symbol.PackageSymbol)receiver, name, kind, symbols);
|
||||
else
|
||||
@@ -103,7 +97,7 @@ public class StubResolver {
|
||||
}
|
||||
}
|
||||
|
||||
private static void findMemberType(Symbol s, int name, Set<Symbol> symbols, Set<Symbol> processed) {
|
||||
private static void findMemberType(Symbol s, int name, Set<Symbol> symbols, Set<Symbol> processed) throws IncompleteHierarchyException {
|
||||
if (!processed.add(s)) {
|
||||
return;
|
||||
}
|
||||
@@ -136,7 +130,8 @@ public class StubResolver {
|
||||
}
|
||||
}
|
||||
|
||||
private static void findInheritedMemberType(Symbol.ClassSymbol c, int name, Set<Symbol> symbols, Set<Symbol> processed) {
|
||||
private static void findInheritedMemberType(Symbol.ClassSymbol c, int name, Set<Symbol> symbols, Set<Symbol> processed)
|
||||
throws IncompleteHierarchyException {
|
||||
for (Symbol.ClassSymbol st : c.getSuperClasses())
|
||||
findMemberType(st, name, symbols, processed);
|
||||
}
|
||||
@@ -149,19 +144,19 @@ public class StubResolver {
|
||||
return loadClass(name);
|
||||
}
|
||||
|
||||
private void findGlobalType(UnitInfo info, int name, Set<Symbol> symbols) {
|
||||
private void findGlobalType(UnitInfo info, 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) {
|
||||
public void handleImport(long tree, int name, Set<Symbol> symbols) throws IncompleteHierarchyException {
|
||||
QualifiedName fullname = Import.getFullName(tree, myNameEnvironment);
|
||||
if (Import.isOnDemand(tree)) {
|
||||
if (Import.isStatic(tree)) {
|
||||
for (Symbol.ClassSymbol p : findGlobalType(fullname))
|
||||
importStaticAll(p, name, symbols);
|
||||
importNamedStatic(p, name, symbols);
|
||||
}
|
||||
else {
|
||||
importAll(fullname, name, symbols);
|
||||
@@ -198,25 +193,11 @@ public class StubResolver {
|
||||
}
|
||||
}
|
||||
|
||||
// handling of `import static tsym.*`
|
||||
private static void importStaticAll(final Symbol.ClassSymbol tsym, final int name, final Set<Symbol> symbols) {
|
||||
new Object() {
|
||||
Set<Symbol> processed = new HashSet<Symbol>();
|
||||
void importFrom(Symbol.ClassSymbol cs) {
|
||||
if (cs == null || !processed.add(cs))
|
||||
return;
|
||||
for (Symbol.ClassSymbol c : cs.getSuperClasses())
|
||||
importFrom(c);
|
||||
importMember(cs.members(), name, symbols, true);
|
||||
}
|
||||
}.importFrom(tsym);
|
||||
}
|
||||
|
||||
// handling of import static `tsym.name` as
|
||||
private static void importNamedStatic(final Symbol.ClassSymbol tsym, final int name, final Set<Symbol> symbols) {
|
||||
private static void importNamedStatic(final Symbol.ClassSymbol tsym, final int name, final Set<Symbol> symbols) throws IncompleteHierarchyException {
|
||||
new Object() {
|
||||
Set<Symbol> processed = new HashSet<Symbol>();
|
||||
void importFrom(Symbol.ClassSymbol cs) {
|
||||
void importFrom(Symbol.ClassSymbol cs) throws IncompleteHierarchyException {
|
||||
if (cs == null || !processed.add(cs))
|
||||
return;
|
||||
for (Symbol.ClassSymbol c : cs.getSuperClasses())
|
||||
|
||||
@@ -86,7 +86,8 @@ public abstract class Symbol {
|
||||
public UnitInfo myUnitInfo;
|
||||
public QualifiedName[] mySuperNames;
|
||||
private ClassSymbol[] myMembers;
|
||||
private HierarchyConnector myConnector;
|
||||
private StubHierarchyConnector myConnector;
|
||||
private boolean myHierarchyIncomplete;
|
||||
|
||||
public ClassSymbol(SmartClassAnchor classAnchor,
|
||||
int flags,
|
||||
@@ -95,7 +96,7 @@ public abstract class Symbol {
|
||||
int name,
|
||||
UnitInfo unitInfo,
|
||||
QualifiedName[] supers,
|
||||
HierarchyConnector connector) {
|
||||
StubHierarchyConnector connector) {
|
||||
super(flags | IndexTree.CLASS, owner, fullname, name);
|
||||
this.myClassAnchor = classAnchor;
|
||||
this.mySuperNames = supers;
|
||||
@@ -103,21 +104,32 @@ public abstract class Symbol {
|
||||
this.myConnector = connector;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return myClassAnchor.toString();
|
||||
}
|
||||
|
||||
public void connect() {
|
||||
if (myConnector != null) {
|
||||
HierarchyConnector c = myConnector;
|
||||
StubHierarchyConnector c = myConnector;
|
||||
myConnector = null;
|
||||
c.connect(this);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ClassSymbol[] getSuperClasses() {
|
||||
public ClassSymbol[] getSuperClasses() throws IncompleteHierarchyException {
|
||||
connect();
|
||||
if (mySuperClasses == null) {
|
||||
return EMPTY_ARRAY;
|
||||
if (myHierarchyIncomplete) {
|
||||
throw IncompleteHierarchyException.INSTANCE;
|
||||
}
|
||||
return mySuperClasses;
|
||||
return rawSuperClasses();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
ClassSymbol[] rawSuperClasses() {
|
||||
assert myConnector == null;
|
||||
return mySuperClasses == null ? EMPTY_ARRAY : mySuperClasses;
|
||||
}
|
||||
|
||||
public boolean isCompiled() {
|
||||
@@ -131,6 +143,14 @@ public abstract class Symbol {
|
||||
public void setMembers(ClassSymbol[] members) {
|
||||
this.myMembers = members;
|
||||
}
|
||||
|
||||
void markHierarchyIncomplete() {
|
||||
myHierarchyIncomplete = true;
|
||||
}
|
||||
|
||||
boolean isHierarchyIncomplete() {
|
||||
return myHierarchyIncomplete;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -65,7 +65,7 @@ public class Symbols {
|
||||
return (ClassSymbol[])cs;
|
||||
}
|
||||
|
||||
public ClassSymbol enterClass(ClassAnchor classAnchor, int flags, int shortName, Symbol owner, UnitInfo info, QualifiedName[] supers, HierarchyConnector connector) {
|
||||
public ClassSymbol enterClass(ClassAnchor classAnchor, int flags, int shortName, Symbol owner, UnitInfo info, QualifiedName[] supers, StubHierarchyConnector connector) {
|
||||
QualifiedName qualifiedName = myNameEnvironment.qualifiedName(owner, shortName);
|
||||
SmartClassAnchor smartClassAnchor = new SmartClassAnchor(id++, classAnchor);
|
||||
ClassSymbol c = new ClassSymbol(smartClassAnchor, flags, owner, qualifiedName, shortName, info, supers, connector);
|
||||
|
||||
Reference in New Issue
Block a user