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.ModuleDescriptor
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.structure.JavaClass
import org.jetbrains.kotlin.name.FqName
@@ -47,17 +46,6 @@ public class LazyJavaPackageFragmentProvider(
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)
override fun getPackageFragments(fqName: FqName) = emptyOrSingletonList(getPackageFragment(fqName))
@@ -69,22 +57,22 @@ public class LazyJavaPackageFragmentProvider(
private inner class FragmentClassResolver : LazyJavaClassResolver {
override fun resolveClass(javaClass: JavaClass): ClassDescriptor? {
val fqName = javaClass.getFqName()
if (fqName != null) {
if (javaClass.getOriginKind() == JavaClass.OriginKind.KOTLIN_LIGHT_CLASS) {
return c.javaResolverCache.getClassResolvedFromSource(fqName)
}
val fqName = javaClass.fqName
if (fqName != null && javaClass.originKind == JavaClass.OriginKind.KOTLIN_LIGHT_CLASS) {
return c.javaResolverCache.getClassResolvedFromSource(fqName)
}
val outerClass = javaClass.getOuterClass()
if (outerClass == null) {
val kotlinResult = c.resolveKotlinBinaryClass(c.kotlinClassFinder.findKotlinClass(javaClass))
return when (kotlinResult) {
is KotlinClassLookupResult.Found -> kotlinResult.descriptor
else -> topLevelClasses(javaClass)
}
javaClass.outerClass?.let { outerClass ->
val outerClassScope = resolveClass(outerClass)?.unsubstitutedInnerClassesScope
return outerClassScope?.getClassifier(javaClass.name) as? ClassDescriptor
}
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.load.java.lazy.LazyJavaResolverContext
import org.jetbrains.kotlin.load.java.structure.JavaClass
import org.jetbrains.kotlin.load.java.structure.JavaPackage
class LazyJavaPackageFragment(
@@ -26,6 +27,13 @@ class LazyJavaPackageFragment(
) : PackageFragmentDescriptorImpl(c.module, jPackage.getFqName()) {
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 toString() = "lazy java package fragment: $fqName"
@@ -57,29 +57,27 @@ public class LazyPackageFragmentScopeForJavaPackage(
private val packageFragment: LazyJavaPackageFragment get() = getContainingDeclaration() as LazyJavaPackageFragment
private val classes = c.storageManager.createMemoizedFunctionWithNullableValues<Name, ClassDescriptor> { name -> findClass(name) }
private fun findClass(name: Name): ClassDescriptor? {
if (!SpecialNames.isSafeIdentifier(name)) return null
private val classes = c.storageManager.createMemoizedFunctionWithNullableValues<Name, ClassDescriptor> { name ->
val classId = ClassId(packageFragment.fqName, name)
val kotlinResult = c.resolveKotlinBinaryClass(c.kotlinClassFinder.findKotlinClass(classId))
return when (kotlinResult) {
when (kotlinResult) {
is KotlinClassLookupResult.Found -> kotlinResult.descriptor
is KotlinClassLookupResult.SyntheticClass -> null
is KotlinClassLookupResult.NotFound -> {
val javaClass = c.finder.findClass(classId) ?: return null
val classDescriptor = c.javaClassResolver.resolveClass(javaClass)
assert(classDescriptor == null || classDescriptor.containingDeclaration == packageFragment) {
"Wrong package fragment for $classDescriptor, expected $packageFragment"
c.finder.findClass(classId)?.let { javaClass ->
c.javaClassResolver.resolveClass(javaClass).apply {
assert(this == null || this.containingDeclaration == 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 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()
return jPackage.getClasses(nameFilter).asSequence()
.filter { c -> c.getOriginKind() != JavaClass.OriginKind.KOTLIN_LIGHT_CLASS }
.map { c -> c.getName() }.toList()
.filter { c -> c.originKind != JavaClass.OriginKind.KOTLIN_LIGHT_CLASS }
.map { c -> c.name }.toList()
}
override fun getFunctionNames(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean): Collection<Name> {