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;
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.util.PsiFormatUtil;
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.ValueParameterDescriptor;
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.JavaMethod;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name;
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
* corresponding package). This applies to enum entries, values() and valueOf(String) methods
*/
public static boolean shouldBeInEnumClassObject(@NotNull PsiMember member) {
PsiClass psiClass = member.getContainingClass();
if (psiClass == null || !psiClass.isEnum()) return false;
public static boolean shouldBeInEnumClassObject(@NotNull JavaMember member) {
JavaClass javaClass = member.getContainingClass();
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;
String signature = PsiFormatUtil.formatMethod((PsiMethod) member,
PsiSubstitutor.EMPTY, SHOW_NAME | SHOW_PARAMETERS, SHOW_TYPE | SHOW_FQ_CLASS_NAMES);
if (!(member instanceof JavaMethod)) return false;
String signature = PsiFormatUtil.formatMethod(((JavaMethod) member).getPsi(), PsiSubstitutor.EMPTY, SHOW_NAME | SHOW_PARAMETERS,
SHOW_TYPE | SHOW_FQ_CLASS_NAMES);
return "values()".equals(signature) ||
"valueOf(java.lang.String)".equals(signature);
}
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) {
@@ -19,7 +19,6 @@ package org.jetbrains.jet.lang.resolve.java.resolver;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.util.PsiFormatUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
@@ -62,9 +61,6 @@ public final class JavaFunctionResolver {
private JavaValueParameterResolver valueParameterResolver;
private JavaAnnotationResolver annotationResolver;
public JavaFunctionResolver() {
}
@Inject
public void setTypeTransformer(JavaTypeTransformer typeTransformer) {
this.typeTransformer = typeTransformer;
@@ -111,9 +107,7 @@ public final class JavaFunctionResolver {
return null;
}
PsiMethod psiMethod = method.getPsi();
SimpleFunctionDescriptor alreadyResolved = trace.get(BindingContext.FUNCTION, psiMethod);
SimpleFunctionDescriptor alreadyResolved = trace.get(BindingContext.FUNCTION, method.getPsi());
if (alreadyResolved != null) {
return alreadyResolved;
}
@@ -177,15 +171,15 @@ public final class JavaFunctionResolver {
);
if (functionDescriptorImpl.getKind() == CallableMemberDescriptor.Kind.DECLARATION && record) {
BindingContextUtils.recordFunctionDeclarationToDescriptor(trace, psiMethod, functionDescriptorImpl);
BindingContextUtils.recordFunctionDeclarationToDescriptor(trace, method.getPsi(), functionDescriptorImpl);
}
if (record) {
trace.record(JavaBindingContext.IS_DECLARED_IN_JAVA, functionDescriptorImpl);
}
if (!RawTypesCheck.hasRawTypesInHierarchicalSignature(psiMethod)
&& JavaMethodSignatureUtil.isMethodReturnTypeCompatible(psiMethod)
if (!RawTypesCheck.hasRawTypesInHierarchicalSignature(method)
&& JavaMethodSignatureUtil.isMethodReturnTypeCompatible(method)
&& !containsErrorType(superFunctions, functionDescriptorImpl)) {
if (signatureErrors.isEmpty()) {
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.TypeConversionUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.resolve.java.structure.JavaMethod;
import java.util.List;
// originally from com.intellij.codeInsight.daemon.impl.analysis.HighlightMethodUtil
class JavaMethodSignatureUtil {
// This and following methods are originally from com.intellij.codeInsight.daemon.impl.analysis.HighlightMethodUtil
static boolean isMethodReturnTypeCompatible(@NotNull PsiMethod method) {
if (method.hasModifierProperty(PsiModifier.STATIC)) return true;
HierarchicalMethodSignature methodSignature = method.getHierarchicalMethodSignature();
static boolean isMethodReturnTypeCompatible(@NotNull JavaMethod method) {
if (method.isStatic()) return true;
if (method.getContainingClass() == null) return false;
HierarchicalMethodSignature methodSignature = method.getPsi().getHierarchicalMethodSignature();
List<HierarchicalMethodSignature> superSignatures = methodSignature.getSuperSignatures();
PsiType returnType = methodSignature.getSubstitutor().substitute(method.getReturnType());
PsiClass aClass = method.getContainingClass();
if (aClass == null) return false;
PsiType returnType = methodSignature.getSubstitutor().substitute(method.getPsi().getReturnType());
if (returnType == null) return true;
for (MethodSignatureBackedByPsiMethod superMethodSignature : superSignatures) {
PsiMethod superMethod = superMethodSignature.getMethod();
PsiType declaredReturnType = superMethod.getReturnType();
PsiType superReturnType = declaredReturnType;
if (superMethodSignature.isRaw()) superReturnType = TypeConversionUtil.erasure(declaredReturnType);
if (returnType == null || superReturnType == null || method == superMethod) continue;
PsiClass superClass = superMethod.getContainingClass();
if (superClass == null) continue;
if (!areMethodsReturnTypesCompatible(superMethodSignature, superReturnType, method, methodSignature, returnType)) return false;
PsiType superReturnType = superMethodSignature.isRaw() ? TypeConversionUtil.erasure(declaredReturnType) : declaredReturnType;
if (superReturnType == null || method == superMethod || superMethod.getContainingClass() == null) continue;
if (!areMethodsReturnTypesCompatible(superMethodSignature, superReturnType, methodSignature, returnType)) {
return false;
}
}
return true;
}
private static boolean areMethodsReturnTypesCompatible(
MethodSignatureBackedByPsiMethod superMethodSignature,
PsiType superReturnType,
PsiMethod method,
MethodSignatureBackedByPsiMethod methodSignature,
PsiType returnType
@NotNull MethodSignatureBackedByPsiMethod superMethodSignature,
@NotNull PsiType superReturnType,
@NotNull MethodSignatureBackedByPsiMethod methodSignature,
@NotNull PsiType returnType
) {
if (superReturnType == null) return false;
PsiType substitutedSuperReturnType;
boolean isJdk15 = PsiUtil.isLanguageLevel5OrHigher(method);
boolean isJdk15 = PsiUtil.isLanguageLevel5OrHigher(methodSignature.getMethod());
if (isJdk15 && !superMethodSignature.isRaw() && superMethodSignature.equals(methodSignature)) { //see 8.4.5
PsiSubstitutor unifyingSubstitutor = MethodSignatureUtil.getSuperMethodSignatureSubstitutor(methodSignature,
superMethodSignature);
@@ -19,10 +19,6 @@ package org.jetbrains.jet.lang.resolve.java.resolver;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
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.Nullable;
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.JavaPackageScope;
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.vfilefinder.VirtualFileFinder;
import org.jetbrains.jet.lang.resolve.name.FqName;
@@ -69,9 +67,6 @@ public final class JavaNamespaceResolver {
private DeserializedDescriptorResolver deserializedDescriptorResolver;
private VirtualFileFinder virtualFileFinder;
public JavaNamespaceResolver() {
}
@Inject
public void setVirtualFileFinder(VirtualFileFinder virtualFileFinder) {
this.virtualFileFinder = virtualFileFinder;
@@ -187,18 +182,17 @@ public final class JavaNamespaceResolver {
return null;
}
PsiClass psiClass = javaClass.getPsi();
if (DescriptorResolverUtils.isCompiledKotlinClassOrPackageClass(psiClass)) {
if (DescriptorResolverUtils.isCompiledKotlinClassOrPackageClass(javaClass.getPsi())) {
return null;
}
if (!hasStaticMembers(psiClass)) {
if (!hasStaticMembers(javaClass)) {
return null;
}
trace.record(JavaBindingContext.JAVA_NAMESPACE_KIND, namespaceDescriptor, JavaNamespaceKind.CLASS_STATICS);
if (record) {
trace.record(BindingContext.NAMESPACE, psiClass, namespaceDescriptor);
trace.record(BindingContext.NAMESPACE, javaClass.getPsi(), namespaceDescriptor);
}
return new JavaClassStaticMembersScope(namespaceDescriptor, fqName, javaClass, javaDescriptorResolver);
@@ -230,18 +224,24 @@ public final class JavaNamespaceResolver {
return createNamespaceScope(fqName, namespaceDescriptor, false);
}
private static boolean hasStaticMembers(@NotNull PsiClass psiClass) {
for (PsiMember member : ContainerUtil.concat(psiClass.getMethods(), psiClass.getFields())) {
if (member.hasModifierProperty(PsiModifier.STATIC) && !DescriptorResolverUtils.shouldBeInEnumClassObject(member)) {
private static boolean hasStaticMembers(@NotNull JavaClass javaClass) {
for (JavaMethod method : javaClass.getMethods()) {
if (method.isStatic() && !DescriptorResolverUtils.shouldBeInEnumClassObject(method)) {
return true;
}
}
for (PsiClass nestedClass : psiClass.getInnerClasses()) {
if (SingleAbstractMethodUtils.isSamInterface(new JavaClass(nestedClass))) {
for (JavaField field : javaClass.getFields()) {
if (field.isStatic() && !DescriptorResolverUtils.shouldBeInEnumClassObject(field)) {
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;
}
}
@@ -16,70 +16,56 @@
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.Nullable;
import org.jetbrains.jet.lang.resolve.java.structure.*;
public class RawTypesCheck {
private static boolean isPartiallyRawType(@NotNull PsiType type) {
return type.accept(new PsiTypeVisitor<Boolean>() {
@Nullable
@Override
public Boolean visitPrimitiveType(PsiPrimitiveType primitiveType) {
return false;
private static boolean isPartiallyRawType(@NotNull JavaType type) {
if (type instanceof JavaPrimitiveType) {
return false;
}
else if (type instanceof JavaClassifierType) {
JavaClassifierType classifierType = (JavaClassifierType) type;
if (classifierType.isRaw()) {
return true;
}
@Nullable
@Override
public Boolean visitClassType(PsiClassType classType) {
if (classType.isRaw()) {
for (JavaType argument : classifierType.getTypeArguments()) {
if (isPartiallyRawType(argument)) {
return true;
}
for (PsiType argument : classType.getParameters()) {
if (argument.accept(this)) {
return true;
}
}
return false;
}
@Nullable
@Override
public Boolean visitArrayType(PsiArrayType arrayType) {
return arrayType.getComponentType().accept(this);
}
@Nullable
@Override
public Boolean visitWildcardType(PsiWildcardType wildcardType) {
PsiType bound = wildcardType.getBound();
return bound == null ? false : bound.accept(this);
}
@Nullable
@Override
public Boolean visitType(PsiType type) {
throw new IllegalStateException(type.getClass().getSimpleName() + " is unexpected");
}
});
return false;
}
else if (type instanceof JavaArrayType) {
return isPartiallyRawType(((JavaArrayType) type).getComponentType());
}
else if (type instanceof JavaWildcardType) {
JavaType bound = ((JavaWildcardType) type).getBound();
return bound != null && isPartiallyRawType(bound);
}
else {
throw new IllegalStateException("Unexpected type: " + type);
}
}
private static boolean hasRawTypesInSignature(@NotNull PsiMethod method) {
PsiType returnType = method.getReturnType();
private static boolean hasRawTypesInSignature(@NotNull JavaMethod method) {
JavaType returnType = method.getReturnType();
if (returnType != null && isPartiallyRawType(returnType)) {
return true;
}
for (PsiParameter parameter : method.getParameterList().getParameters()) {
for (JavaValueParameter parameter : method.getValueParameters()) {
if (isPartiallyRawType(parameter.getType())) {
return true;
}
}
for (PsiTypeParameter typeParameter : method.getTypeParameters()) {
for (PsiClassType upperBound : typeParameter.getExtendsList().getReferencedTypes()) {
for (JavaTypeParameter typeParameter : method.getTypeParameters()) {
for (JavaClassifierType upperBound : typeParameter.getUpperBounds()) {
if (isPartiallyRawType(upperBound)) {
return true;
}
@@ -89,17 +75,17 @@ public class RawTypesCheck {
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
// 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)) {
return true;
}
for (HierarchicalMethodSignature superSignature : method.getHierarchicalMethodSignature().getSuperSignatures()) {
PsiMethod superMethod = superSignature.getMethod();
for (HierarchicalMethodSignature superSignature : method.getPsi().getHierarchicalMethodSignature().getSuperSignatures()) {
JavaMethod superMethod = new JavaMethod(superSignature.getMethod());
if (superSignature.isRaw() || typeParameterIsErased(method, superMethod) || hasRawTypesInSignature(superMethod)) {
return true;
}
@@ -108,12 +94,12 @@ public class RawTypesCheck {
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
// <T extends Foo> T foo(), in the superclass and then
// Foo foo(), in the subclass
// 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() {
@@ -123,6 +123,11 @@ public class JavaClass extends JavaClassifier
return methods(getPsi().getAllMethods());
}
@NotNull
public Collection<JavaField> getFields() {
return fields(getPsi().getFields());
}
@NotNull
public Collection<JavaField> getAllFields() {
return fields(getPsi().getAllFields());