From 04717b57c98d443c2e3ebf09a7ec5767d0017c4d Mon Sep 17 00:00:00 2001 From: Dmitry Savvinov Date: Wed, 10 Jul 2019 15:42:12 +0300 Subject: [PATCH] [API Usage] Support refinement for Java classes' scope Also, we should skip supertypes refinement for additional built-in members scope --- .../kotlin/frontend/java/di/injection.kt | 1 + .../descriptors/LazyJavaClassDescriptor.kt | 19 ++++++-- .../descriptors/LazyJavaClassMemberScope.kt | 25 +++++++--- .../java/lazy/descriptors/LazyJavaScope.kt | 48 ++++++++++++++----- 4 files changed, 70 insertions(+), 23 deletions(-) diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/frontend/java/di/injection.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/frontend/java/di/injection.kt index 6d35c51fe54..78c4e5a79f2 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/frontend/java/di/injection.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/frontend/java/di/injection.kt @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.frontend.java.di import com.intellij.psi.search.GlobalSearchScope import org.jetbrains.kotlin.builtins.jvm.JvmBuiltIns import org.jetbrains.kotlin.builtins.jvm.JvmBuiltInsPackageFragmentProvider +import org.jetbrains.kotlin.config.AnalysisFlags import org.jetbrains.kotlin.config.JvmAnalysisFlags import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageVersionSettings diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassDescriptor.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassDescriptor.kt index ac4bbf67334..654ef1a9a07 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassDescriptor.kt +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassDescriptor.kt @@ -34,6 +34,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.resolveTopLevelClass import org.jetbrains.kotlin.resolve.scopes.InnerClassesScopeWrapper import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.types.* +import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner import org.jetbrains.kotlin.utils.addIfNotNull import org.jetbrains.kotlin.utils.addToStdlib.safeAs import java.util.* @@ -100,10 +101,21 @@ class LazyJavaClassDescriptor( private val typeConstructor = LazyJavaClassTypeConstructor() override fun getTypeConstructor(): TypeConstructor = typeConstructor - private val unsubstitutedMemberScope = LazyJavaClassMemberScope(c, this, jClass) - override fun getUnsubstitutedMemberScope() = unsubstitutedMemberScope + private val unsubstitutedMemberScope = + LazyJavaClassMemberScope(c, this, jClass, skipRefinement = additionalSupertypeClassDescriptor != null) - private val innerClassesScope = InnerClassesScopeWrapper(getUnsubstitutedMemberScope()) + private val scopeHolder = + ScopesHolderForClass.create(this, c.storageManager, c.components.kotlinTypeChecker.kotlinTypeRefiner) { kotlinTypeRefiner -> + LazyJavaClassMemberScope( + c, this, jClass, + skipRefinement = additionalSupertypeClassDescriptor != null, + mainScope = unsubstitutedMemberScope + ) + } + + override fun getUnsubstitutedMemberScope(kotlinTypeRefiner: KotlinTypeRefiner) = scopeHolder.getScope(kotlinTypeRefiner) + + private val innerClassesScope = InnerClassesScopeWrapper(unsubstitutedMemberScope) override fun getUnsubstitutedInnerClassesScope(): MemberScope = innerClassesScope private val staticScope = LazyJavaStaticClassScope(c, jClass, this) @@ -113,6 +125,7 @@ class LazyJavaClassDescriptor( override fun getCompanionObjectDescriptor(): ClassDescriptor? = null + override fun getUnsubstitutedMemberScope() = super.getUnsubstitutedMemberScope() as LazyJavaClassMemberScope override fun getConstructors() = unsubstitutedMemberScope.constructors() override val annotations = c.resolveAnnotations(jClass) diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassMemberScope.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassMemberScope.kt index e3cf0398a08..7a53b2356af 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassMemberScope.kt +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassMemberScope.kt @@ -67,8 +67,10 @@ import java.util.* class LazyJavaClassMemberScope( c: LazyJavaResolverContext, override val ownerDescriptor: ClassDescriptor, - private val jClass: JavaClass -) : LazyJavaScope(c) { + private val jClass: JavaClass, + private val skipRefinement: Boolean, + mainScope: LazyJavaClassMemberScope? = null +) : LazyJavaScope(c, mainScope) { override fun computeMemberIndex() = ClassDeclaredMemberIndex(jClass) { !it.isStatic } @@ -431,9 +433,10 @@ class LazyJavaClassMemberScope( } private fun getFunctionsFromSupertypes(name: Name): Set { - return ownerDescriptor.typeConstructor.supertypes.flatMapTo(LinkedHashSet()) { - it.memberScope.getContributedFunctions(name, NoLookupLocation.WHEN_GET_SUPER_MEMBERS) - } + return computeSupertypes() + .flatMapTo(LinkedHashSet()) { + it.memberScope.getContributedFunctions(name, NoLookupLocation.WHEN_GET_SUPER_MEMBERS) + } } override fun computeNonDeclaredProperties(name: Name, result: MutableCollection) { @@ -548,11 +551,18 @@ class LazyJavaClassMemberScope( } private fun getPropertiesFromSupertypes(name: Name): Set { - return ownerDescriptor.typeConstructor.supertypes.flatMap { + return computeSupertypes().flatMap { it.memberScope.getContributedVariables(name, NoLookupLocation.WHEN_GET_SUPER_MEMBERS).map { p -> p } }.toSet() } + private fun computeSupertypes(): Collection { + if (skipRefinement) return ownerDescriptor.typeConstructor.supertypes + + @UseExperimental(TypeRefinement::class) + return c.components.kotlinTypeChecker.kotlinTypeRefiner.refineSupertypes(ownerDescriptor) + } + override fun resolveMethodSignature( method: JavaMethod, methodTypeParameters: List, returnType: KotlinType, valueParameters: List @@ -728,7 +738,8 @@ class LazyJavaClassMemberScope( override fun getContributedClassifier(name: Name, location: LookupLocation): ClassifierDescriptor? { recordLookup(name, location) - return nestedClasses(name) + + return (mainScope as LazyJavaClassMemberScope?)?.nestedClasses?.invoke(name) ?: nestedClasses(name) } override fun getContributedFunctions(name: Name, location: LookupLocation): Collection { diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaScope.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaScope.kt index f304249366d..8b3def13ae9 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaScope.kt +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaScope.kt @@ -45,6 +45,8 @@ import org.jetbrains.kotlin.resolve.scopes.DescriptorKindExclude.NonExtensions import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.resolve.scopes.MemberScopeImpl +import org.jetbrains.kotlin.storage.MemoizedFunctionToNotNull +import org.jetbrains.kotlin.storage.MemoizedFunctionToNullable import org.jetbrains.kotlin.storage.NotNullLazyValue import org.jetbrains.kotlin.storage.getValue import org.jetbrains.kotlin.types.KotlinType @@ -54,7 +56,10 @@ import org.jetbrains.kotlin.utils.addIfNotNull import org.jetbrains.kotlin.utils.addToStdlib.safeAs import java.util.* -abstract class LazyJavaScope(protected val c: LazyJavaResolverContext) : MemberScopeImpl() { +abstract class LazyJavaScope( + protected val c: LazyJavaResolverContext, + protected val mainScope: LazyJavaScope? = null +) : MemberScopeImpl() { protected abstract val ownerDescriptor: DeclarationDescriptor // this lazy value is not used at all in LazyPackageFragmentScopeForJavaPackage because we do not use caching there @@ -79,17 +84,38 @@ abstract class LazyJavaScope(protected val c: LazyJavaResolverContext) : MemberS protected abstract fun getDispatchReceiverParameter(): ReceiverParameterDescriptor? - private val functions = c.storageManager.createMemoizedFunction> { name -> - val result = LinkedHashSet() + private val declaredFunctions: MemoizedFunctionToNotNull> = + c.storageManager.createMemoizedFunction { name -> + if (mainScope != null) return@createMemoizedFunction mainScope.declaredFunctions(name) - for (method in declaredMemberIndex().findMethodsByName(name)) { - val descriptor = resolveMethodToFunctionDescriptor(method) - if (!descriptor.isVisibleAsFunction()) continue + val result = mutableListOf() - c.components.javaResolverCache.recordMethod(method, descriptor) - result.add(descriptor) + for (method in declaredMemberIndex().findMethodsByName(name)) { + val descriptor = resolveMethodToFunctionDescriptor(method) + if (!descriptor.isVisibleAsFunction()) continue + + c.components.javaResolverCache.recordMethod(method, descriptor) + result.add(descriptor) + } + + result } + private val declaredField: MemoizedFunctionToNullable = + c.storageManager.createMemoizedFunctionWithNullableValues { name -> + if (mainScope != null) return@createMemoizedFunctionWithNullableValues mainScope.declaredField(name) + + val field = declaredMemberIndex().findFieldByName(name) + if (field != null && !field.isEnumEntry) + resolveProperty(field) + else + null + } + + + private val functions = c.storageManager.createMemoizedFunction> { name -> + val result = LinkedHashSet(declaredFunctions(name)) + result.retainMostSpecificInEachOverridableGroup() computeNonDeclaredFunctions(result, name) @@ -250,11 +276,7 @@ abstract class LazyJavaScope(protected val c: LazyJavaResolverContext) : MemberS private val properties = c.storageManager.createMemoizedFunction { name: Name -> val properties = ArrayList() - val field = declaredMemberIndex().findFieldByName(name) - if (field != null && !field.isEnumEntry) { - properties.add(resolveProperty(field)) - } - + properties.addIfNotNull(declaredField(name)) computeNonDeclaredProperties(name, properties) if (DescriptorUtils.isAnnotationClass(ownerDescriptor))