mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
javac ast indices: store actual qualifier type for method call
This commit is contained in:
+19
-4
@@ -196,7 +196,7 @@ final class JavacReferenceCollectorListener implements TaskListener {
|
||||
// member import
|
||||
for (Element memberElement : myElementUtility.getAllMembers((TypeElement)ownerElement)) {
|
||||
if (memberElement.getSimpleName() == name) {
|
||||
incrementOrAdd(elements, JavacRef.JavacElementRefBase.fromElement(memberElement, myNameTableCache));
|
||||
incrementOrAdd(elements, JavacRef.JavacElementRefBase.fromElement(memberElement, null, myNameTableCache));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -213,7 +213,7 @@ final class JavacReferenceCollectorListener implements TaskListener {
|
||||
for (Element element = baseImport;
|
||||
element != null && element.getKind() != ElementKind.PACKAGE;
|
||||
element = element.getEnclosingElement()) {
|
||||
incrementOrAdd(collector, JavacRef.JavacElementRefBase.fromElement(element, myNameTableCache));
|
||||
incrementOrAdd(collector, JavacRef.JavacElementRefBase.fromElement(element, null, myNameTableCache));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,6 +221,7 @@ final class JavacReferenceCollectorListener implements TaskListener {
|
||||
private final JavacFileData myFileData;
|
||||
private final JavacTreeHelper myTreeHelper;
|
||||
private int myRemainDeclarations;
|
||||
public CompilationUnitTree myUnitTree;
|
||||
|
||||
private ReferenceCollector(int remainDeclarations,
|
||||
String filePath,
|
||||
@@ -231,6 +232,7 @@ final class JavacReferenceCollectorListener implements TaskListener {
|
||||
myDivideImportRefs ? createReferenceHolder() : EMPTY_T_OBJ_INT_MAP,
|
||||
createDefinitionHolder());
|
||||
myTreeHelper = new JavacTreeHelper(unitTree, myTreeUtility);
|
||||
myUnitTree = unitTree;
|
||||
}
|
||||
|
||||
void sinkReference(@Nullable JavacRef.JavacElementRefBase ref) {
|
||||
@@ -243,13 +245,18 @@ final class JavacReferenceCollectorListener implements TaskListener {
|
||||
|
||||
@Nullable
|
||||
JavacRef.JavacElementRefBase asJavacRef(Element element) {
|
||||
return JavacRef.JavacElementRefBase.fromElement(element, myNameTableCache);
|
||||
return asJavacRef(element, null);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
JavacRef.JavacElementRefBase asJavacRef(Element element, Element qualifier) {
|
||||
return JavacRef.JavacElementRefBase.fromElement(element, qualifier, myNameTableCache);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
JavacRef.JavacElementRefBase asJavacRef(TypeMirror typeMirror) {
|
||||
final Element element = getTypeUtility().asElement(typeMirror);
|
||||
return element == null ? null : JavacRef.JavacElementRefBase.fromElement(element, myNameTableCache);
|
||||
return element == null ? null : JavacRef.JavacElementRefBase.fromElement(element, null, myNameTableCache);
|
||||
}
|
||||
|
||||
Element getReferencedElement(Tree tree) {
|
||||
@@ -267,6 +274,14 @@ final class JavacReferenceCollectorListener implements TaskListener {
|
||||
private int decrementRemainDeclarationsAndGet(Tree declarationToProcess) {
|
||||
return declarationToProcess == null ? myRemainDeclarations : --myRemainDeclarations;
|
||||
}
|
||||
|
||||
public Elements getElementUtility() {
|
||||
return myElementUtility;
|
||||
}
|
||||
|
||||
public Trees getTrees() {
|
||||
return myTreeUtility;
|
||||
}
|
||||
}
|
||||
|
||||
private static TObjectIntHashMap<JavacRef> createReferenceHolder() {
|
||||
|
||||
@@ -15,14 +15,18 @@
|
||||
*/
|
||||
package org.jetbrains.jps.javac.ast;
|
||||
|
||||
import com.intellij.util.containers.Stack;
|
||||
import com.sun.source.tree.*;
|
||||
import com.sun.source.util.TreeScanner;
|
||||
import org.jetbrains.jps.javac.ast.api.JavacDef;
|
||||
import org.jetbrains.jps.javac.ast.api.JavacRef;
|
||||
|
||||
import javax.lang.model.element.*;
|
||||
import javax.lang.model.type.DeclaredType;
|
||||
import javax.lang.model.type.TypeKind;
|
||||
import javax.lang.model.type.TypeMirror;
|
||||
import javax.lang.model.util.Elements;
|
||||
import javax.lang.model.util.Types;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
@@ -87,7 +91,13 @@ class JavacTreeRefScanner extends TreeScanner<Tree, JavacReferenceCollectorListe
|
||||
public Tree visitMemberSelect(MemberSelectTree node, JavacReferenceCollectorListener.ReferenceCollector refCollector) {
|
||||
final Element element = refCollector.getReferencedElement(node);
|
||||
if (element != null && element.getKind() != ElementKind.PACKAGE) {
|
||||
refCollector.sinkReference(refCollector.asJavacRef(element));
|
||||
ExpressionTree qualifierExpression = node.getExpression();
|
||||
Element qualifierType = null;
|
||||
TypeMirror type = refCollector.getType(qualifierExpression);
|
||||
if (type instanceof DeclaredType) {
|
||||
qualifierType = ((DeclaredType)type).asElement();
|
||||
}
|
||||
refCollector.sinkReference(refCollector.asJavacRef(element, qualifierType));
|
||||
}
|
||||
return super.visitMemberSelect(node, refCollector);
|
||||
}
|
||||
@@ -107,11 +117,48 @@ class JavacTreeRefScanner extends TreeScanner<Tree, JavacReferenceCollectorListe
|
||||
}
|
||||
return super.visitMethod(node, refCollector);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Tree visitMethodInvocation(MethodInvocationTree node, JavacReferenceCollectorListener.ReferenceCollector collector) {
|
||||
if (node.getMethodSelect() instanceof IdentifierTree) {
|
||||
Element element = collector.getReferencedElement(node.getMethodSelect());
|
||||
if (element.getKind() != ElementKind.CONSTRUCTOR && !element.getModifiers().contains(Modifier.STATIC)) {
|
||||
TypeElement currentClass = myCurrentEnclosingElement.peek();
|
||||
Elements elements = collector.getElementUtility();
|
||||
Types types = collector.getTypeUtility();
|
||||
TypeElement actualQualifier = null;
|
||||
while (currentClass != null) {
|
||||
List<? extends Element> members = elements.getAllMembers(currentClass);
|
||||
for (Element member : members) {
|
||||
if (member == element /*cheaper then the next condition*/ || types.isSameType(member.asType(), element.asType())) {
|
||||
actualQualifier = currentClass;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (actualQualifier != null) {
|
||||
break;
|
||||
}
|
||||
currentClass = getEnclosingClass(currentClass);
|
||||
}
|
||||
|
||||
if (actualQualifier == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
collector.sinkReference(collector.asJavacRef(element, actualQualifier));
|
||||
scan(node.getTypeArguments(), collector);
|
||||
scan(node.getArguments(), collector);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return super.visitMethodInvocation(node, collector);
|
||||
}
|
||||
|
||||
final Stack<TypeElement> myCurrentEnclosingElement = new Stack<TypeElement>();
|
||||
@Override
|
||||
public Tree visitClass(ClassTree node, JavacReferenceCollectorListener.ReferenceCollector refCollector) {
|
||||
TypeElement element = (TypeElement)refCollector.getReferencedElement(node);
|
||||
if (element == null) return null;
|
||||
myCurrentEnclosingElement.add(element);
|
||||
|
||||
final TypeMirror superclass = element.getSuperclass();
|
||||
final List<? extends TypeMirror> interfaces = element.getInterfaces();
|
||||
@@ -136,7 +183,9 @@ class JavacTreeRefScanner extends TreeScanner<Tree, JavacReferenceCollectorListe
|
||||
if (aClass == null) return null;
|
||||
refCollector.sinkReference(aClass);
|
||||
refCollector.sinkDeclaration(new JavacDef.JavacClassDef(aClass, supers));
|
||||
return super.visitClass(node, refCollector);
|
||||
super.visitClass(node, refCollector);
|
||||
myCurrentEnclosingElement.pop();
|
||||
return null;
|
||||
}
|
||||
|
||||
static JavacTreeRefScanner createASTScanner() {
|
||||
@@ -152,4 +201,13 @@ class JavacTreeRefScanner extends TreeScanner<Tree, JavacReferenceCollectorListe
|
||||
private static boolean isStatic(Element element) {
|
||||
return element.getModifiers().contains(Modifier.STATIC);
|
||||
}
|
||||
|
||||
private static TypeElement getEnclosingClass(TypeElement element) {
|
||||
Element current = element;
|
||||
while (true) {
|
||||
current = current.getEnclosingElement();
|
||||
if (current == null) return null;
|
||||
if (current instanceof TypeElement) return (TypeElement)current;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,18 +121,15 @@ public interface JavacRef {
|
||||
|
||||
abstract class JavacElementRefBase implements JavacRef {
|
||||
protected final @NotNull Element myOriginalElement;
|
||||
@Nullable private final Element myQualifier;
|
||||
protected final JavacNameTable myNameTableCache;
|
||||
|
||||
protected JavacElementRefBase(@NotNull Element element, JavacNameTable nameTableCache) {
|
||||
protected JavacElementRefBase(@NotNull Element element, @Nullable Element qualifier, JavacNameTable nameTableCache) {
|
||||
myOriginalElement = element;
|
||||
myQualifier = qualifier;
|
||||
myNameTableCache = nameTableCache;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Element getOriginalElement() {
|
||||
return myOriginalElement;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getName() {
|
||||
@@ -147,19 +144,19 @@ public interface JavacRef {
|
||||
@NotNull
|
||||
@Override
|
||||
public String getOwnerName() {
|
||||
return myNameTableCache.parseBinaryName(myOriginalElement.getEnclosingElement());
|
||||
return myNameTableCache.parseBinaryName(myQualifier != null ? myQualifier : myOriginalElement.getEnclosingElement());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static JavacElementRefBase fromElement(Element element, JavacNameTable nameTableCache) {
|
||||
public static JavacElementRefBase fromElement(Element element, Element qualifier, JavacNameTable nameTableCache) {
|
||||
if (element instanceof TypeElement) {
|
||||
return new JavacElementClassImpl(element, nameTableCache);
|
||||
return new JavacElementClassImpl(element, qualifier, nameTableCache);
|
||||
}
|
||||
else if (element instanceof VariableElement) {
|
||||
return new JavacElementFieldImpl(element, nameTableCache);
|
||||
return new JavacElementFieldImpl(element, qualifier, nameTableCache);
|
||||
}
|
||||
else if (element instanceof ExecutableElement) {
|
||||
return new JavacElementMethodImpl(element, nameTableCache);
|
||||
return new JavacElementMethodImpl(element, qualifier, nameTableCache);
|
||||
}
|
||||
else if (element == null || element.getKind() == ElementKind.OTHER || element.getKind() == ElementKind.TYPE_PARAMETER) {
|
||||
// javac reserved symbol kind (e.g: com.sun.tools.javac.comp.Resolve.ResolveError)
|
||||
@@ -175,18 +172,22 @@ public interface JavacRef {
|
||||
|
||||
JavacElementRefBase base = (JavacElementRefBase)o;
|
||||
|
||||
return myOriginalElement == base.myOriginalElement;
|
||||
return myOriginalElement == base.myOriginalElement && myQualifier == base.myQualifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return myOriginalElement.hashCode();
|
||||
int hashCode = myOriginalElement.hashCode();
|
||||
if (myQualifier != null) {
|
||||
hashCode += myQualifier.hashCode();
|
||||
}
|
||||
return hashCode;
|
||||
}
|
||||
}
|
||||
|
||||
class JavacElementClassImpl extends JavacElementRefBase implements JavacClass {
|
||||
public JavacElementClassImpl(@NotNull Element element, JavacNameTable nameTableCache) {
|
||||
super(element, nameTableCache);
|
||||
public JavacElementClassImpl(@NotNull Element element, @Nullable Element qualifier, JavacNameTable nameTableCache) {
|
||||
super(element, qualifier, nameTableCache);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -202,8 +203,8 @@ public interface JavacRef {
|
||||
}
|
||||
|
||||
class JavacElementMethodImpl extends JavacElementRefBase implements JavacMethod {
|
||||
public JavacElementMethodImpl(@NotNull Element element, JavacNameTable nameTableCache) {
|
||||
super(element, nameTableCache);
|
||||
public JavacElementMethodImpl(@NotNull Element element, @Nullable Element qualifier, JavacNameTable nameTableCache) {
|
||||
super(element, qualifier, nameTableCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -213,8 +214,8 @@ public interface JavacRef {
|
||||
}
|
||||
|
||||
class JavacElementFieldImpl extends JavacElementRefBase implements JavacField {
|
||||
public JavacElementFieldImpl(@NotNull Element element, JavacNameTable nameTableCache) {
|
||||
super(element, nameTableCache);
|
||||
public JavacElementFieldImpl(@NotNull Element element, @Nullable Element qualifier, JavacNameTable nameTableCache) {
|
||||
super(element, qualifier, nameTableCache);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user