Don't cache nulls for invalid names in Java resolve

This commit is contained in:
Alexander Udalov
2015-07-30 16:38:30 +03:00
parent d3d0cbde97
commit a336e9c930
3 changed files with 34 additions and 40 deletions
@@ -20,7 +20,6 @@ import org.jetbrains.kotlin.builtins.ReflectionTypes
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.PackageFragmentProvider import org.jetbrains.kotlin.descriptors.PackageFragmentProvider
import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaClassDescriptor
import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaPackageFragment import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaPackageFragment
import org.jetbrains.kotlin.load.java.structure.JavaClass import org.jetbrains.kotlin.load.java.structure.JavaClass
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
@@ -47,17 +46,6 @@ public class LazyJavaPackageFragmentProvider(
else null else null
} }
private val topLevelClasses = c.storageManager.createMemoizedFunctionWithNullableValues lambda@ {
jClass: JavaClass ->
val fqName = jClass.getFqName()
if (fqName == null) return@lambda null
val packageFragment = getPackageFragment(fqName.parent())
if (packageFragment == null) return@lambda null
LazyJavaClassDescriptor(c, packageFragment, fqName, jClass)
}
private fun getPackageFragment(fqName: FqName) = packageFragments(fqName) private fun getPackageFragment(fqName: FqName) = packageFragments(fqName)
override fun getPackageFragments(fqName: FqName) = emptyOrSingletonList(getPackageFragment(fqName)) override fun getPackageFragments(fqName: FqName) = emptyOrSingletonList(getPackageFragment(fqName))
@@ -69,22 +57,22 @@ public class LazyJavaPackageFragmentProvider(
private inner class FragmentClassResolver : LazyJavaClassResolver { private inner class FragmentClassResolver : LazyJavaClassResolver {
override fun resolveClass(javaClass: JavaClass): ClassDescriptor? { override fun resolveClass(javaClass: JavaClass): ClassDescriptor? {
val fqName = javaClass.getFqName() val fqName = javaClass.fqName
if (fqName != null) { if (fqName != null && javaClass.originKind == JavaClass.OriginKind.KOTLIN_LIGHT_CLASS) {
if (javaClass.getOriginKind() == JavaClass.OriginKind.KOTLIN_LIGHT_CLASS) { return c.javaResolverCache.getClassResolvedFromSource(fqName)
return c.javaResolverCache.getClassResolvedFromSource(fqName)
}
} }
val outerClass = javaClass.getOuterClass()
if (outerClass == null) { javaClass.outerClass?.let { outerClass ->
val kotlinResult = c.resolveKotlinBinaryClass(c.kotlinClassFinder.findKotlinClass(javaClass)) val outerClassScope = resolveClass(outerClass)?.unsubstitutedInnerClassesScope
return when (kotlinResult) { return outerClassScope?.getClassifier(javaClass.name) as? ClassDescriptor
is KotlinClassLookupResult.Found -> kotlinResult.descriptor
else -> topLevelClasses(javaClass)
}
} }
val outerClassScope = resolveClass(outerClass)?.getUnsubstitutedInnerClassesScope()
return outerClassScope?.getClassifier(javaClass.getName()) as? ClassDescriptor val kotlinResult = c.resolveKotlinBinaryClass(c.kotlinClassFinder.findKotlinClass(javaClass))
if (kotlinResult is KotlinClassLookupResult.Found) return kotlinResult.descriptor
if (fqName == null) return null
return getPackageFragment(fqName.parent())?.resolveTopLevelClass(javaClass)
} }
} }
} }
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.load.java.lazy.descriptors
import org.jetbrains.kotlin.descriptors.impl.PackageFragmentDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.PackageFragmentDescriptorImpl
import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext
import org.jetbrains.kotlin.load.java.structure.JavaClass
import org.jetbrains.kotlin.load.java.structure.JavaPackage import org.jetbrains.kotlin.load.java.structure.JavaPackage
class LazyJavaPackageFragment( class LazyJavaPackageFragment(
@@ -26,6 +27,13 @@ class LazyJavaPackageFragment(
) : PackageFragmentDescriptorImpl(c.module, jPackage.getFqName()) { ) : PackageFragmentDescriptorImpl(c.module, jPackage.getFqName()) {
private val scope by lazy { LazyPackageFragmentScopeForJavaPackage(c, jPackage, this) } private val scope by lazy { LazyPackageFragmentScopeForJavaPackage(c, jPackage, this) }
private val topLevelClasses = c.storageManager.createMemoizedFunctionWithNullableValues {
javaClass: JavaClass ->
LazyJavaClassDescriptor(c, this, javaClass.fqName!!, javaClass)
}
internal fun resolveTopLevelClass(javaClass: JavaClass) = topLevelClasses(javaClass)
override fun getMemberScope() = scope override fun getMemberScope() = scope
override fun toString() = "lazy java package fragment: $fqName" override fun toString() = "lazy java package fragment: $fqName"
@@ -57,29 +57,27 @@ public class LazyPackageFragmentScopeForJavaPackage(
private val packageFragment: LazyJavaPackageFragment get() = getContainingDeclaration() as LazyJavaPackageFragment private val packageFragment: LazyJavaPackageFragment get() = getContainingDeclaration() as LazyJavaPackageFragment
private val classes = c.storageManager.createMemoizedFunctionWithNullableValues<Name, ClassDescriptor> { name -> findClass(name) } private val classes = c.storageManager.createMemoizedFunctionWithNullableValues<Name, ClassDescriptor> { name ->
private fun findClass(name: Name): ClassDescriptor? {
if (!SpecialNames.isSafeIdentifier(name)) return null
val classId = ClassId(packageFragment.fqName, name) val classId = ClassId(packageFragment.fqName, name)
val kotlinResult = c.resolveKotlinBinaryClass(c.kotlinClassFinder.findKotlinClass(classId)) val kotlinResult = c.resolveKotlinBinaryClass(c.kotlinClassFinder.findKotlinClass(classId))
return when (kotlinResult) { when (kotlinResult) {
is KotlinClassLookupResult.Found -> kotlinResult.descriptor is KotlinClassLookupResult.Found -> kotlinResult.descriptor
is KotlinClassLookupResult.SyntheticClass -> null is KotlinClassLookupResult.SyntheticClass -> null
is KotlinClassLookupResult.NotFound -> { is KotlinClassLookupResult.NotFound -> {
val javaClass = c.finder.findClass(classId) ?: return null c.finder.findClass(classId)?.let { javaClass ->
val classDescriptor = c.javaClassResolver.resolveClass(javaClass) c.javaClassResolver.resolveClass(javaClass).apply {
assert(classDescriptor == null || classDescriptor.containingDeclaration == packageFragment) { assert(this == null || this.containingDeclaration == packageFragment) {
"Wrong package fragment for $classDescriptor, expected $packageFragment" "Wrong package fragment for $this, expected $packageFragment"
}
}
} }
return classDescriptor
} }
} }
} }
override fun getClassifier(name: Name, location: UsageLocation): ClassifierDescriptor? = classes(name) override fun getClassifier(name: Name, location: UsageLocation): ClassifierDescriptor? =
if (SpecialNames.isSafeIdentifier(name)) classes(name) else null
override fun getProperties(name: Name, location: UsageLocation) = deserializedPackageScope().getProperties(name, location) override fun getProperties(name: Name, location: UsageLocation) = deserializedPackageScope().getProperties(name, location)
override fun getFunctions(name: Name, location: UsageLocation) = deserializedPackageScope().getFunctions(name, location) + super.getFunctions(name, location) override fun getFunctions(name: Name, location: UsageLocation) = deserializedPackageScope().getFunctions(name, location) + super.getFunctions(name, location)
@@ -100,8 +98,8 @@ public class LazyPackageFragmentScopeForJavaPackage(
if (!kindFilter.acceptsKinds(DescriptorKindFilter.NON_SINGLETON_CLASSIFIERS_MASK)) return listOf() if (!kindFilter.acceptsKinds(DescriptorKindFilter.NON_SINGLETON_CLASSIFIERS_MASK)) return listOf()
return jPackage.getClasses(nameFilter).asSequence() return jPackage.getClasses(nameFilter).asSequence()
.filter { c -> c.getOriginKind() != JavaClass.OriginKind.KOTLIN_LIGHT_CLASS } .filter { c -> c.originKind != JavaClass.OriginKind.KOTLIN_LIGHT_CLASS }
.map { c -> c.getName() }.toList() .map { c -> c.name }.toList()
} }
override fun getFunctionNames(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean): Collection<Name> { override fun getFunctionNames(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean): Collection<Name> {