From b82e85b676491489cbf3f4e83a4d40ec47d6153f Mon Sep 17 00:00:00 2001 From: "Pavel V. Talanov" Date: Wed, 10 Oct 2012 20:52:03 +0400 Subject: [PATCH] Extract JavaSupertypesResolver class from JavaClassResolver Regenerate injectors --- .../di/InjectorForJavaDescriptorResolver.java | 12 +- .../di/InjectorForJavaSemanticServices.java | 12 +- .../di/InjectorForTopDownAnalyzerForJvm.java | 12 +- .../resolver/JavaClassObjectResolver.java | 10 +- .../java/resolver/JavaClassResolver.java | 132 +---------- .../java/resolver/JavaSupertypesResolver.java | 206 ++++++++++++++++++ 6 files changed, 247 insertions(+), 137 deletions(-) create mode 100644 compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaSupertypesResolver.java diff --git a/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForJavaDescriptorResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForJavaDescriptorResolver.java index 5e83b5b884c..e2065ce9b75 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForJavaDescriptorResolver.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForJavaDescriptorResolver.java @@ -30,6 +30,7 @@ import org.jetbrains.jet.lang.resolve.java.resolver.JavaClassResolver; import org.jetbrains.jet.lang.resolve.java.resolver.JavaAnnotationResolver; import org.jetbrains.jet.lang.resolve.java.resolver.JavaCompileTimeConstResolver; import org.jetbrains.jet.lang.resolve.java.resolver.JavaClassObjectResolver; +import org.jetbrains.jet.lang.resolve.java.resolver.JavaSupertypesResolver; import org.jetbrains.jet.lang.resolve.java.resolver.JavaNamespaceResolver; import org.jetbrains.jet.lang.resolve.java.JavaDescriptorSignatureResolver; import org.jetbrains.jet.lang.resolve.java.resolver.JavaConstructorResolver; @@ -56,6 +57,7 @@ public class InjectorForJavaDescriptorResolver { private JavaAnnotationResolver javaAnnotationResolver; private JavaCompileTimeConstResolver javaCompileTimeConstResolver; private JavaClassObjectResolver javaClassObjectResolver; + private JavaSupertypesResolver javaSupertypesResolver; private JavaNamespaceResolver javaNamespaceResolver; private JavaDescriptorSignatureResolver javaDescriptorSignatureResolver; private JavaConstructorResolver javaConstructorResolver; @@ -83,6 +85,7 @@ public class InjectorForJavaDescriptorResolver { this.javaAnnotationResolver = new JavaAnnotationResolver(); this.javaCompileTimeConstResolver = new JavaCompileTimeConstResolver(); this.javaClassObjectResolver = new JavaClassObjectResolver(); + this.javaSupertypesResolver = new JavaSupertypesResolver(); this.javaNamespaceResolver = new JavaNamespaceResolver(); this.javaDescriptorSignatureResolver = new JavaDescriptorSignatureResolver(); this.javaConstructorResolver = new JavaConstructorResolver(); @@ -119,8 +122,8 @@ public class InjectorForJavaDescriptorResolver { javaClassResolver.setPsiClassFinder(psiClassFinder); javaClassResolver.setSemanticServices(javaSemanticServices); javaClassResolver.setSignatureResolver(javaDescriptorSignatureResolver); + javaClassResolver.setSupertypesResolver(javaSupertypesResolver); javaClassResolver.setTrace(bindingTrace); - javaClassResolver.setTypeTransformer(javaTypeTransformer); javaAnnotationResolver.setClassResolver(javaClassResolver); javaAnnotationResolver.setCompileTimeConstResolver(javaCompileTimeConstResolver); @@ -128,11 +131,16 @@ public class InjectorForJavaDescriptorResolver { javaCompileTimeConstResolver.setAnnotationResolver(javaAnnotationResolver); javaCompileTimeConstResolver.setClassResolver(javaClassResolver); - javaClassObjectResolver.setClassResolver(javaClassResolver); javaClassObjectResolver.setJavaDescriptorResolver(javaDescriptorResolver); javaClassObjectResolver.setSemanticServices(javaSemanticServices); + javaClassObjectResolver.setSupertypesResolver(javaSupertypesResolver); javaClassObjectResolver.setTrace(bindingTrace); + javaSupertypesResolver.setClassResolver(javaClassResolver); + javaSupertypesResolver.setSemanticServices(javaSemanticServices); + javaSupertypesResolver.setTrace(bindingTrace); + javaSupertypesResolver.setTypeTransformer(javaTypeTransformer); + javaNamespaceResolver.setJavaSemanticServices(javaSemanticServices); javaNamespaceResolver.setPsiClassFinder(psiClassFinder); javaNamespaceResolver.setTrace(bindingTrace); diff --git a/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForJavaSemanticServices.java b/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForJavaSemanticServices.java index 7205229df52..f95cfa063ea 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForJavaSemanticServices.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForJavaSemanticServices.java @@ -30,6 +30,7 @@ import org.jetbrains.jet.lang.resolve.java.resolver.JavaClassResolver; import org.jetbrains.jet.lang.resolve.java.resolver.JavaAnnotationResolver; import org.jetbrains.jet.lang.resolve.java.resolver.JavaCompileTimeConstResolver; import org.jetbrains.jet.lang.resolve.java.resolver.JavaClassObjectResolver; +import org.jetbrains.jet.lang.resolve.java.resolver.JavaSupertypesResolver; import org.jetbrains.jet.lang.resolve.java.resolver.JavaNamespaceResolver; import org.jetbrains.jet.lang.resolve.java.JavaDescriptorSignatureResolver; import org.jetbrains.jet.lang.resolve.java.resolver.JavaConstructorResolver; @@ -56,6 +57,7 @@ public class InjectorForJavaSemanticServices { private JavaAnnotationResolver javaAnnotationResolver; private JavaCompileTimeConstResolver javaCompileTimeConstResolver; private JavaClassObjectResolver javaClassObjectResolver; + private JavaSupertypesResolver javaSupertypesResolver; private JavaNamespaceResolver javaNamespaceResolver; private JavaDescriptorSignatureResolver javaDescriptorSignatureResolver; private JavaConstructorResolver javaConstructorResolver; @@ -81,6 +83,7 @@ public class InjectorForJavaSemanticServices { this.javaAnnotationResolver = new JavaAnnotationResolver(); this.javaCompileTimeConstResolver = new JavaCompileTimeConstResolver(); this.javaClassObjectResolver = new JavaClassObjectResolver(); + this.javaSupertypesResolver = new JavaSupertypesResolver(); this.javaNamespaceResolver = new JavaNamespaceResolver(); this.javaDescriptorSignatureResolver = new JavaDescriptorSignatureResolver(); this.javaConstructorResolver = new JavaConstructorResolver(); @@ -117,8 +120,8 @@ public class InjectorForJavaSemanticServices { javaClassResolver.setPsiClassFinder(psiClassFinder); javaClassResolver.setSemanticServices(javaSemanticServices); javaClassResolver.setSignatureResolver(javaDescriptorSignatureResolver); + javaClassResolver.setSupertypesResolver(javaSupertypesResolver); javaClassResolver.setTrace(bindingTrace); - javaClassResolver.setTypeTransformer(javaTypeTransformer); javaAnnotationResolver.setClassResolver(javaClassResolver); javaAnnotationResolver.setCompileTimeConstResolver(javaCompileTimeConstResolver); @@ -126,11 +129,16 @@ public class InjectorForJavaSemanticServices { javaCompileTimeConstResolver.setAnnotationResolver(javaAnnotationResolver); javaCompileTimeConstResolver.setClassResolver(javaClassResolver); - javaClassObjectResolver.setClassResolver(javaClassResolver); javaClassObjectResolver.setJavaDescriptorResolver(javaDescriptorResolver); javaClassObjectResolver.setSemanticServices(javaSemanticServices); + javaClassObjectResolver.setSupertypesResolver(javaSupertypesResolver); javaClassObjectResolver.setTrace(bindingTrace); + javaSupertypesResolver.setClassResolver(javaClassResolver); + javaSupertypesResolver.setSemanticServices(javaSemanticServices); + javaSupertypesResolver.setTrace(bindingTrace); + javaSupertypesResolver.setTypeTransformer(javaTypeTransformer); + javaNamespaceResolver.setJavaSemanticServices(javaSemanticServices); javaNamespaceResolver.setPsiClassFinder(psiClassFinder); javaNamespaceResolver.setTrace(bindingTrace); diff --git a/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java b/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java index 0a94f9cb904..634112d0453 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java @@ -52,6 +52,7 @@ import org.jetbrains.jet.lang.resolve.java.resolver.JavaClassResolver; import org.jetbrains.jet.lang.resolve.java.resolver.JavaAnnotationResolver; import org.jetbrains.jet.lang.resolve.java.resolver.JavaCompileTimeConstResolver; import org.jetbrains.jet.lang.resolve.java.resolver.JavaClassObjectResolver; +import org.jetbrains.jet.lang.resolve.java.resolver.JavaSupertypesResolver; import org.jetbrains.jet.lang.resolve.java.resolver.JavaNamespaceResolver; import org.jetbrains.jet.lang.resolve.java.JavaDescriptorSignatureResolver; import org.jetbrains.jet.lang.resolve.java.resolver.JavaConstructorResolver; @@ -99,6 +100,7 @@ public class InjectorForTopDownAnalyzerForJvm implements InjectorForTopDownAnaly private JavaAnnotationResolver javaAnnotationResolver; private JavaCompileTimeConstResolver javaCompileTimeConstResolver; private JavaClassObjectResolver javaClassObjectResolver; + private JavaSupertypesResolver javaSupertypesResolver; private JavaNamespaceResolver javaNamespaceResolver; private JavaDescriptorSignatureResolver javaDescriptorSignatureResolver; private JavaConstructorResolver javaConstructorResolver; @@ -148,6 +150,7 @@ public class InjectorForTopDownAnalyzerForJvm implements InjectorForTopDownAnaly this.javaAnnotationResolver = new JavaAnnotationResolver(); this.javaCompileTimeConstResolver = new JavaCompileTimeConstResolver(); this.javaClassObjectResolver = new JavaClassObjectResolver(); + this.javaSupertypesResolver = new JavaSupertypesResolver(); this.javaNamespaceResolver = new JavaNamespaceResolver(); this.javaDescriptorSignatureResolver = new JavaDescriptorSignatureResolver(); this.javaConstructorResolver = new JavaConstructorResolver(); @@ -274,8 +277,8 @@ public class InjectorForTopDownAnalyzerForJvm implements InjectorForTopDownAnaly javaClassResolver.setPsiClassFinder(psiClassFinder); javaClassResolver.setSemanticServices(javaSemanticServices); javaClassResolver.setSignatureResolver(javaDescriptorSignatureResolver); + javaClassResolver.setSupertypesResolver(javaSupertypesResolver); javaClassResolver.setTrace(bindingTrace); - javaClassResolver.setTypeTransformer(javaTypeTransformer); javaAnnotationResolver.setClassResolver(javaClassResolver); javaAnnotationResolver.setCompileTimeConstResolver(javaCompileTimeConstResolver); @@ -283,11 +286,16 @@ public class InjectorForTopDownAnalyzerForJvm implements InjectorForTopDownAnaly javaCompileTimeConstResolver.setAnnotationResolver(javaAnnotationResolver); javaCompileTimeConstResolver.setClassResolver(javaClassResolver); - javaClassObjectResolver.setClassResolver(javaClassResolver); javaClassObjectResolver.setJavaDescriptorResolver(javaDescriptorResolver); javaClassObjectResolver.setSemanticServices(javaSemanticServices); + javaClassObjectResolver.setSupertypesResolver(javaSupertypesResolver); javaClassObjectResolver.setTrace(bindingTrace); + javaSupertypesResolver.setClassResolver(javaClassResolver); + javaSupertypesResolver.setSemanticServices(javaSemanticServices); + javaSupertypesResolver.setTrace(bindingTrace); + javaSupertypesResolver.setTypeTransformer(javaTypeTransformer); + javaNamespaceResolver.setJavaSemanticServices(javaSemanticServices); javaNamespaceResolver.setPsiClassFinder(psiClassFinder); javaNamespaceResolver.setTrace(bindingTrace); diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaClassObjectResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaClassObjectResolver.java index 05043603353..4bcf6131bc6 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaClassObjectResolver.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaClassObjectResolver.java @@ -48,14 +48,14 @@ import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getClassObjectName; public final class JavaClassObjectResolver { - private JavaClassResolver classResolver; private JavaDescriptorResolver javaDescriptorResolver; private BindingTrace trace; private JavaSemanticServices semanticServices; + private JavaSupertypesResolver supertypesResolver; @Inject - public void setClassResolver(JavaClassResolver classResolver) { - this.classResolver = classResolver; + public void setSupertypesResolver(JavaSupertypesResolver supertypesResolver) { + this.supertypesResolver = supertypesResolver; } @Inject @@ -108,8 +108,8 @@ public final class JavaClassObjectResolver { .getResolverBinaryClassData(); ClassDescriptorFromJvmBytecode classObjectDescriptor = classData.getClassDescriptor(); - classObjectDescriptor.setSupertypes(classResolver.getSupertypes(new PsiClassWrapper(classObjectPsiClass), classData, - new ArrayList(0))); + classObjectDescriptor.setSupertypes(supertypesResolver.getSupertypes(new PsiClassWrapper(classObjectPsiClass), classData, + new ArrayList(0))); setUpClassObjectDescriptor(containing, fqName, classData, getClassObjectName(containing.getName())); return classObjectDescriptor.getResolverBinaryClassData(); } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaClassResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaClassResolver.java index 1a0e0fe9e82..1e7ce6e5633 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaClassResolver.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaClassResolver.java @@ -18,11 +18,9 @@ package org.jetbrains.jet.lang.resolve.java.resolver; import com.google.common.collect.Lists; import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiClassType; import com.intellij.psi.PsiModifier; import gnu.trove.THashMap; import gnu.trove.TObjectHashingStrategy; -import jet.typeinfo.TypeInfoVariance; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; @@ -39,19 +37,9 @@ import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.FqNameBase; import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe; import org.jetbrains.jet.lang.resolve.name.Name; -import org.jetbrains.jet.lang.types.ErrorUtils; import org.jetbrains.jet.lang.types.JetType; -import org.jetbrains.jet.lang.types.TypeUtils; -import org.jetbrains.jet.lang.types.lang.JetStandardClasses; -import org.jetbrains.jet.lang.types.lang.JetStandardLibrary; -import org.jetbrains.jet.rt.signature.JetSignatureAdapter; -import org.jetbrains.jet.rt.signature.JetSignatureExceptionsAdapter; -import org.jetbrains.jet.rt.signature.JetSignatureReader; -import org.jetbrains.jet.rt.signature.JetSignatureVisitor; import javax.inject.Inject; -import java.util.ArrayList; -import java.util.Collection; import java.util.List; import java.util.Map; @@ -82,8 +70,8 @@ public final class JavaClassResolver { private JavaAnnotationResolver annotationResolver; private PsiClassFinder psiClassFinder; private JavaNamespaceResolver namespaceResolver; - private JavaTypeTransformer typeTransformer; private JavaClassObjectResolver classObjectResolver; + private JavaSupertypesResolver supertypesResolver; public JavaClassResolver() { } @@ -129,8 +117,8 @@ public final class JavaClassResolver { } @Inject - public void setTypeTransformer(JavaTypeTransformer typeTransformer) { - this.typeTransformer = typeTransformer; + public void setSupertypesResolver(JavaSupertypesResolver supertypesResolver) { + this.supertypesResolver = supertypesResolver; } @Nullable @@ -247,7 +235,7 @@ public final class JavaClassResolver { // TODO: ugly hack: tests crash if initializeTypeParameters called with class containing proper supertypes List classTypeParameters = classDescriptor.getTypeConstructor().getParameters(); - supertypes.addAll(getSupertypes(new PsiClassWrapper(psiClass), classData, classTypeParameters)); + supertypes.addAll(supertypesResolver.getSupertypes(new PsiClassWrapper(psiClass), classData, classTypeParameters)); ResolverClassData classObjectData = classObjectResolver.createClassObjectDescriptor(classDescriptor, psiClass); classDescriptorCache.put(DescriptorResolverUtils.getFqNameForClassObject(psiClass), classObjectData); @@ -278,8 +266,8 @@ public final class JavaClassResolver { return Modality.FINAL; } return Modality.convertFromFlags( - psiClass.hasModifierProperty(PsiModifier.ABSTRACT) || psiClass.isInterface(), - !psiClass.hasModifierProperty(PsiModifier.FINAL)); + psiClass.hasModifierProperty(PsiModifier.ABSTRACT) || psiClass.isInterface(), + !psiClass.hasModifierProperty(PsiModifier.FINAL)); } void checkFqNamesAreConsistent(@NotNull PsiClass psiClass, @NotNull FqName desiredFqName) { @@ -293,105 +281,6 @@ public final class JavaClassResolver { } } - public Collection getSupertypes( - @NotNull PsiClassWrapper psiClass, - @NotNull ResolverClassData classData, - @NotNull List typeParameters - ) { - ClassDescriptor classDescriptor = classData.getClassDescriptor(); - - final List result = new ArrayList(); - - String context = "class " + psiClass.getQualifiedName(); - - if (psiClass.getJetClass().signature().length() > 0) { - final TypeVariableResolver typeVariableResolver = - TypeVariableResolvers.typeVariableResolverFromTypeParameters(typeParameters, classDescriptor, context); - - new JetSignatureReader(psiClass.getJetClass().signature()).accept(new JetSignatureExceptionsAdapter() { - @Override - public JetSignatureVisitor visitFormalTypeParameter(String name, TypeInfoVariance variance, boolean reified) { - // TODO: collect - return new JetSignatureAdapter(); - } - - @Override - public JetSignatureVisitor visitSuperclass() { - return new JetTypeJetSignatureReader(semanticServices, JetStandardLibrary.getInstance(), - typeVariableResolver) { - @Override - protected void done(@NotNull JetType jetType) { - if (!jetType.equals(JetStandardClasses.getAnyType())) { - result.add(jetType); - } - } - }; - } - - @Override - public JetSignatureVisitor visitInterface() { - return visitSuperclass(); - } - }); - } - else { - TypeVariableResolver typeVariableResolverForSupertypes = - TypeVariableResolvers.typeVariableResolverFromTypeParameters(typeParameters, classDescriptor, context); - transformSupertypeList(result, psiClass.getPsiClass().getExtendsListTypes(), typeVariableResolverForSupertypes); - transformSupertypeList(result, psiClass.getPsiClass().getImplementsListTypes(), typeVariableResolverForSupertypes); - } - - for (JetType supertype : result) { - if (ErrorUtils.isErrorType(supertype)) { - trace.record(BindingContext.INCOMPLETE_HIERARCHY, classDescriptor); - } - } - - if (result.isEmpty()) { - if (classData.isKotlin() - || DescriptorResolverUtils.OBJECT_FQ_NAME.equalsTo(psiClass.getQualifiedName()) - // TODO: annotations - || classDescriptor.getKind() == ClassKind.ANNOTATION_CLASS) { - result.add(JetStandardClasses.getAnyType()); - } - else { - ClassDescriptor object = resolveJavaLangObject(); - if (object != null) { - result.add(object.getDefaultType()); - } - else { - result.add(JetStandardClasses.getAnyType()); - } - } - } - return result; - } - - private void transformSupertypeList( - List result, - PsiClassType[] extendsListTypes, - TypeVariableResolver typeVariableResolver - ) { - for (PsiClassType type : extendsListTypes) { - PsiClass resolved = type.resolve(); - if (resolved != null) { - final String qualifiedName = resolved.getQualifiedName(); - assert qualifiedName != null; - if (JvmStdlibNames.JET_OBJECT.getFqName().equalsTo(qualifiedName)) { - continue; - } - } - - JetType transform = typeTransformer - .transformToType(type, JavaTypeTransformer.TypeUsage.SUPERTYPE, typeVariableResolver); - if (ErrorUtils.isErrorType(transform)) { - continue; - } - - result.add(TypeUtils.makeNotNullable(transform)); - } - } - @NotNull private ClassOrNamespaceDescriptor resolveParentDescriptor(@NotNull PsiClass psiClass) { final String qualifiedName = psiClass.getQualifiedName(); @@ -425,15 +314,6 @@ public final class JavaClassResolver { return ns; } - @Nullable - private ClassDescriptor resolveJavaLangObject() { - ClassDescriptor clazz = resolveClass(DescriptorResolverUtils.OBJECT_FQ_NAME, DescriptorSearchRule.IGNORE_IF_FOUND_IN_KOTLIN); - if (clazz == null) { - // TODO: warning - } - return clazz; - } - private static ClassKind getClassKind(@NotNull PsiClass psiClass, @NotNull JetClassAnnotation jetClassAnnotation) { if (psiClass.isInterface()) { return (psiClass.isAnnotationType() ? ClassKind.ANNOTATION_CLASS : ClassKind.TRAIT); diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaSupertypesResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaSupertypesResolver.java new file mode 100644 index 00000000000..f8620e236ab --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaSupertypesResolver.java @@ -0,0 +1,206 @@ +/* + * Copyright 2010-2012 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 org.jetbrains.jet.lang.resolve.java.resolver; + +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiClassType; +import jet.typeinfo.TypeInfoVariance; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.descriptors.ClassDescriptor; +import org.jetbrains.jet.lang.descriptors.ClassKind; +import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; +import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.BindingTrace; +import org.jetbrains.jet.lang.resolve.java.*; +import org.jetbrains.jet.lang.resolve.java.data.ResolverClassData; +import org.jetbrains.jet.lang.resolve.java.wrapper.PsiClassWrapper; +import org.jetbrains.jet.lang.types.ErrorUtils; +import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.lang.types.TypeUtils; +import org.jetbrains.jet.lang.types.lang.JetStandardClasses; +import org.jetbrains.jet.lang.types.lang.JetStandardLibrary; +import org.jetbrains.jet.rt.signature.JetSignatureAdapter; +import org.jetbrains.jet.rt.signature.JetSignatureExceptionsAdapter; +import org.jetbrains.jet.rt.signature.JetSignatureReader; +import org.jetbrains.jet.rt.signature.JetSignatureVisitor; + +import javax.inject.Inject; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public final class JavaSupertypesResolver { + + private BindingTrace trace; + private JavaSemanticServices semanticServices; + private JavaTypeTransformer typeTransformer; + private JavaClassResolver classResolver; + + @Inject + public void setTrace(BindingTrace trace) { + this.trace = trace; + } + + @Inject + public void setSemanticServices(JavaSemanticServices semanticServices) { + this.semanticServices = semanticServices; + } + + @Inject + public void setTypeTransformer(JavaTypeTransformer typeTransformer) { + this.typeTransformer = typeTransformer; + } + + @Inject + public void setClassResolver(JavaClassResolver classResolver) { + this.classResolver = classResolver; + } + + public Collection getSupertypes( + @NotNull PsiClassWrapper psiClass, + @NotNull ResolverClassData classData, + @NotNull List typeParameters + ) { + ClassDescriptor classDescriptor = classData.getClassDescriptor(); + + final List result = new ArrayList(); + + String context = "class " + psiClass.getQualifiedName(); + + if (psiClass.getJetClass().signature().length() > 0) { + readSuperTypes(psiClass, typeParameters, classDescriptor, result, context); + } + else { + TypeVariableResolver typeVariableResolverForSupertypes = + TypeVariableResolvers.typeVariableResolverFromTypeParameters(typeParameters, classDescriptor, context); + transformSupertypeList(result, psiClass.getPsiClass().getExtendsListTypes(), typeVariableResolverForSupertypes); + transformSupertypeList(result, psiClass.getPsiClass().getImplementsListTypes(), typeVariableResolverForSupertypes); + } + + reportIncompleteHierarchyForErrorTypes(classDescriptor, result); + + if (result.isEmpty()) { + addBaseClass(psiClass, classData, classDescriptor, result); + } + return result; + } + + private void readSuperTypes( + PsiClassWrapper psiClass, + List typeParameters, + ClassDescriptor classDescriptor, + final List result, + String context + ) { + final TypeVariableResolver typeVariableResolver = + TypeVariableResolvers.typeVariableResolverFromTypeParameters(typeParameters, classDescriptor, context); + + new JetSignatureReader(psiClass.getJetClass().signature()).accept(new JetSignatureExceptionsAdapter() { + @Override + public JetSignatureVisitor visitFormalTypeParameter(String name, TypeInfoVariance variance, boolean reified) { + // TODO: collect + return new JetSignatureAdapter(); + } + + @Override + public JetSignatureVisitor visitSuperclass() { + return new JetTypeJetSignatureReader(semanticServices, JetStandardLibrary.getInstance(), + typeVariableResolver) { + @Override + protected void done(@NotNull JetType jetType) { + if (!jetType.equals(JetStandardClasses.getAnyType())) { + result.add(jetType); + } + } + }; + } + + @Override + public JetSignatureVisitor visitInterface() { + return visitSuperclass(); + } + }); + } + + private void addBaseClass( + @NotNull PsiClassWrapper psiClass, + @NotNull ResolverClassData classData, + @NotNull ClassDescriptor classDescriptor, + @NotNull List result + ) { + if (classData.isKotlin() + || DescriptorResolverUtils.OBJECT_FQ_NAME.equalsTo(psiClass.getQualifiedName()) + // TODO: annotations + || classDescriptor.getKind() == ClassKind.ANNOTATION_CLASS) { + result.add(JetStandardClasses.getAnyType()); + } + else { + ClassDescriptor object = resolveJavaLangObject(); + if (object != null) { + result.add(object.getDefaultType()); + } + else { + throw new IllegalStateException("Could not resolve java.lang.Object"); + } + } + } + + private void reportIncompleteHierarchyForErrorTypes(ClassDescriptor classDescriptor, List result) { + for (JetType supertype : result) { + if (ErrorUtils.isErrorType(supertype)) { + trace.record(BindingContext.INCOMPLETE_HIERARCHY, classDescriptor); + } + } + } + + private void transformSupertypeList( + List result, + PsiClassType[] extendsListTypes, + TypeVariableResolver typeVariableResolver + ) { + for (PsiClassType type : extendsListTypes) { + PsiClass resolved = type.resolve(); + if (resolved != null) { + final String qualifiedName = resolved.getQualifiedName(); + assert qualifiedName != null; + if (JvmStdlibNames.JET_OBJECT.getFqName().equalsTo(qualifiedName)) { + continue; + } + } + + JetType transform = typeTransformer + .transformToType(type, JavaTypeTransformer.TypeUsage.SUPERTYPE, typeVariableResolver); + if (ErrorUtils.isErrorType(transform)) { + continue; + } + + result.add(TypeUtils.makeNotNullable(transform)); + } + } + + + @Nullable + private ClassDescriptor resolveJavaLangObject() { + ClassDescriptor clazz = classResolver.resolveClass(DescriptorResolverUtils.OBJECT_FQ_NAME, + DescriptorSearchRule.IGNORE_IF_FOUND_IN_KOTLIN); + if (clazz == null) { + // TODO: warning + } + return clazz; + } +}