From c030a047aafa3b38f31de515c3e7415fd48a2bb9 Mon Sep 17 00:00:00 2001 From: "Pavel V. Talanov" Date: Mon, 18 Sep 2017 19:46:29 +0300 Subject: [PATCH] Fix getting ModuleResolver by element for script files Fixes EA-105435 (some isntances) JavaResolveExtension: refactor API --- .../kotlin/analyzer/AnalyzerFacade.kt | 9 +++-- .../caches/resolve/JavaResolveExtension.kt | 34 +++++++------------ .../caches/resolve/KotlinCacheServiceImpl.kt | 11 ------ .../caches/resolve/ProjectResolutionFacade.kt | 19 ++++++++--- .../caches/resolve/ResolutionFacadeImpl.kt | 6 ++-- .../changeSignature/KotlinChangeInfo.kt | 3 +- .../refactoring/memberInfo/memberInfoUtils.kt | 3 +- 7 files changed, 42 insertions(+), 43 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AnalyzerFacade.kt b/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AnalyzerFacade.kt index 59de04c2c84..7ff185ea308 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AnalyzerFacade.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AnalyzerFacade.kt @@ -57,6 +57,7 @@ abstract class ResolverForProject { abstract fun tryGetResolverForModule(moduleInfo: M): ResolverForModule? abstract fun descriptorForModule(moduleInfo: M): ModuleDescriptor abstract fun resolverForModuleDescriptor(descriptor: ModuleDescriptor): ResolverForModule + abstract fun diagnoseUnknownModuleInfo(infos: List): Nothing abstract val name: String abstract val allModules: Collection @@ -70,8 +71,9 @@ class EmptyResolverForProject : ResolverForProject() { override fun tryGetResolverForModule(moduleInfo: M): ResolverForModule? = null override fun resolverForModuleDescriptor(descriptor: ModuleDescriptor): ResolverForModule = throw IllegalStateException("$descriptor is not contained in this resolver") - override fun descriptorForModule(moduleInfo: M) = throw IllegalStateException("Should not be called for $moduleInfo") + override fun descriptorForModule(moduleInfo: M) = diagnoseUnknownModuleInfo(listOf(moduleInfo)) override val allModules: Collection = listOf() + override fun diagnoseUnknownModuleInfo(infos: List) = throw IllegalStateException("Should not be called for $infos") } class ResolverForProjectImpl( @@ -164,11 +166,14 @@ class ResolverForProjectImpl( override fun descriptorForModule(moduleInfo: M): ModuleDescriptorImpl { if (!isCorrectModuleInfo(moduleInfo)) { - throw AssertionError("$name does not know how to resolve $moduleInfo") + diagnoseUnknownModuleInfo(listOf(moduleInfo)) } return doGetDescriptorForModule(moduleInfo) } + override fun diagnoseUnknownModuleInfo(infos: List) = + throw AssertionError("$name does not know how to resolve $infos") + private fun doGetDescriptorForModule(module: M): ModuleDescriptorImpl { if (module in modules) { return projectContext.storageManager.compute { diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/JavaResolveExtension.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/JavaResolveExtension.kt index a07ecb6e988..11af8e17530 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/JavaResolveExtension.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/JavaResolveExtension.kt @@ -39,7 +39,7 @@ import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform import org.jetbrains.kotlin.resolve.scopes.MemberScope @JvmOverloads -fun PsiMethod.getJavaMethodDescriptor(resolutionFacade: ResolutionFacade? = null): FunctionDescriptor? { +fun PsiMethod.getJavaMethodDescriptor(resolutionFacade: ResolutionFacade = javaResolutionFacade()): FunctionDescriptor? { val method = originalElement as? PsiMethod ?: return null if (method.containingClass == null || !Name.isValidIdentifier(method.name)) return null val resolver = method.getJavaDescriptorResolver(resolutionFacade) @@ -50,19 +50,19 @@ fun PsiMethod.getJavaMethodDescriptor(resolutionFacade: ResolutionFacade? = null } @JvmOverloads -fun PsiClass.getJavaClassDescriptor(resolutionFacade: ResolutionFacade? = null): ClassDescriptor? { +fun PsiClass.getJavaClassDescriptor(resolutionFacade: ResolutionFacade = javaResolutionFacade()): ClassDescriptor? { val psiClass = originalElement as? PsiClass ?: return null return psiClass.getJavaDescriptorResolver(resolutionFacade)?.resolveClass(JavaClassImpl(psiClass)) } @JvmOverloads -fun PsiField.getJavaFieldDescriptor(resolutionFacade: ResolutionFacade? = null): PropertyDescriptor? { +fun PsiField.getJavaFieldDescriptor(resolutionFacade: ResolutionFacade = javaResolutionFacade()): PropertyDescriptor? { val field = originalElement as? PsiField ?: return null return field.getJavaDescriptorResolver(resolutionFacade)?.resolveField(JavaFieldImpl(field)) } @JvmOverloads -fun PsiMember.getJavaMemberDescriptor(resolutionFacade: ResolutionFacade? = null): DeclarationDescriptor? { +fun PsiMember.getJavaMemberDescriptor(resolutionFacade: ResolutionFacade = javaResolutionFacade()): DeclarationDescriptor? { return when (this) { is PsiClass -> getJavaClassDescriptor(resolutionFacade) is PsiMethod -> getJavaMethodDescriptor(resolutionFacade) @@ -72,19 +72,19 @@ fun PsiMember.getJavaMemberDescriptor(resolutionFacade: ResolutionFacade? = null } @JvmOverloads -fun PsiMember.getJavaOrKotlinMemberDescriptor(resolutionFacade: ResolutionFacade? = null): DeclarationDescriptor? { +fun PsiMember.getJavaOrKotlinMemberDescriptor(resolutionFacade: ResolutionFacade = javaResolutionFacade()): DeclarationDescriptor? { val callable = unwrapped return when (callable) { is PsiMember -> getJavaMemberDescriptor(resolutionFacade) is KtDeclaration -> { - val descriptor = resolutionFacade?.resolveToDescriptor(callable) ?: callable.unsafeResolveToDescriptor() + val descriptor = resolutionFacade.resolveToDescriptor(callable) if (descriptor is ClassDescriptor && this is PsiMethod) descriptor.unsubstitutedPrimaryConstructor else descriptor } else -> null } } -fun PsiParameter.getParameterDescriptor(resolutionFacade: ResolutionFacade? = null): ValueParameterDescriptor? { +fun PsiParameter.getParameterDescriptor(resolutionFacade: ResolutionFacade = javaResolutionFacade()): ValueParameterDescriptor? { val method = declarationScope as? PsiMethod ?: return null val methodDescriptor = method.getJavaMethodDescriptor(resolutionFacade) ?: return null return methodDescriptor.valueParameters[parameterIndex()] @@ -104,19 +104,8 @@ fun PsiClass.resolveToDescriptor( } as? ClassDescriptor } -private fun PsiElement.getJavaDescriptorResolver(resolutionFacade: ResolutionFacade?): JavaDescriptorResolver? { - if (resolutionFacade != null) { - return resolutionFacade.tryGetFrontendService(this, JavaDescriptorResolver::class.java) - } - else { - //TODO_R: should this work in scripts? - if (!ProjectRootsUtil.isInProjectOrLibraryClassFile(this)) return null - - val cacheService = KotlinCacheService.getInstance(project) - val moduleInfo = this.getNullableModuleInfo() ?: return null - @Suppress("DEPRECATION") - return (cacheService as? KotlinCacheServiceImpl)?.tryGetProjectService(JvmPlatform, moduleInfo, JavaDescriptorResolver::class.java) - } +private fun PsiElement.getJavaDescriptorResolver(resolutionFacade: ResolutionFacade): JavaDescriptorResolver? { + return resolutionFacade.tryGetFrontendService(this, JavaDescriptorResolver::class.java) } private fun JavaDescriptorResolver.resolveMethod(method: JavaMethod): FunctionDescriptor? { @@ -151,4 +140,7 @@ private fun Collection.findByJavaElemen false } } -} \ No newline at end of file +} + +fun PsiElement.javaResolutionFacade() = + KotlinCacheService.getInstance(project).getResolutionFacadeByFile(this.containingFile, JvmPlatform) diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/KotlinCacheServiceImpl.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/KotlinCacheServiceImpl.kt index ce546117cc9..63ef84b1dd3 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/KotlinCacheServiceImpl.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/KotlinCacheServiceImpl.kt @@ -154,23 +154,12 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { ) } - @Deprecated("Use JetElement.getResolutionFacade(), please avoid introducing new usages") - fun getProjectService(platform: TargetPlatform, ideaModuleInfo: IdeaModuleInfo, serviceClass: Class): T { - val settings = PlatformAnalysisSettings(platform, ideaModuleInfo.sdk, ideaModuleInfo.supportsAdditionalBuiltInsMembers()) - return globalFacade(settings).resolverForModuleInfo(ideaModuleInfo).componentProvider.getService(serviceClass) - } - private fun IdeaModuleInfo.supportsAdditionalBuiltInsMembers(): Boolean { return IDELanguageSettingsProvider .getLanguageVersionSettings(this, project) .supportsFeature(LanguageFeature.AdditionalBuiltInsMembers) } - fun tryGetProjectService(platform: TargetPlatform, ideaModuleInfo: IdeaModuleInfo, serviceClass: Class): T? { - val settings = PlatformAnalysisSettings(platform, ideaModuleInfo.sdk, ideaModuleInfo.supportsAdditionalBuiltInsMembers()) - return globalFacade(settings).tryGetResolverForModuleInfo(ideaModuleInfo)?.componentProvider?.tryGetService(serviceClass) - } - private fun globalFacade(settings: PlatformAnalysisSettings) = getOrBuildGlobalFacade(settings).facadeForModules diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/ProjectResolutionFacade.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/ProjectResolutionFacade.kt index faca7b17203..35011864e2a 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/ProjectResolutionFacade.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/ProjectResolutionFacade.kt @@ -17,17 +17,20 @@ package org.jetbrains.kotlin.idea.caches.resolve import com.intellij.openapi.project.Project +import com.intellij.psi.PsiElement import com.intellij.psi.util.CachedValueProvider import com.intellij.psi.util.CachedValuesManager import com.intellij.psi.util.PsiModificationTracker import com.intellij.util.containers.SLRUCache import org.jetbrains.kotlin.analyzer.AnalysisResult import org.jetbrains.kotlin.analyzer.EmptyResolverForProject +import org.jetbrains.kotlin.analyzer.ResolverForModule import org.jetbrains.kotlin.context.GlobalContextImpl import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.resolve.CompositeBindingContext +import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult internal class ProjectResolutionFacade( private val debugString: String, @@ -70,12 +73,20 @@ internal class ProjectResolutionFacade( private val moduleResolverProvider: ModuleResolverProvider get() = globalContext.storageManager.compute { cachedValue.value } - fun resolverForModuleInfo(moduleInfo: IdeaModuleInfo) = moduleResolverProvider.resolverForProject.resolverForModule(moduleInfo) - fun tryGetResolverForModuleInfo(moduleInfo: IdeaModuleInfo) = moduleResolverProvider.resolverForProject.tryGetResolverForModule(moduleInfo) - fun resolverForDescriptor(moduleDescriptor: ModuleDescriptor) = moduleResolverProvider.resolverForProject.resolverForModuleDescriptor(moduleDescriptor) + private val resolverForProject get() = moduleResolverProvider.resolverForProject + + fun resolverForModuleInfo(moduleInfo: IdeaModuleInfo) = resolverForProject.resolverForModule(moduleInfo) + + fun resolverForElement(element: PsiElement): ResolverForModule { + val infos = element.getModuleInfos() + return infos.firstNotNullResult { resolverForProject.tryGetResolverForModule(it) } + ?: resolverForProject.diagnoseUnknownModuleInfo(infos) + } + + fun resolverForDescriptor(moduleDescriptor: ModuleDescriptor) = resolverForProject.resolverForModuleDescriptor(moduleDescriptor) fun findModuleDescriptor(ideaModuleInfo: IdeaModuleInfo): ModuleDescriptor { - return moduleResolverProvider.resolverForProject.descriptorForModule(ideaModuleInfo) + return resolverForProject.descriptorForModule(ideaModuleInfo) } private val analysisResults = CachedValuesManager.getManager(project).createCachedValue( diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/ResolutionFacadeImpl.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/ResolutionFacadeImpl.kt index 8e9e9a15df3..c376870382b 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/ResolutionFacadeImpl.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/ResolutionFacadeImpl.kt @@ -69,7 +69,7 @@ internal class ResolutionFacadeImpl( ?: getFrontendService(moduleInfo, AbsentDescriptorHandler::class.java).diagnoseDescriptorNotFound(declaration) } else { - val resolveSession = projectFacade.resolverForModuleInfo(declaration.getModuleInfo()).componentProvider.get() + val resolveSession = projectFacade.resolverForElement(declaration).componentProvider.get() resolveSession.resolveToDescriptor(declaration) } } @@ -81,11 +81,11 @@ internal class ResolutionFacadeImpl( } override fun getFrontendService(element: PsiElement, serviceClass: Class): T { - return getFrontendService(element.getModuleInfo(), serviceClass) + return projectFacade.resolverForElement(element).componentProvider.getService(serviceClass) } override fun tryGetFrontendService(element: PsiElement, serviceClass: Class): T? { - return element.getModuleInfos().firstNotNullResult { projectFacade.tryGetResolverForModuleInfo(it)?.componentProvider?.tryGetService(serviceClass) } + return projectFacade.resolverForElement(element).componentProvider.tryGetService(serviceClass) } fun getFrontendService(ideaModuleInfo: IdeaModuleInfo, serviceClass: Class): T { diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/KotlinChangeInfo.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/KotlinChangeInfo.kt index d6a66636a4b..e55151c312a 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/KotlinChangeInfo.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/KotlinChangeInfo.kt @@ -36,6 +36,7 @@ import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.Visibility import org.jetbrains.kotlin.idea.KotlinLanguage import org.jetbrains.kotlin.idea.caches.resolve.getJavaOrKotlinMemberDescriptor +import org.jetbrains.kotlin.idea.caches.resolve.javaResolutionFacade import org.jetbrains.kotlin.idea.project.TargetPlatformDetector import org.jetbrains.kotlin.idea.refactoring.changeSignature.KotlinMethodDescriptor.Kind import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.KotlinCallableDefinitionUsage @@ -528,7 +529,7 @@ fun KotlinChangeInfo.getAffectedCallables(): Collection = methodDescr fun ChangeInfo.toJetChangeInfo( originalChangeSignatureDescriptor: KotlinMethodDescriptor, - resolutionFacade: ResolutionFacade? = null + resolutionFacade: ResolutionFacade = method.javaResolutionFacade() ): KotlinChangeInfo { val method = method as PsiMethod diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/memberInfo/memberInfoUtils.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/memberInfo/memberInfoUtils.kt index bfcb275cc39..6650dde9bc2 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/memberInfo/memberInfoUtils.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/memberInfo/memberInfoUtils.kt @@ -26,6 +26,7 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.idea.caches.resolve.getJavaClassDescriptor import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade +import org.jetbrains.kotlin.idea.caches.resolve.javaResolutionFacade import org.jetbrains.kotlin.idea.resolve.ResolutionFacade import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.allChildren @@ -66,7 +67,7 @@ fun KotlinMemberInfo.getChildrenToAnalyze(): List { } internal fun KtNamedDeclaration.resolveToDescriptorWrapperAware(resolutionFacade: ResolutionFacade? = null): DeclarationDescriptor { - if (this is KtPsiClassWrapper) return psiClass.getJavaClassDescriptor(resolutionFacade)!! + if (this is KtPsiClassWrapper) return psiClass.getJavaClassDescriptor(resolutionFacade ?: javaResolutionFacade())!! return (resolutionFacade ?: getResolutionFacade()).resolveToDescriptor(this) }