From 2e4d166d6f906f75eff3b8a546ca30a094832980 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Tue, 31 Dec 2013 21:01:25 +0400 Subject: [PATCH] Loading deseralized descriptors integrated with loading from bare Java code --- .../jet/types/JetTypeCheckerTest.java | 4 +- .../resolve/java/JavaDescriptorResolver.java | 67 +------------------ .../lazy/LazyJavaPackageFragmentProvider.kt | 19 ++++-- .../lazy/descriptors/LazyJavaMemberScope.kt | 6 ++ .../LazyJavaPackageFragmentScope.kt | 37 +++++++--- .../jet/lang/resolve/java/lazy/resolvers.kt | 28 +++++++- 6 files changed, 82 insertions(+), 79 deletions(-) diff --git a/compiler/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java b/compiler/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java index 157235d8111..8f85d017743 100644 --- a/compiler/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java +++ b/compiler/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java @@ -29,6 +29,7 @@ import org.jetbrains.jet.di.InjectorForJavaDescriptorResolver; import org.jetbrains.jet.di.InjectorForJavaDescriptorResolverUtil; import org.jetbrains.jet.di.InjectorForTests; import org.jetbrains.jet.lang.descriptors.ModuleDescriptor; +import org.jetbrains.jet.lang.descriptors.ModuleDescriptorImpl; import org.jetbrains.jet.lang.descriptors.PackageViewDescriptor; import org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor; import org.jetbrains.jet.lang.descriptors.impl.ReceiverParameterDescriptorImpl; @@ -589,7 +590,8 @@ public class JetTypeCheckerTest extends JetLiteFixture { scope, scope.getContainingDeclaration(), RedeclarationHandler.DO_NOTHING, "JetTypeCheckerTest.addImports"); InjectorForJavaDescriptorResolver injector = InjectorForJavaDescriptorResolverUtil.create(getProject(), new BindingTraceContext()); JavaDescriptorResolver javaDescriptorResolver = injector.getJavaDescriptorResolver(); - ModuleDescriptor module = javaDescriptorResolver.getModule(); + ModuleDescriptorImpl module = (ModuleDescriptorImpl) javaDescriptorResolver.getModule(); + module.addFragmentProvider(KotlinBuiltIns.getInstance().getBuiltInsModule().getPackageFragmentProvider()); for (ImportPath defaultImport : module.getDefaultImports()) { writableScope.importScope(module.getPackage(defaultImport.fqnPart()).getMemberScope()); } diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java index db91bd4e490..3a1d0829a0f 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java @@ -16,31 +16,24 @@ package org.jetbrains.jet.lang.resolve.java; -import jet.Function1; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.PlatformToKotlinClassMap; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.ModuleDescriptor; import org.jetbrains.jet.lang.descriptors.PackageFragmentDescriptor; -import org.jetbrains.jet.lang.resolve.ImportPath; import org.jetbrains.jet.lang.resolve.java.lazy.GlobalJavaResolverContext; import org.jetbrains.jet.lang.resolve.java.lazy.LazyJavaClassResolver; import org.jetbrains.jet.lang.resolve.java.lazy.LazyJavaPackageFragmentProvider; import org.jetbrains.jet.lang.resolve.java.resolver.*; import org.jetbrains.jet.lang.resolve.java.structure.JavaClass; -import org.jetbrains.jet.lang.resolve.java.structure.JavaPackage; import org.jetbrains.jet.lang.resolve.kotlin.DeserializedDescriptorResolver; import org.jetbrains.jet.lang.resolve.kotlin.KotlinClassFinder; -import org.jetbrains.jet.lang.resolve.kotlin.KotlinJvmBinaryClass; import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.types.DependencyClassByQualifiedNameResolver; import org.jetbrains.jet.storage.LockBasedStorageManager; -import org.jetbrains.jet.storage.MemoizedFunctionToNullable; import javax.inject.Inject; -import java.util.Collections; import static org.jetbrains.jet.lang.resolve.java.DescriptorSearchRule.IGNORE_KOTLIN_SOURCES; @@ -55,23 +48,6 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes private final LockBasedStorageManager storageManager = new LockBasedStorageManager(); - private final MemoizedFunctionToNullable kotlinClassesFromBinaries = storageManager.createMemoizedFunctionWithNullableValues( - new Function1() { - @Override - public ClassDescriptor invoke(FqName fqName) { - //TODO: correct scope - KotlinJvmBinaryClass kotlinClass = kotlinClassFinder.find(fqName); - if (kotlinClass != null) { - ClassDescriptor deserializedDescriptor = deserializedDescriptorResolver.resolveClass(kotlinClass); - if (deserializedDescriptor != null) { - return deserializedDescriptor; - } - } - return null; - } - } - ); - private JavaClassResolver classResolver; private JavaPackageFragmentProvider packageFragmentProvider; private JavaClassFinder javaClassFinder; @@ -150,36 +126,7 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes lazyJavaPackageFragmentProvider = new LazyJavaPackageFragmentProvider( new GlobalJavaResolverContext( storageManager, - new JavaClassFinder() { - - @Nullable - @Override - public JavaClass findClass(@NotNull FqName fqName) { - // Do not look for JavaClasses for Kotlin binaries & built-ins - if (kotlinClassesFromBinaries.invoke(fqName) != null - //|| kotlinNamespacesFromBinaries.invoke(fqName) != null - || JavaClassResolver.getKotlinBuiltinClassDescriptor(fqName) != null) { - return null; - } - - JavaClass javaClass = javaClassFinder.findClass(fqName); - if (javaClass == null) { - return null; - } - - // Light classes are not proper binaries either - if (javaClass.getOriginKind() == JavaClass.OriginKind.KOTLIN_LIGHT_CLASS) { - return null; - } - return javaClass; - } - - @Nullable - @Override - public JavaPackage findPackage(@NotNull FqName fqName) { - return javaClassFinder.findPackage(fqName); - } - }, + javaClassFinder, kotlinClassFinder, deserializedDescriptorResolver, new LazyJavaClassResolver() { @@ -195,17 +142,7 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes @Override public ClassDescriptor resolveClassByFqName(FqName fqName) { - ClassDescriptor kotlinClassDescriptor = javaResolverCache.getClassResolvedFromSource(fqName); - if (kotlinClassDescriptor != null) { - return kotlinClassDescriptor; - } - - ClassDescriptor classFromBinaries = kotlinClassesFromBinaries.invoke(fqName); - if (classFromBinaries != null) { - return classFromBinaries; - } - - return null; + return javaResolverCache.getClassResolvedFromSource(fqName); } }, externalAnnotationResolver, diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/LazyJavaPackageFragmentProvider.kt b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/LazyJavaPackageFragmentProvider.kt index de5689dbb1e..465a2c976e9 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/LazyJavaPackageFragmentProvider.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/LazyJavaPackageFragmentProvider.kt @@ -12,6 +12,8 @@ import org.jetbrains.jet.lang.resolve.java.resolver.DescriptorResolverUtils import org.jetbrains.jet.lang.resolve.java.resolver.JavaPackageFragmentProvider import org.jetbrains.jet.lang.resolve.java.lazy.descriptors.LazyJavaPackageFragment import org.jetbrains.jet.lang.resolve.name.Name +import org.jetbrains.jet.lang.resolve.scopes.JetScope +import org.jetbrains.jet.lang.resolve.kotlin.KotlinJvmBinaryClass public open class LazyJavaPackageFragmentProvider( private val outerContext: GlobalJavaResolverContext, @@ -43,7 +45,7 @@ public open class LazyJavaPackageFragmentProvider( LazyPackageFragmentForJavaPackage(c, _module, jPackage) } else { - val jClass = c.finder.findClass(fqName) + val jClass = c.findJavaClass(fqName) if (jClass != null && DescriptorResolverUtils.isJavaClassVisibleAsPackage(jClass)) { LazyPackageFragmentForJavaClass(c, _module, jClass) } @@ -61,14 +63,22 @@ public open class LazyJavaPackageFragmentProvider( fun getClass(fqName: FqName): ClassDescriptor? = c.javaClassResolver.resolveClassByFqName(fqName) + internal val resolveKotlinBinaryClass = c.storageManager.createMemoizedFunctionWithNullableValues { + (kotlinClass: KotlinJvmBinaryClass) -> c.deserializedDescriptorResolver.resolveClass(kotlinClass) + } + private inner class FragmentClassResolver : LazyJavaClassResolver { override fun resolveClass(javaClass: JavaClass): ClassDescriptor? { // TODO: there's no notion of module separation here. We must refuse to resolve classes from other modules val fqName = javaClass.getFqName() if (fqName != null) { - // TODO: this should be handled by module seperation logic + // TODO: this should be handled by module separation logic val builtinClass = JavaClassResolver.getKotlinBuiltinClassDescriptor(fqName) if (builtinClass != null) return builtinClass + + if (javaClass.getOriginKind() == JavaClass.OriginKind.KOTLIN_LIGHT_CLASS) { + return c.javaResolverCache.getClassResolvedFromSource(fqName) + } } val outer = javaClass.getOuterClass() @@ -83,15 +93,16 @@ public open class LazyJavaPackageFragmentProvider( outerPackage.getMemberScope() } return scope.getClassifier(javaClass.getName()) as? ClassDescriptor + ?: outerContext.javaClassResolver.resolveClass(javaClass) } override fun resolveClassByFqName(fqName: FqName): ClassDescriptor? { val builtinClass = JavaClassResolver.getKotlinBuiltinClassDescriptor(fqName) if (builtinClass != null) return builtinClass - val jClass = c.finder.findClass(fqName) + val (jClass, kClass) = c.findClassInJava(fqName) if (jClass != null) return resolveClass(jClass) - + if (kClass != null) return resolveKotlinBinaryClass(kClass) return outerContext.javaClassResolver.resolveClassByFqName(fqName) } } diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaMemberScope.kt b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaMemberScope.kt index 7cba3917241..e42f6d094be 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaMemberScope.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaMemberScope.kt @@ -303,9 +303,15 @@ public abstract class LazyJavaMemberScope( result.addAll(getProperties(name)) } + addExtraDescriptors(result) + return result } + protected open fun addExtraDescriptors(result: MutableSet) { + // Do nothing + } + protected abstract fun getAllPackageNames(): Collection protected abstract fun getAllClassNames(): Collection diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaPackageFragmentScope.kt b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaPackageFragmentScope.kt index c75cd75b8db..0596469faa0 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaPackageFragmentScope.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaPackageFragmentScope.kt @@ -12,8 +12,12 @@ import org.jetbrains.jet.lang.resolve.name.FqName import org.jetbrains.jet.utils.flatten import org.jetbrains.jet.lang.resolve.java.structure.JavaClass import org.jetbrains.kotlin.util.inn -import org.jetbrains.jet.lang.resolve.java.DescriptorSearchRule import org.jetbrains.kotlin.util.sure +import org.jetbrains.jet.lang.resolve.java.lazy.findJavaClass +import org.jetbrains.jet.lang.resolve.java.lazy.findClassInJava +import org.jetbrains.jet.lang.resolve.java.PackageClassUtils +import org.jetbrains.jet.lang.resolve.scopes.JetScope +import org.jetbrains.jet.storage.NotNullLazyValue public abstract class LazyJavaPackageFragmentScope( c: LazyJavaResolverContext, @@ -24,22 +28,24 @@ public abstract class LazyJavaPackageFragmentScope( private val classes = c.storageManager.createMemoizedFunctionWithNullableValues { name -> val fqName = fqName.child(name) - val javaClass = c.finder.findClass(fqName) - if (javaClass == null) - c.javaClassResolver.resolveClassByFqName(fqName) + val (jClass, kClass) = c.findClassInJava(fqName) + if (kClass != null) + c.packageFragmentProvider.resolveKotlinBinaryClass(kClass) + else if (jClass == null) + null else { // TODO: this caching is a temporary workaround, should be replaced with properly caching the whole LazyJavaSubModule - val cached = c.javaResolverCache.getClass(javaClass) + val cached = c.javaResolverCache.getClass(jClass) if (cached != null) cached else - LazyJavaClassDescriptor(c.withTypes(TypeParameterResolver.EMPTY), packageFragment, fqName, javaClass) + LazyJavaClassDescriptor(c.withTypes(TypeParameterResolver.EMPTY), packageFragment, fqName, jClass) } } protected fun computeMemberIndexForSamConstructors(delegate: MemberIndex): MemberIndex = object : MemberIndex by delegate { override fun getAllMethodNames(): Collection { - val jClass = c.finder.findClass(fqName) + val jClass = c.findJavaClass(fqName) return delegate.getAllMethodNames() + // For SAM-constructors getAllClassNames() + @@ -66,6 +72,22 @@ public class LazyPackageFragmentScopeForJavaPackage( packageFragment: LazyJavaPackageFragment ) : LazyJavaPackageFragmentScope(c, packageFragment) { + private val deserializedPackageScope = c.storageManager.createLazyValue { + val packageClassFqName = PackageClassUtils.getPackageClassFqName(fqName) + val kotlinBinaryClass = c.kotlinClassFinder.findKotlinClass(packageClassFqName) + if (kotlinBinaryClass == null) + JetScope.EMPTY + else + c.deserializedDescriptorResolver.createKotlinPackageScope(packageFragment, kotlinBinaryClass) ?: JetScope.EMPTY + } + + override fun getProperties(name: Name) = deserializedPackageScope().getProperties(name) + override fun getFunctions(name: Name) = deserializedPackageScope().getFunctions(name) + super.getFunctions(name) + + override fun addExtraDescriptors(result: MutableSet) { + result.addAll(deserializedPackageScope().getAllDescriptors()) + } + override fun computeMemberIndex(): MemberIndex = computeMemberIndexForSamConstructors(EMPTY_MEMBER_INDEX) override fun getAllClassNames(): Collection { @@ -83,7 +105,6 @@ public class LazyPackageFragmentScopeForJavaPackage( ).flatten() - override fun getProperties(name: Name): Collection = Collections.emptyList() override fun getAllPropertyNames() = Collections.emptyList() } diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/resolvers.kt b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/resolvers.kt index 13653d282c0..3c7c616cb08 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/resolvers.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/resolvers.kt @@ -20,10 +20,11 @@ import org.jetbrains.jet.lang.resolve.java.structure.JavaClass import org.jetbrains.jet.lang.descriptors.ClassDescriptor import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor import org.jetbrains.jet.lang.resolve.java.structure.JavaTypeParameter -import org.jetbrains.jet.utils.valuesToMap import org.jetbrains.jet.lang.resolve.java.lazy.descriptors.LazyJavaTypeParameterDescriptor import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor import org.jetbrains.jet.lang.resolve.name.FqName +import org.jetbrains.jet.lang.resolve.java.resolver.JavaClassResolver +import org.jetbrains.jet.lang.resolve.kotlin.KotlinJvmBinaryClass trait LazyJavaClassResolver { fun resolveClass(javaClass: JavaClass): ClassDescriptor? @@ -60,4 +61,29 @@ class LazyJavaTypeParameterResolver( override fun resolveTypeParameter(javaTypeParameter: JavaTypeParameter): TypeParameterDescriptor? { return resolve(javaTypeParameter) ?: c.typeParameterResolver.resolveTypeParameter(javaTypeParameter) } +} + +fun GlobalJavaResolverContext.findJavaClass(fqName: FqName): JavaClass? = findClassInJava(fqName).jClass + +data class JavaClassLookupResult(val jClass: JavaClass? = null, val kClass: KotlinJvmBinaryClass? = null) + +fun GlobalJavaResolverContext.findClassInJava(fqName: FqName): JavaClassLookupResult { + // TODO: this should be governed by module separation logic + // Do not look for JavaClasses for Kotlin binaries & built-ins + if (JavaClassResolver.getKotlinBuiltinClassDescriptor(fqName) != null) { + return JavaClassLookupResult() + } + + // Do not look for Kotlin binary classes + val kotlinClass = kotlinClassFinder.findKotlinClass(fqName) + if (kotlinClass != null) return JavaClassLookupResult(kClass = kotlinClass) + + val javaClass = finder.findClass(fqName) + if (javaClass == null) return JavaClassLookupResult() + + // Light classes are not proper binaries either + if (javaClass.getOriginKind() == JavaClass.OriginKind.KOTLIN_LIGHT_CLASS) return JavaClassLookupResult() + + return JavaClassLookupResult(javaClass) + } \ No newline at end of file