Loading deseralized descriptors integrated with loading from bare Java code

This commit is contained in:
Andrey Breslav
2013-12-31 21:01:25 +04:00
parent 672594cb92
commit 2e4d166d6f
6 changed files with 82 additions and 79 deletions
@@ -29,6 +29,7 @@ import org.jetbrains.jet.di.InjectorForJavaDescriptorResolver;
import org.jetbrains.jet.di.InjectorForJavaDescriptorResolverUtil; import org.jetbrains.jet.di.InjectorForJavaDescriptorResolverUtil;
import org.jetbrains.jet.di.InjectorForTests; import org.jetbrains.jet.di.InjectorForTests;
import org.jetbrains.jet.lang.descriptors.ModuleDescriptor; 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.PackageViewDescriptor;
import org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor; import org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor;
import org.jetbrains.jet.lang.descriptors.impl.ReceiverParameterDescriptorImpl; 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"); scope, scope.getContainingDeclaration(), RedeclarationHandler.DO_NOTHING, "JetTypeCheckerTest.addImports");
InjectorForJavaDescriptorResolver injector = InjectorForJavaDescriptorResolverUtil.create(getProject(), new BindingTraceContext()); InjectorForJavaDescriptorResolver injector = InjectorForJavaDescriptorResolverUtil.create(getProject(), new BindingTraceContext());
JavaDescriptorResolver javaDescriptorResolver = injector.getJavaDescriptorResolver(); JavaDescriptorResolver javaDescriptorResolver = injector.getJavaDescriptorResolver();
ModuleDescriptor module = javaDescriptorResolver.getModule(); ModuleDescriptorImpl module = (ModuleDescriptorImpl) javaDescriptorResolver.getModule();
module.addFragmentProvider(KotlinBuiltIns.getInstance().getBuiltInsModule().getPackageFragmentProvider());
for (ImportPath defaultImport : module.getDefaultImports()) { for (ImportPath defaultImport : module.getDefaultImports()) {
writableScope.importScope(module.getPackage(defaultImport.fqnPart()).getMemberScope()); writableScope.importScope(module.getPackage(defaultImport.fqnPart()).getMemberScope());
} }
@@ -16,31 +16,24 @@
package org.jetbrains.jet.lang.resolve.java; package org.jetbrains.jet.lang.resolve.java;
import jet.Function1;
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.PlatformToKotlinClassMap;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.ModuleDescriptor; import org.jetbrains.jet.lang.descriptors.ModuleDescriptor;
import org.jetbrains.jet.lang.descriptors.PackageFragmentDescriptor; 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.GlobalJavaResolverContext;
import org.jetbrains.jet.lang.resolve.java.lazy.LazyJavaClassResolver; 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.lazy.LazyJavaPackageFragmentProvider;
import org.jetbrains.jet.lang.resolve.java.resolver.*; 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.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.DeserializedDescriptorResolver;
import org.jetbrains.jet.lang.resolve.kotlin.KotlinClassFinder; 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.FqName;
import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.types.DependencyClassByQualifiedNameResolver; import org.jetbrains.jet.lang.types.DependencyClassByQualifiedNameResolver;
import org.jetbrains.jet.storage.LockBasedStorageManager; import org.jetbrains.jet.storage.LockBasedStorageManager;
import org.jetbrains.jet.storage.MemoizedFunctionToNullable;
import javax.inject.Inject; import javax.inject.Inject;
import java.util.Collections;
import static org.jetbrains.jet.lang.resolve.java.DescriptorSearchRule.IGNORE_KOTLIN_SOURCES; 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 LockBasedStorageManager storageManager = new LockBasedStorageManager();
private final MemoizedFunctionToNullable<FqName, ClassDescriptor> kotlinClassesFromBinaries = storageManager.createMemoizedFunctionWithNullableValues(
new Function1<FqName, ClassDescriptor>() {
@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 JavaClassResolver classResolver;
private JavaPackageFragmentProvider packageFragmentProvider; private JavaPackageFragmentProvider packageFragmentProvider;
private JavaClassFinder javaClassFinder; private JavaClassFinder javaClassFinder;
@@ -150,36 +126,7 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
lazyJavaPackageFragmentProvider = new LazyJavaPackageFragmentProvider( lazyJavaPackageFragmentProvider = new LazyJavaPackageFragmentProvider(
new GlobalJavaResolverContext( new GlobalJavaResolverContext(
storageManager, storageManager,
new JavaClassFinder() { 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);
}
},
kotlinClassFinder, kotlinClassFinder,
deserializedDescriptorResolver, deserializedDescriptorResolver,
new LazyJavaClassResolver() { new LazyJavaClassResolver() {
@@ -195,17 +142,7 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
@Override @Override
public ClassDescriptor resolveClassByFqName(FqName fqName) { public ClassDescriptor resolveClassByFqName(FqName fqName) {
ClassDescriptor kotlinClassDescriptor = javaResolverCache.getClassResolvedFromSource(fqName); return javaResolverCache.getClassResolvedFromSource(fqName);
if (kotlinClassDescriptor != null) {
return kotlinClassDescriptor;
}
ClassDescriptor classFromBinaries = kotlinClassesFromBinaries.invoke(fqName);
if (classFromBinaries != null) {
return classFromBinaries;
}
return null;
} }
}, },
externalAnnotationResolver, externalAnnotationResolver,
@@ -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.resolver.JavaPackageFragmentProvider
import org.jetbrains.jet.lang.resolve.java.lazy.descriptors.LazyJavaPackageFragment import org.jetbrains.jet.lang.resolve.java.lazy.descriptors.LazyJavaPackageFragment
import org.jetbrains.jet.lang.resolve.name.Name 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( public open class LazyJavaPackageFragmentProvider(
private val outerContext: GlobalJavaResolverContext, private val outerContext: GlobalJavaResolverContext,
@@ -43,7 +45,7 @@ public open class LazyJavaPackageFragmentProvider(
LazyPackageFragmentForJavaPackage(c, _module, jPackage) LazyPackageFragmentForJavaPackage(c, _module, jPackage)
} }
else { else {
val jClass = c.finder.findClass(fqName) val jClass = c.findJavaClass(fqName)
if (jClass != null && DescriptorResolverUtils.isJavaClassVisibleAsPackage(jClass)) { if (jClass != null && DescriptorResolverUtils.isJavaClassVisibleAsPackage(jClass)) {
LazyPackageFragmentForJavaClass(c, _module, jClass) LazyPackageFragmentForJavaClass(c, _module, jClass)
} }
@@ -61,14 +63,22 @@ public open class LazyJavaPackageFragmentProvider(
fun getClass(fqName: FqName): ClassDescriptor? = c.javaClassResolver.resolveClassByFqName(fqName) 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 { private inner class FragmentClassResolver : LazyJavaClassResolver {
override fun resolveClass(javaClass: JavaClass): ClassDescriptor? { override fun resolveClass(javaClass: JavaClass): ClassDescriptor? {
// TODO: there's no notion of module separation here. We must refuse to resolve classes from other modules // TODO: there's no notion of module separation here. We must refuse to resolve classes from other modules
val fqName = javaClass.getFqName() val fqName = javaClass.getFqName()
if (fqName != null) { 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) val builtinClass = JavaClassResolver.getKotlinBuiltinClassDescriptor(fqName)
if (builtinClass != null) return builtinClass if (builtinClass != null) return builtinClass
if (javaClass.getOriginKind() == JavaClass.OriginKind.KOTLIN_LIGHT_CLASS) {
return c.javaResolverCache.getClassResolvedFromSource(fqName)
}
} }
val outer = javaClass.getOuterClass() val outer = javaClass.getOuterClass()
@@ -83,15 +93,16 @@ public open class LazyJavaPackageFragmentProvider(
outerPackage.getMemberScope() outerPackage.getMemberScope()
} }
return scope.getClassifier(javaClass.getName()) as? ClassDescriptor return scope.getClassifier(javaClass.getName()) as? ClassDescriptor
?: outerContext.javaClassResolver.resolveClass(javaClass)
} }
override fun resolveClassByFqName(fqName: FqName): ClassDescriptor? { override fun resolveClassByFqName(fqName: FqName): ClassDescriptor? {
val builtinClass = JavaClassResolver.getKotlinBuiltinClassDescriptor(fqName) val builtinClass = JavaClassResolver.getKotlinBuiltinClassDescriptor(fqName)
if (builtinClass != null) return builtinClass if (builtinClass != null) return builtinClass
val jClass = c.finder.findClass(fqName) val (jClass, kClass) = c.findClassInJava(fqName)
if (jClass != null) return resolveClass(jClass) if (jClass != null) return resolveClass(jClass)
if (kClass != null) return resolveKotlinBinaryClass(kClass)
return outerContext.javaClassResolver.resolveClassByFqName(fqName) return outerContext.javaClassResolver.resolveClassByFqName(fqName)
} }
} }
@@ -303,9 +303,15 @@ public abstract class LazyJavaMemberScope(
result.addAll(getProperties(name)) result.addAll(getProperties(name))
} }
addExtraDescriptors(result)
return result return result
} }
protected open fun addExtraDescriptors(result: MutableSet<DeclarationDescriptor>) {
// Do nothing
}
protected abstract fun getAllPackageNames(): Collection<Name> protected abstract fun getAllPackageNames(): Collection<Name>
protected abstract fun getAllClassNames(): Collection<Name> protected abstract fun getAllClassNames(): Collection<Name>
@@ -12,8 +12,12 @@ import org.jetbrains.jet.lang.resolve.name.FqName
import org.jetbrains.jet.utils.flatten import org.jetbrains.jet.utils.flatten
import org.jetbrains.jet.lang.resolve.java.structure.JavaClass import org.jetbrains.jet.lang.resolve.java.structure.JavaClass
import org.jetbrains.kotlin.util.inn import org.jetbrains.kotlin.util.inn
import org.jetbrains.jet.lang.resolve.java.DescriptorSearchRule
import org.jetbrains.kotlin.util.sure 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( public abstract class LazyJavaPackageFragmentScope(
c: LazyJavaResolverContext, c: LazyJavaResolverContext,
@@ -24,22 +28,24 @@ public abstract class LazyJavaPackageFragmentScope(
private val classes = c.storageManager.createMemoizedFunctionWithNullableValues<Name, ClassDescriptor> { private val classes = c.storageManager.createMemoizedFunctionWithNullableValues<Name, ClassDescriptor> {
name -> name ->
val fqName = fqName.child(name) val fqName = fqName.child(name)
val javaClass = c.finder.findClass(fqName) val (jClass, kClass) = c.findClassInJava(fqName)
if (javaClass == null) if (kClass != null)
c.javaClassResolver.resolveClassByFqName(fqName) c.packageFragmentProvider.resolveKotlinBinaryClass(kClass)
else if (jClass == null)
null
else { else {
// TODO: this caching is a temporary workaround, should be replaced with properly caching the whole LazyJavaSubModule // 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) if (cached != null)
cached cached
else 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 { protected fun computeMemberIndexForSamConstructors(delegate: MemberIndex): MemberIndex = object : MemberIndex by delegate {
override fun getAllMethodNames(): Collection<Name> { override fun getAllMethodNames(): Collection<Name> {
val jClass = c.finder.findClass(fqName) val jClass = c.findJavaClass(fqName)
return delegate.getAllMethodNames() + return delegate.getAllMethodNames() +
// For SAM-constructors // For SAM-constructors
getAllClassNames() + getAllClassNames() +
@@ -66,6 +72,22 @@ public class LazyPackageFragmentScopeForJavaPackage(
packageFragment: LazyJavaPackageFragment packageFragment: LazyJavaPackageFragment
) : LazyJavaPackageFragmentScope(c, packageFragment) { ) : 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<DeclarationDescriptor>) {
result.addAll(deserializedPackageScope().getAllDescriptors())
}
override fun computeMemberIndex(): MemberIndex = computeMemberIndexForSamConstructors(EMPTY_MEMBER_INDEX) override fun computeMemberIndex(): MemberIndex = computeMemberIndexForSamConstructors(EMPTY_MEMBER_INDEX)
override fun getAllClassNames(): Collection<Name> { override fun getAllClassNames(): Collection<Name> {
@@ -83,7 +105,6 @@ public class LazyPackageFragmentScopeForJavaPackage(
).flatten() ).flatten()
override fun getProperties(name: Name): Collection<VariableDescriptor> = Collections.emptyList()
override fun getAllPropertyNames() = Collections.emptyList<Name>() override fun getAllPropertyNames() = Collections.emptyList<Name>()
} }
@@ -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.ClassDescriptor
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor
import org.jetbrains.jet.lang.resolve.java.structure.JavaTypeParameter 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.resolve.java.lazy.descriptors.LazyJavaTypeParameterDescriptor
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor
import org.jetbrains.jet.lang.resolve.name.FqName 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 { trait LazyJavaClassResolver {
fun resolveClass(javaClass: JavaClass): ClassDescriptor? fun resolveClass(javaClass: JavaClass): ClassDescriptor?
@@ -60,4 +61,29 @@ class LazyJavaTypeParameterResolver(
override fun resolveTypeParameter(javaTypeParameter: JavaTypeParameter): TypeParameterDescriptor? { override fun resolveTypeParameter(javaTypeParameter: JavaTypeParameter): TypeParameterDescriptor? {
return resolve(javaTypeParameter) ?: c.typeParameterResolver.resolveTypeParameter(javaTypeParameter) 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)
} }