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 29eb635b6ac..f50f8c8af0a 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForJavaDescriptorResolver.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForJavaDescriptorResolver.java @@ -20,6 +20,7 @@ import com.intellij.openapi.project.Project; import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver; import org.jetbrains.jet.lang.resolve.java.PsiClassFinderImpl; +import org.jetbrains.jet.lang.resolve.java.vfilefinder.VirtualFileFinder; 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; @@ -43,6 +44,7 @@ public class InjectorForJavaDescriptorResolver { private final BindingTrace bindingTrace; private final JavaDescriptorResolver javaDescriptorResolver; private final PsiClassFinderImpl psiClassFinder; + private final VirtualFileFinder virtualFileFinder; private final JavaClassResolver javaClassResolver; private final JavaAnnotationResolver javaAnnotationResolver; private final JavaCompileTimeConstResolver javaCompileTimeConstResolver; @@ -65,6 +67,7 @@ public class InjectorForJavaDescriptorResolver { this.bindingTrace = bindingTrace; this.javaDescriptorResolver = new JavaDescriptorResolver(); this.psiClassFinder = new PsiClassFinderImpl(); + this.virtualFileFinder = com.intellij.openapi.components.ServiceManager.getService(project, VirtualFileFinder.class); this.javaClassResolver = new JavaClassResolver(); this.javaAnnotationResolver = new JavaAnnotationResolver(); this.javaCompileTimeConstResolver = new JavaCompileTimeConstResolver(); @@ -96,6 +99,7 @@ public class InjectorForJavaDescriptorResolver { javaClassResolver.setSignatureResolver(javaSignatureResolver); javaClassResolver.setSupertypesResolver(javaSupertypeResolver); javaClassResolver.setTrace(bindingTrace); + javaClassResolver.setVirtualFileFinder(virtualFileFinder); javaAnnotationResolver.setClassResolver(javaClassResolver); javaAnnotationResolver.setCompileTimeConstResolver(javaCompileTimeConstResolver); 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 6c7da56a9c7..55baffa074d 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java @@ -31,6 +31,7 @@ import org.jetbrains.jet.lang.resolve.java.JavaBridgeConfiguration; import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver; import org.jetbrains.jet.lang.resolve.java.PsiClassFinderImpl; import org.jetbrains.jet.lang.resolve.NamespaceFactoryImpl; +import org.jetbrains.jet.lang.resolve.java.vfilefinder.VirtualFileFinder; import org.jetbrains.jet.lang.resolve.DeclarationResolver; import org.jetbrains.jet.lang.resolve.AnnotationResolver; import org.jetbrains.jet.lang.resolve.calls.CallResolver; @@ -81,6 +82,7 @@ public class InjectorForTopDownAnalyzerForJvm implements InjectorForTopDownAnaly private final JavaDescriptorResolver javaDescriptorResolver; private final PsiClassFinderImpl psiClassFinder; private final NamespaceFactoryImpl namespaceFactory; + private final VirtualFileFinder virtualFileFinder; private final DeclarationResolver declarationResolver; private final AnnotationResolver annotationResolver; private final CallResolver callResolver; @@ -132,6 +134,7 @@ public class InjectorForTopDownAnalyzerForJvm implements InjectorForTopDownAnaly this.javaDescriptorResolver = new JavaDescriptorResolver(); this.psiClassFinder = new PsiClassFinderImpl(); this.namespaceFactory = new NamespaceFactoryImpl(); + this.virtualFileFinder = com.intellij.openapi.components.ServiceManager.getService(project, VirtualFileFinder.class); this.declarationResolver = new DeclarationResolver(); this.annotationResolver = new AnnotationResolver(); this.callResolver = new CallResolver(); @@ -283,6 +286,7 @@ public class InjectorForTopDownAnalyzerForJvm implements InjectorForTopDownAnaly javaClassResolver.setSignatureResolver(javaSignatureResolver); javaClassResolver.setSupertypesResolver(javaSupertypeResolver); javaClassResolver.setTrace(bindingTrace); + javaClassResolver.setVirtualFileFinder(virtualFileFinder); javaAnnotationResolver.setClassResolver(javaClassResolver); javaAnnotationResolver.setCompileTimeConstResolver(javaCompileTimeConstResolver); 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 ab567a96a45..8640b2593d8 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 @@ -36,6 +36,7 @@ import org.jetbrains.jet.lang.resolve.java.*; import org.jetbrains.jet.lang.resolve.java.descriptor.ClassDescriptorFromJvmBytecode; import org.jetbrains.jet.lang.resolve.java.sam.SingleAbstractMethodUtils; import org.jetbrains.jet.lang.resolve.java.scope.JavaClassNonStaticMembersScope; +import org.jetbrains.jet.lang.resolve.java.vfilefinder.VirtualFileFinder; import org.jetbrains.jet.lang.resolve.java.wrapper.PsiMethodWrapper; import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.FqNameBase; @@ -56,7 +57,6 @@ import java.util.*; import static org.jetbrains.jet.lang.resolve.DescriptorResolver.createEnumClassObjectValueOfMethod; import static org.jetbrains.jet.lang.resolve.DescriptorResolver.createEnumClassObjectValuesMethod; import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getClassObjectName; -import static org.jetbrains.jet.lang.resolve.java.resolver.DeserializedResolverUtils.getVirtualFile; public final class JavaClassResolver { @@ -91,10 +91,16 @@ public final class JavaClassResolver { private JavaSupertypeResolver supertypesResolver; private JavaFunctionResolver functionResolver; private DeserializedDescriptorResolver kotlinDescriptorResolver; + private VirtualFileFinder virtualFileFinder; public JavaClassResolver() { } + @Inject + public void setVirtualFileFinder(VirtualFileFinder virtualFileFinder) { + this.virtualFileFinder = virtualFileFinder; + } + @Inject public void setTrace(BindingTrace trace) { this.trace = trace; @@ -202,6 +208,30 @@ public final class JavaClassResolver { } private ClassDescriptor doResolveClass(@NotNull FqName qualifiedName, @NotNull PostponedTasks tasks) { + //TODO: correct scope + VirtualFile file = virtualFileFinder.find(qualifiedName); + if (file != null) { + //TODO: code duplication + //TODO: it is a hackish way to determine whether it is inner class or not + boolean isInnerClass = file.getName().contains("$"); + ClassOrNamespaceDescriptor containingDeclaration = resolveParentDescriptor(qualifiedName, isInnerClass); + // class may be resolved during resolution of parent + ClassDescriptor cachedDescriptor = classDescriptorCache.get(javaClassToKotlinFqName(qualifiedName)); + if (cachedDescriptor != null) { + return cachedDescriptor; + } + assert (!unresolvedCache.contains(qualifiedName)) + : "We can resolve the class, so it can't be 'unresolved' during parent resolution"; + + ClassId id = ClassId.fromFqNameAndContainingDeclaration(qualifiedName, containingDeclaration); + ErrorReporter errorReporter = AbiVersionUtil.abiVersionErrorReporter(file, qualifiedName, trace); + ClassDescriptor deserializedDescriptor = kotlinDescriptorResolver.resolveClass(id, file, errorReporter); + if (deserializedDescriptor != null) { + cache(javaClassToKotlinFqName(qualifiedName), deserializedDescriptor); + return deserializedDescriptor; + } + } + PsiClass psiClass = psiClassFinder.findPsiClass(qualifiedName, PsiClassFinder.RuntimeClassesHandleMode.REPORT_ERROR); if (psiClass == null) { cacheNegativeValue(javaClassToKotlinFqName(qualifiedName)); @@ -213,8 +243,21 @@ public final class JavaClassResolver { if (alreadyResolved != null) { return alreadyResolved; } + //TODO: code duplication + ClassOrNamespaceDescriptor containingDeclaration = resolveParentDescriptor(qualifiedName, isContainedInClass(psiClass)); + // class may be resolved during resolution of parent + ClassDescriptor cachedDescriptor = classDescriptorCache.get(javaClassToKotlinFqName(qualifiedName)); + if (cachedDescriptor != null) { + return cachedDescriptor; + } + assert (!unresolvedCache + .contains(qualifiedName)) : "We can resolve the class, so it can't be 'unresolved' during parent resolution"; - return createJavaClassDescriptor(qualifiedName, psiClass, tasks); + checkFqNamesAreConsistent(psiClass, qualifiedName); + checkPsiClassIsNotJet(psiClass); + + + return doCreateClassDescriptor(qualifiedName, psiClass, tasks, containingDeclaration); } private void cacheNegativeValue(@NotNull FqNameBase qualifiedName) { @@ -229,42 +272,6 @@ public final class JavaClassResolver { return qualifiedName.asString().endsWith(JvmAbi.TRAIT_IMPL_SUFFIX); } - @NotNull - private ClassDescriptor createJavaClassDescriptor( - @NotNull FqName fqName, @NotNull PsiClass psiClass, - @NotNull PostponedTasks taskList - ) { - checkFqNamesAreConsistent(psiClass, fqName); - checkPsiClassIsNotJet(psiClass); - - ClassOrNamespaceDescriptor containingDeclaration = resolveParentDescriptor(psiClass); - // class may be resolved during resolution of parent - ClassDescriptor cachedDescriptor = classDescriptorCache.get(javaClassToKotlinFqName(fqName)); - if (cachedDescriptor != null) { - return cachedDescriptor; - } - - assert (!unresolvedCache.contains(fqName)) : "We can resolve the class, so it can't be 'unresolved' during parent resolution"; - - VirtualFile outerClassFile = psiClass.getContainingFile().getVirtualFile(); - if (outerClassFile != null) { - ClassId id = ClassId.fromFqNameAndContainingDeclaration(fqName, containingDeclaration); - VirtualFile file = getVirtualFile(id, outerClassFile); - if (file != null) { - ClassDescriptor deserializedDescriptor = kotlinDescriptorResolver.resolveClass(id, file, - DescriptorResolverUtils.createPsiBasedErrorReporter(psiClass, trace)); - - if (deserializedDescriptor != null) { - //TODO: class object and psi class - cache(javaClassToKotlinFqName(fqName), deserializedDescriptor); - return deserializedDescriptor; - } - } - } - - return doCreateClassDescriptor(fqName, psiClass, taskList, containingDeclaration); - } - @NotNull private ClassDescriptorFromJvmBytecode doCreateClassDescriptor( @NotNull FqName fqName, @@ -418,22 +425,25 @@ public final class JavaClassResolver { } @NotNull - private ClassOrNamespaceDescriptor resolveParentDescriptor(@NotNull PsiClass psiClass) { - if (isContainedInClass(psiClass)) { - return resolveParentClass(psiClass); + private ClassOrNamespaceDescriptor resolveParentDescriptor(@NotNull FqName childClassFQName, boolean isInnerClass) { + FqName parentFqName = childClassFQName.parent(); + if (isInnerClass) { + ClassDescriptor parentClass = resolveClass(parentFqName, DescriptorSearchRule.INCLUDE_KOTLIN); + if (parentClass == null) { + throw new IllegalStateException("Could not resolve " + parentFqName + " required to be parent for " + childClassFQName); + } + return parentClass; } else { - return resolveParentNamespace(psiClass); + //TODO: why do we include kotlin here? what this flags means anyway? + NamespaceDescriptor parentNamespace = namespaceResolver.resolveNamespace(parentFqName, DescriptorSearchRule.INCLUDE_KOTLIN); + if (parentNamespace == null) { + throw new IllegalStateException("Could not resolve " + parentFqName + " required to be parent for " + childClassFQName); + } + return parentNamespace; } } - @NotNull - private static FqName getFqName(@NotNull PsiClass psiClass) { - String qualifiedName = psiClass.getQualifiedName(); - assert qualifiedName != null; - return new FqName(qualifiedName); - } - // This method replaces "object" segments of FQ name to "" @NotNull private static FqNameUnsafe javaClassToKotlinFqName(@NotNull FqName rawFqName) { @@ -459,30 +469,6 @@ public final class JavaClassResolver { return isContainedInClass(psiClass) && !psiClass.hasModifierProperty(PsiModifier.STATIC); } - @NotNull - private ClassOrNamespaceDescriptor resolveParentClass(@NotNull PsiClass psiClass) { - PsiClass containingClass = psiClass.getContainingClass(); - assert containingClass != null; - FqName containerFqName = getFqName(containingClass); - ClassDescriptor parentClass = resolveClass(containerFqName, DescriptorSearchRule.INCLUDE_KOTLIN); - if (parentClass == null) { - throw new IllegalStateException( - "PsiClass not found by name " + containerFqName + ", required to be container declaration of " + getFqName(psiClass)); - } - return parentClass; - } - - @NotNull - private ClassOrNamespaceDescriptor resolveParentNamespace(@NotNull PsiClass psiClass) { - FqName namespaceFqName = getFqName(psiClass).parent(); - NamespaceDescriptor parentNamespace = namespaceResolver.resolveNamespace(namespaceFqName, DescriptorSearchRule.INCLUDE_KOTLIN); - if (parentNamespace == null) { - throw new IllegalStateException("cannot resolve namespace " + namespaceFqName + - ", required to be container for " + getFqName(psiClass)); - } - return parentNamespace; - } - @NotNull private static ClassKind getClassKind(@NotNull PsiClass psiClass) { if (psiClass.isInterface()) { diff --git a/generators/org/jetbrains/jet/generators/injectors/GenerateInjectors.java b/generators/org/jetbrains/jet/generators/injectors/GenerateInjectors.java index a2ebabb5bb3..cf66bfc6538 100644 --- a/generators/org/jetbrains/jet/generators/injectors/GenerateInjectors.java +++ b/generators/org/jetbrains/jet/generators/injectors/GenerateInjectors.java @@ -36,6 +36,7 @@ import org.jetbrains.jet.lang.resolve.calls.NeedSyntheticCallResolverExtension; import org.jetbrains.jet.lang.resolve.java.JavaBridgeConfiguration; import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver; import org.jetbrains.jet.lang.resolve.java.PsiClassFinderImpl; +import org.jetbrains.jet.lang.resolve.java.vfilefinder.VirtualFileFinder; import org.jetbrains.jet.lang.resolve.lazy.ResolveSession; import org.jetbrains.jet.lang.resolve.lazy.ScopeProvider; import org.jetbrains.jet.lang.types.DependencyClassByQualifiedNameResolverDummyImpl; @@ -103,6 +104,9 @@ public class GenerateInjectors { generator.addField(JavaDescriptorResolver.class); generator.addField(PsiClassFinderImpl.class); generator.addPublicField(NamespaceFactoryImpl.class); + generator.addField(false, VirtualFileFinder.class, "virtualFileFinder", + new GivenExpression( + "com.intellij.openapi.components.ServiceManager.getService(project, VirtualFileFinder.class)")); generator.generate("compiler/frontend.java/src", "org.jetbrains.jet.di", "InjectorForTopDownAnalyzerForJvm", GenerateInjectors.class); } @@ -117,6 +121,8 @@ public class GenerateInjectors { // Fields generator.addPublicField(JavaDescriptorResolver.class); generator.addPublicField(PsiClassFinderImpl.class); + generator.addField(false, VirtualFileFinder.class, "virtualFileFinder", + new GivenExpression("com.intellij.openapi.components.ServiceManager.getService(project, VirtualFileFinder.class)")); generator.generate("compiler/frontend.java/src", "org.jetbrains.jet.di", "InjectorForJavaDescriptorResolver", GenerateInjectors.class);