Migrate the rest of resolvers from PSI to JavaElement

JavaMethodSignatureUtil needs to be handled specially later
This commit is contained in:
Alexander Udalov
2013-08-02 16:05:51 +04:00
parent f1892372eb
commit 34a552abfc
6 changed files with 95 additions and 105 deletions
@@ -17,7 +17,10 @@
package org.jetbrains.jet.lang.resolve.java; package org.jetbrains.jet.lang.resolve.java;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.intellij.psi.*; import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiMember;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiSubstitutor;
import com.intellij.psi.impl.compiled.ClsClassImpl; import com.intellij.psi.impl.compiled.ClsClassImpl;
import com.intellij.psi.util.PsiFormatUtil; import com.intellij.psi.util.PsiFormatUtil;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -27,7 +30,9 @@ import org.jetbrains.jet.lang.descriptors.ClassOrNamespaceDescriptor;
import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor; import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.jetbrains.jet.lang.resolve.java.structure.JavaClass; import org.jetbrains.jet.lang.resolve.java.structure.JavaClass;
import org.jetbrains.jet.lang.resolve.java.structure.JavaField;
import org.jetbrains.jet.lang.resolve.java.structure.JavaMember; import org.jetbrains.jet.lang.resolve.java.structure.JavaMember;
import org.jetbrains.jet.lang.resolve.java.structure.JavaMethod;
import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
@@ -95,22 +100,22 @@ public final class DescriptorResolverUtils {
* @return true if {@code member} is a static member of enum class, which is to be put into its class object (and not into the * @return true if {@code member} is a static member of enum class, which is to be put into its class object (and not into the
* corresponding package). This applies to enum entries, values() and valueOf(String) methods * corresponding package). This applies to enum entries, values() and valueOf(String) methods
*/ */
public static boolean shouldBeInEnumClassObject(@NotNull PsiMember member) { public static boolean shouldBeInEnumClassObject(@NotNull JavaMember member) {
PsiClass psiClass = member.getContainingClass(); JavaClass javaClass = member.getContainingClass();
if (psiClass == null || !psiClass.isEnum()) return false; if (javaClass == null || !javaClass.isEnum()) return false;
if (member instanceof PsiEnumConstant) return true; if (member instanceof JavaField && ((JavaField) member).isEnumEntry()) return true;
if (!(member instanceof PsiMethod)) return false; if (!(member instanceof JavaMethod)) return false;
String signature = PsiFormatUtil.formatMethod((PsiMethod) member, String signature = PsiFormatUtil.formatMethod(((JavaMethod) member).getPsi(), PsiSubstitutor.EMPTY, SHOW_NAME | SHOW_PARAMETERS,
PsiSubstitutor.EMPTY, SHOW_NAME | SHOW_PARAMETERS, SHOW_TYPE | SHOW_FQ_CLASS_NAMES); SHOW_TYPE | SHOW_FQ_CLASS_NAMES);
return "values()".equals(signature) || return "values()".equals(signature) ||
"valueOf(java.lang.String)".equals(signature); "valueOf(java.lang.String)".equals(signature);
} }
public static boolean isCorrectOwnerForEnumMember(@NotNull ClassOrNamespaceDescriptor ownerDescriptor, @NotNull JavaMember member) { public static boolean isCorrectOwnerForEnumMember(@NotNull ClassOrNamespaceDescriptor ownerDescriptor, @NotNull JavaMember member) {
return isEnumClassObject(ownerDescriptor) == shouldBeInEnumClassObject(member.getPsi()); return isEnumClassObject(ownerDescriptor) == shouldBeInEnumClassObject(member);
} }
public static boolean isObjectMethodInInterface(@NotNull PsiMember member) { public static boolean isObjectMethodInInterface(@NotNull PsiMember member) {
@@ -19,7 +19,6 @@ package org.jetbrains.jet.lang.resolve.java.resolver;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.util.PsiFormatUtil; import com.intellij.psi.util.PsiFormatUtil;
import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -62,9 +61,6 @@ public final class JavaFunctionResolver {
private JavaValueParameterResolver valueParameterResolver; private JavaValueParameterResolver valueParameterResolver;
private JavaAnnotationResolver annotationResolver; private JavaAnnotationResolver annotationResolver;
public JavaFunctionResolver() {
}
@Inject @Inject
public void setTypeTransformer(JavaTypeTransformer typeTransformer) { public void setTypeTransformer(JavaTypeTransformer typeTransformer) {
this.typeTransformer = typeTransformer; this.typeTransformer = typeTransformer;
@@ -111,9 +107,7 @@ public final class JavaFunctionResolver {
return null; return null;
} }
PsiMethod psiMethod = method.getPsi(); SimpleFunctionDescriptor alreadyResolved = trace.get(BindingContext.FUNCTION, method.getPsi());
SimpleFunctionDescriptor alreadyResolved = trace.get(BindingContext.FUNCTION, psiMethod);
if (alreadyResolved != null) { if (alreadyResolved != null) {
return alreadyResolved; return alreadyResolved;
} }
@@ -177,15 +171,15 @@ public final class JavaFunctionResolver {
); );
if (functionDescriptorImpl.getKind() == CallableMemberDescriptor.Kind.DECLARATION && record) { if (functionDescriptorImpl.getKind() == CallableMemberDescriptor.Kind.DECLARATION && record) {
BindingContextUtils.recordFunctionDeclarationToDescriptor(trace, psiMethod, functionDescriptorImpl); BindingContextUtils.recordFunctionDeclarationToDescriptor(trace, method.getPsi(), functionDescriptorImpl);
} }
if (record) { if (record) {
trace.record(JavaBindingContext.IS_DECLARED_IN_JAVA, functionDescriptorImpl); trace.record(JavaBindingContext.IS_DECLARED_IN_JAVA, functionDescriptorImpl);
} }
if (!RawTypesCheck.hasRawTypesInHierarchicalSignature(psiMethod) if (!RawTypesCheck.hasRawTypesInHierarchicalSignature(method)
&& JavaMethodSignatureUtil.isMethodReturnTypeCompatible(psiMethod) && JavaMethodSignatureUtil.isMethodReturnTypeCompatible(method)
&& !containsErrorType(superFunctions, functionDescriptorImpl)) { && !containsErrorType(superFunctions, functionDescriptorImpl)) {
if (signatureErrors.isEmpty()) { if (signatureErrors.isEmpty()) {
checkFunctionsOverrideCorrectly(method, superFunctions, functionDescriptorImpl); checkFunctionsOverrideCorrectly(method, superFunctions, functionDescriptorImpl);
@@ -22,44 +22,44 @@ import com.intellij.psi.util.MethodSignatureUtil;
import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil; import com.intellij.psi.util.TypeConversionUtil;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.resolve.java.structure.JavaMethod;
import java.util.List; import java.util.List;
// originally from com.intellij.codeInsight.daemon.impl.analysis.HighlightMethodUtil // originally from com.intellij.codeInsight.daemon.impl.analysis.HighlightMethodUtil
class JavaMethodSignatureUtil { class JavaMethodSignatureUtil {
// This and following methods are originally from com.intellij.codeInsight.daemon.impl.analysis.HighlightMethodUtil // This and following methods are originally from com.intellij.codeInsight.daemon.impl.analysis.HighlightMethodUtil
static boolean isMethodReturnTypeCompatible(@NotNull PsiMethod method) { static boolean isMethodReturnTypeCompatible(@NotNull JavaMethod method) {
if (method.hasModifierProperty(PsiModifier.STATIC)) return true; if (method.isStatic()) return true;
HierarchicalMethodSignature methodSignature = method.getHierarchicalMethodSignature(); if (method.getContainingClass() == null) return false;
HierarchicalMethodSignature methodSignature = method.getPsi().getHierarchicalMethodSignature();
List<HierarchicalMethodSignature> superSignatures = methodSignature.getSuperSignatures(); List<HierarchicalMethodSignature> superSignatures = methodSignature.getSuperSignatures();
PsiType returnType = methodSignature.getSubstitutor().substitute(method.getReturnType()); PsiType returnType = methodSignature.getSubstitutor().substitute(method.getPsi().getReturnType());
PsiClass aClass = method.getContainingClass(); if (returnType == null) return true;
if (aClass == null) return false;
for (MethodSignatureBackedByPsiMethod superMethodSignature : superSignatures) { for (MethodSignatureBackedByPsiMethod superMethodSignature : superSignatures) {
PsiMethod superMethod = superMethodSignature.getMethod(); PsiMethod superMethod = superMethodSignature.getMethod();
PsiType declaredReturnType = superMethod.getReturnType(); PsiType declaredReturnType = superMethod.getReturnType();
PsiType superReturnType = declaredReturnType; PsiType superReturnType = superMethodSignature.isRaw() ? TypeConversionUtil.erasure(declaredReturnType) : declaredReturnType;
if (superMethodSignature.isRaw()) superReturnType = TypeConversionUtil.erasure(declaredReturnType); if (superReturnType == null || method == superMethod || superMethod.getContainingClass() == null) continue;
if (returnType == null || superReturnType == null || method == superMethod) continue; if (!areMethodsReturnTypesCompatible(superMethodSignature, superReturnType, methodSignature, returnType)) {
PsiClass superClass = superMethod.getContainingClass(); return false;
if (superClass == null) continue; }
if (!areMethodsReturnTypesCompatible(superMethodSignature, superReturnType, method, methodSignature, returnType)) return false;
} }
return true; return true;
} }
private static boolean areMethodsReturnTypesCompatible( private static boolean areMethodsReturnTypesCompatible(
MethodSignatureBackedByPsiMethod superMethodSignature, @NotNull MethodSignatureBackedByPsiMethod superMethodSignature,
PsiType superReturnType, @NotNull PsiType superReturnType,
PsiMethod method, @NotNull MethodSignatureBackedByPsiMethod methodSignature,
MethodSignatureBackedByPsiMethod methodSignature, @NotNull PsiType returnType
PsiType returnType
) { ) {
if (superReturnType == null) return false;
PsiType substitutedSuperReturnType; PsiType substitutedSuperReturnType;
boolean isJdk15 = PsiUtil.isLanguageLevel5OrHigher(method); boolean isJdk15 = PsiUtil.isLanguageLevel5OrHigher(methodSignature.getMethod());
if (isJdk15 && !superMethodSignature.isRaw() && superMethodSignature.equals(methodSignature)) { //see 8.4.5 if (isJdk15 && !superMethodSignature.isRaw() && superMethodSignature.equals(methodSignature)) { //see 8.4.5
PsiSubstitutor unifyingSubstitutor = MethodSignatureUtil.getSuperMethodSignatureSubstitutor(methodSignature, PsiSubstitutor unifyingSubstitutor = MethodSignatureUtil.getSuperMethodSignatureSubstitutor(methodSignature,
superMethodSignature); superMethodSignature);
@@ -19,10 +19,6 @@ package org.jetbrains.jet.lang.resolve.java.resolver;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiMember;
import com.intellij.psi.PsiModifier;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.ModuleDescriptor; import org.jetbrains.jet.lang.descriptors.ModuleDescriptor;
@@ -40,6 +36,8 @@ import org.jetbrains.jet.lang.resolve.java.sam.SingleAbstractMethodUtils;
import org.jetbrains.jet.lang.resolve.java.scope.JavaClassStaticMembersScope; import org.jetbrains.jet.lang.resolve.java.scope.JavaClassStaticMembersScope;
import org.jetbrains.jet.lang.resolve.java.scope.JavaPackageScope; import org.jetbrains.jet.lang.resolve.java.scope.JavaPackageScope;
import org.jetbrains.jet.lang.resolve.java.structure.JavaClass; import org.jetbrains.jet.lang.resolve.java.structure.JavaClass;
import org.jetbrains.jet.lang.resolve.java.structure.JavaField;
import org.jetbrains.jet.lang.resolve.java.structure.JavaMethod;
import org.jetbrains.jet.lang.resolve.java.structure.JavaPackage; import org.jetbrains.jet.lang.resolve.java.structure.JavaPackage;
import org.jetbrains.jet.lang.resolve.java.vfilefinder.VirtualFileFinder; import org.jetbrains.jet.lang.resolve.java.vfilefinder.VirtualFileFinder;
import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.FqName;
@@ -69,9 +67,6 @@ public final class JavaNamespaceResolver {
private DeserializedDescriptorResolver deserializedDescriptorResolver; private DeserializedDescriptorResolver deserializedDescriptorResolver;
private VirtualFileFinder virtualFileFinder; private VirtualFileFinder virtualFileFinder;
public JavaNamespaceResolver() {
}
@Inject @Inject
public void setVirtualFileFinder(VirtualFileFinder virtualFileFinder) { public void setVirtualFileFinder(VirtualFileFinder virtualFileFinder) {
this.virtualFileFinder = virtualFileFinder; this.virtualFileFinder = virtualFileFinder;
@@ -187,18 +182,17 @@ public final class JavaNamespaceResolver {
return null; return null;
} }
PsiClass psiClass = javaClass.getPsi(); if (DescriptorResolverUtils.isCompiledKotlinClassOrPackageClass(javaClass.getPsi())) {
if (DescriptorResolverUtils.isCompiledKotlinClassOrPackageClass(psiClass)) {
return null; return null;
} }
if (!hasStaticMembers(psiClass)) { if (!hasStaticMembers(javaClass)) {
return null; return null;
} }
trace.record(JavaBindingContext.JAVA_NAMESPACE_KIND, namespaceDescriptor, JavaNamespaceKind.CLASS_STATICS); trace.record(JavaBindingContext.JAVA_NAMESPACE_KIND, namespaceDescriptor, JavaNamespaceKind.CLASS_STATICS);
if (record) { if (record) {
trace.record(BindingContext.NAMESPACE, psiClass, namespaceDescriptor); trace.record(BindingContext.NAMESPACE, javaClass.getPsi(), namespaceDescriptor);
} }
return new JavaClassStaticMembersScope(namespaceDescriptor, fqName, javaClass, javaDescriptorResolver); return new JavaClassStaticMembersScope(namespaceDescriptor, fqName, javaClass, javaDescriptorResolver);
@@ -230,18 +224,24 @@ public final class JavaNamespaceResolver {
return createNamespaceScope(fqName, namespaceDescriptor, false); return createNamespaceScope(fqName, namespaceDescriptor, false);
} }
private static boolean hasStaticMembers(@NotNull PsiClass psiClass) { private static boolean hasStaticMembers(@NotNull JavaClass javaClass) {
for (PsiMember member : ContainerUtil.concat(psiClass.getMethods(), psiClass.getFields())) { for (JavaMethod method : javaClass.getMethods()) {
if (member.hasModifierProperty(PsiModifier.STATIC) && !DescriptorResolverUtils.shouldBeInEnumClassObject(member)) { if (method.isStatic() && !DescriptorResolverUtils.shouldBeInEnumClassObject(method)) {
return true; return true;
} }
} }
for (PsiClass nestedClass : psiClass.getInnerClasses()) { for (JavaField field : javaClass.getFields()) {
if (SingleAbstractMethodUtils.isSamInterface(new JavaClass(nestedClass))) { if (field.isStatic() && !DescriptorResolverUtils.shouldBeInEnumClassObject(field)) {
return true; return true;
} }
if (nestedClass.hasModifierProperty(PsiModifier.STATIC) && hasStaticMembers(nestedClass)) { }
for (JavaClass nestedClass : javaClass.getInnerClasses()) {
if (SingleAbstractMethodUtils.isSamInterface(nestedClass)) {
return true;
}
if (nestedClass.isStatic() && hasStaticMembers(nestedClass)) {
return true; return true;
} }
} }
@@ -16,70 +16,56 @@
package org.jetbrains.jet.lang.resolve.java.resolver; package org.jetbrains.jet.lang.resolve.java.resolver;
import com.intellij.psi.*; import com.intellij.psi.HierarchicalMethodSignature;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.resolve.java.structure.*;
public class RawTypesCheck { public class RawTypesCheck {
private static boolean isPartiallyRawType(@NotNull PsiType type) { private static boolean isPartiallyRawType(@NotNull JavaType type) {
return type.accept(new PsiTypeVisitor<Boolean>() { if (type instanceof JavaPrimitiveType) {
@Nullable return false;
@Override }
public Boolean visitPrimitiveType(PsiPrimitiveType primitiveType) { else if (type instanceof JavaClassifierType) {
return false; JavaClassifierType classifierType = (JavaClassifierType) type;
if (classifierType.isRaw()) {
return true;
} }
@Nullable for (JavaType argument : classifierType.getTypeArguments()) {
@Override if (isPartiallyRawType(argument)) {
public Boolean visitClassType(PsiClassType classType) {
if (classType.isRaw()) {
return true; return true;
} }
for (PsiType argument : classType.getParameters()) {
if (argument.accept(this)) {
return true;
}
}
return false;
} }
@Nullable return false;
@Override }
public Boolean visitArrayType(PsiArrayType arrayType) { else if (type instanceof JavaArrayType) {
return arrayType.getComponentType().accept(this); return isPartiallyRawType(((JavaArrayType) type).getComponentType());
} }
else if (type instanceof JavaWildcardType) {
@Nullable JavaType bound = ((JavaWildcardType) type).getBound();
@Override return bound != null && isPartiallyRawType(bound);
public Boolean visitWildcardType(PsiWildcardType wildcardType) { }
PsiType bound = wildcardType.getBound(); else {
return bound == null ? false : bound.accept(this); throw new IllegalStateException("Unexpected type: " + type);
} }
@Nullable
@Override
public Boolean visitType(PsiType type) {
throw new IllegalStateException(type.getClass().getSimpleName() + " is unexpected");
}
});
} }
private static boolean hasRawTypesInSignature(@NotNull PsiMethod method) { private static boolean hasRawTypesInSignature(@NotNull JavaMethod method) {
PsiType returnType = method.getReturnType(); JavaType returnType = method.getReturnType();
if (returnType != null && isPartiallyRawType(returnType)) { if (returnType != null && isPartiallyRawType(returnType)) {
return true; return true;
} }
for (PsiParameter parameter : method.getParameterList().getParameters()) { for (JavaValueParameter parameter : method.getValueParameters()) {
if (isPartiallyRawType(parameter.getType())) { if (isPartiallyRawType(parameter.getType())) {
return true; return true;
} }
} }
for (PsiTypeParameter typeParameter : method.getTypeParameters()) { for (JavaTypeParameter typeParameter : method.getTypeParameters()) {
for (PsiClassType upperBound : typeParameter.getExtendsList().getReferencedTypes()) { for (JavaClassifierType upperBound : typeParameter.getUpperBounds()) {
if (isPartiallyRawType(upperBound)) { if (isPartiallyRawType(upperBound)) {
return true; return true;
} }
@@ -89,17 +75,17 @@ public class RawTypesCheck {
return false; return false;
} }
static boolean hasRawTypesInHierarchicalSignature(@NotNull PsiMethod method) { static boolean hasRawTypesInHierarchicalSignature(@NotNull JavaMethod method) {
// This is a very important optimization: package-classes are big and full of static methods // This is a very important optimization: package-classes are big and full of static methods
// building method hierarchies for such classes takes a very long time // building method hierarchies for such classes takes a very long time
if (method.hasModifierProperty(PsiModifier.STATIC)) return false; if (method.isStatic()) return false;
if (hasRawTypesInSignature(method)) { if (hasRawTypesInSignature(method)) {
return true; return true;
} }
for (HierarchicalMethodSignature superSignature : method.getHierarchicalMethodSignature().getSuperSignatures()) { for (HierarchicalMethodSignature superSignature : method.getPsi().getHierarchicalMethodSignature().getSuperSignatures()) {
PsiMethod superMethod = superSignature.getMethod(); JavaMethod superMethod = new JavaMethod(superSignature.getMethod());
if (superSignature.isRaw() || typeParameterIsErased(method, superMethod) || hasRawTypesInSignature(superMethod)) { if (superSignature.isRaw() || typeParameterIsErased(method, superMethod) || hasRawTypesInSignature(superMethod)) {
return true; return true;
} }
@@ -108,12 +94,12 @@ public class RawTypesCheck {
return false; return false;
} }
private static boolean typeParameterIsErased(@NotNull PsiMethod a, @NotNull PsiMethod b) { private static boolean typeParameterIsErased(@NotNull JavaMethod method, @NotNull JavaMethod superMethod) {
// Java allows you to write // Java allows you to write
// <T extends Foo> T foo(), in the superclass and then // <T extends Foo> T foo(), in the superclass and then
// Foo foo(), in the subclass // Foo foo(), in the subclass
// this is a valid Java override, but in fact it is an erasure // this is a valid Java override, but in fact it is an erasure
return a.getTypeParameters().length != b.getTypeParameters().length; return method.getTypeParameters().size() != superMethod.getTypeParameters().size();
} }
private RawTypesCheck() { private RawTypesCheck() {
@@ -123,6 +123,11 @@ public class JavaClass extends JavaClassifier
return methods(getPsi().getAllMethods()); return methods(getPsi().getAllMethods());
} }
@NotNull
public Collection<JavaField> getFields() {
return fields(getPsi().getFields());
}
@NotNull @NotNull
public Collection<JavaField> getAllFields() { public Collection<JavaField> getAllFields() {
return fields(getPsi().getAllFields()); return fields(getPsi().getAllFields());