Fix getting ModuleResolver by element for script files

Fixes EA-105435 (some isntances)
JavaResolveExtension: refactor API
This commit is contained in:
Pavel V. Talanov
2017-09-18 19:46:29 +03:00
parent 2af0bf4c71
commit c030a047aa
7 changed files with 42 additions and 43 deletions
@@ -57,6 +57,7 @@ abstract class ResolverForProject<M : ModuleInfo> {
abstract fun tryGetResolverForModule(moduleInfo: M): ResolverForModule? abstract fun tryGetResolverForModule(moduleInfo: M): ResolverForModule?
abstract fun descriptorForModule(moduleInfo: M): ModuleDescriptor abstract fun descriptorForModule(moduleInfo: M): ModuleDescriptor
abstract fun resolverForModuleDescriptor(descriptor: ModuleDescriptor): ResolverForModule abstract fun resolverForModuleDescriptor(descriptor: ModuleDescriptor): ResolverForModule
abstract fun diagnoseUnknownModuleInfo(infos: List<ModuleInfo>): Nothing
abstract val name: String abstract val name: String
abstract val allModules: Collection<M> abstract val allModules: Collection<M>
@@ -70,8 +71,9 @@ class EmptyResolverForProject<M : ModuleInfo> : ResolverForProject<M>() {
override fun tryGetResolverForModule(moduleInfo: M): ResolverForModule? = null override fun tryGetResolverForModule(moduleInfo: M): ResolverForModule? = null
override fun resolverForModuleDescriptor(descriptor: ModuleDescriptor): ResolverForModule = throw IllegalStateException("$descriptor is not contained in this resolver") 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<M> = listOf() override val allModules: Collection<M> = listOf()
override fun diagnoseUnknownModuleInfo(infos: List<ModuleInfo>) = throw IllegalStateException("Should not be called for $infos")
} }
class ResolverForProjectImpl<M : ModuleInfo>( class ResolverForProjectImpl<M : ModuleInfo>(
@@ -164,11 +166,14 @@ class ResolverForProjectImpl<M : ModuleInfo>(
override fun descriptorForModule(moduleInfo: M): ModuleDescriptorImpl { override fun descriptorForModule(moduleInfo: M): ModuleDescriptorImpl {
if (!isCorrectModuleInfo(moduleInfo)) { if (!isCorrectModuleInfo(moduleInfo)) {
throw AssertionError("$name does not know how to resolve $moduleInfo") diagnoseUnknownModuleInfo(listOf(moduleInfo))
} }
return doGetDescriptorForModule(moduleInfo) return doGetDescriptorForModule(moduleInfo)
} }
override fun diagnoseUnknownModuleInfo(infos: List<ModuleInfo>) =
throw AssertionError("$name does not know how to resolve $infos")
private fun doGetDescriptorForModule(module: M): ModuleDescriptorImpl { private fun doGetDescriptorForModule(module: M): ModuleDescriptorImpl {
if (module in modules) { if (module in modules) {
return projectContext.storageManager.compute { return projectContext.storageManager.compute {
@@ -39,7 +39,7 @@ import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.resolve.scopes.MemberScope
@JvmOverloads @JvmOverloads
fun PsiMethod.getJavaMethodDescriptor(resolutionFacade: ResolutionFacade? = null): FunctionDescriptor? { fun PsiMethod.getJavaMethodDescriptor(resolutionFacade: ResolutionFacade = javaResolutionFacade()): FunctionDescriptor? {
val method = originalElement as? PsiMethod ?: return null val method = originalElement as? PsiMethod ?: return null
if (method.containingClass == null || !Name.isValidIdentifier(method.name)) return null if (method.containingClass == null || !Name.isValidIdentifier(method.name)) return null
val resolver = method.getJavaDescriptorResolver(resolutionFacade) val resolver = method.getJavaDescriptorResolver(resolutionFacade)
@@ -50,19 +50,19 @@ fun PsiMethod.getJavaMethodDescriptor(resolutionFacade: ResolutionFacade? = null
} }
@JvmOverloads @JvmOverloads
fun PsiClass.getJavaClassDescriptor(resolutionFacade: ResolutionFacade? = null): ClassDescriptor? { fun PsiClass.getJavaClassDescriptor(resolutionFacade: ResolutionFacade = javaResolutionFacade()): ClassDescriptor? {
val psiClass = originalElement as? PsiClass ?: return null val psiClass = originalElement as? PsiClass ?: return null
return psiClass.getJavaDescriptorResolver(resolutionFacade)?.resolveClass(JavaClassImpl(psiClass)) return psiClass.getJavaDescriptorResolver(resolutionFacade)?.resolveClass(JavaClassImpl(psiClass))
} }
@JvmOverloads @JvmOverloads
fun PsiField.getJavaFieldDescriptor(resolutionFacade: ResolutionFacade? = null): PropertyDescriptor? { fun PsiField.getJavaFieldDescriptor(resolutionFacade: ResolutionFacade = javaResolutionFacade()): PropertyDescriptor? {
val field = originalElement as? PsiField ?: return null val field = originalElement as? PsiField ?: return null
return field.getJavaDescriptorResolver(resolutionFacade)?.resolveField(JavaFieldImpl(field)) return field.getJavaDescriptorResolver(resolutionFacade)?.resolveField(JavaFieldImpl(field))
} }
@JvmOverloads @JvmOverloads
fun PsiMember.getJavaMemberDescriptor(resolutionFacade: ResolutionFacade? = null): DeclarationDescriptor? { fun PsiMember.getJavaMemberDescriptor(resolutionFacade: ResolutionFacade = javaResolutionFacade()): DeclarationDescriptor? {
return when (this) { return when (this) {
is PsiClass -> getJavaClassDescriptor(resolutionFacade) is PsiClass -> getJavaClassDescriptor(resolutionFacade)
is PsiMethod -> getJavaMethodDescriptor(resolutionFacade) is PsiMethod -> getJavaMethodDescriptor(resolutionFacade)
@@ -72,19 +72,19 @@ fun PsiMember.getJavaMemberDescriptor(resolutionFacade: ResolutionFacade? = null
} }
@JvmOverloads @JvmOverloads
fun PsiMember.getJavaOrKotlinMemberDescriptor(resolutionFacade: ResolutionFacade? = null): DeclarationDescriptor? { fun PsiMember.getJavaOrKotlinMemberDescriptor(resolutionFacade: ResolutionFacade = javaResolutionFacade()): DeclarationDescriptor? {
val callable = unwrapped val callable = unwrapped
return when (callable) { return when (callable) {
is PsiMember -> getJavaMemberDescriptor(resolutionFacade) is PsiMember -> getJavaMemberDescriptor(resolutionFacade)
is KtDeclaration -> { 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 if (descriptor is ClassDescriptor && this is PsiMethod) descriptor.unsubstitutedPrimaryConstructor else descriptor
} }
else -> null else -> null
} }
} }
fun PsiParameter.getParameterDescriptor(resolutionFacade: ResolutionFacade? = null): ValueParameterDescriptor? { fun PsiParameter.getParameterDescriptor(resolutionFacade: ResolutionFacade = javaResolutionFacade()): ValueParameterDescriptor? {
val method = declarationScope as? PsiMethod ?: return null val method = declarationScope as? PsiMethod ?: return null
val methodDescriptor = method.getJavaMethodDescriptor(resolutionFacade) ?: return null val methodDescriptor = method.getJavaMethodDescriptor(resolutionFacade) ?: return null
return methodDescriptor.valueParameters[parameterIndex()] return methodDescriptor.valueParameters[parameterIndex()]
@@ -104,19 +104,8 @@ fun PsiClass.resolveToDescriptor(
} as? ClassDescriptor } as? ClassDescriptor
} }
private fun PsiElement.getJavaDescriptorResolver(resolutionFacade: ResolutionFacade?): JavaDescriptorResolver? { private fun PsiElement.getJavaDescriptorResolver(resolutionFacade: ResolutionFacade): JavaDescriptorResolver? {
if (resolutionFacade != null) { return resolutionFacade.tryGetFrontendService(this, JavaDescriptorResolver::class.java)
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 JavaDescriptorResolver.resolveMethod(method: JavaMethod): FunctionDescriptor? { private fun JavaDescriptorResolver.resolveMethod(method: JavaMethod): FunctionDescriptor? {
@@ -151,4 +140,7 @@ private fun <T : DeclarationDescriptorWithSource> Collection<T>.findByJavaElemen
false false
} }
} }
} }
fun PsiElement.javaResolutionFacade() =
KotlinCacheService.getInstance(project).getResolutionFacadeByFile(this.containingFile, JvmPlatform)
@@ -154,23 +154,12 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService {
) )
} }
@Deprecated("Use JetElement.getResolutionFacade(), please avoid introducing new usages")
fun <T : Any> getProjectService(platform: TargetPlatform, ideaModuleInfo: IdeaModuleInfo, serviceClass: Class<T>): T {
val settings = PlatformAnalysisSettings(platform, ideaModuleInfo.sdk, ideaModuleInfo.supportsAdditionalBuiltInsMembers())
return globalFacade(settings).resolverForModuleInfo(ideaModuleInfo).componentProvider.getService(serviceClass)
}
private fun IdeaModuleInfo.supportsAdditionalBuiltInsMembers(): Boolean { private fun IdeaModuleInfo.supportsAdditionalBuiltInsMembers(): Boolean {
return IDELanguageSettingsProvider return IDELanguageSettingsProvider
.getLanguageVersionSettings(this, project) .getLanguageVersionSettings(this, project)
.supportsFeature(LanguageFeature.AdditionalBuiltInsMembers) .supportsFeature(LanguageFeature.AdditionalBuiltInsMembers)
} }
fun <T : Any> tryGetProjectService(platform: TargetPlatform, ideaModuleInfo: IdeaModuleInfo, serviceClass: Class<T>): T? {
val settings = PlatformAnalysisSettings(platform, ideaModuleInfo.sdk, ideaModuleInfo.supportsAdditionalBuiltInsMembers())
return globalFacade(settings).tryGetResolverForModuleInfo(ideaModuleInfo)?.componentProvider?.tryGetService(serviceClass)
}
private fun globalFacade(settings: PlatformAnalysisSettings) = private fun globalFacade(settings: PlatformAnalysisSettings) =
getOrBuildGlobalFacade(settings).facadeForModules getOrBuildGlobalFacade(settings).facadeForModules
@@ -17,17 +17,20 @@
package org.jetbrains.kotlin.idea.caches.resolve package org.jetbrains.kotlin.idea.caches.resolve
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement
import com.intellij.psi.util.CachedValueProvider import com.intellij.psi.util.CachedValueProvider
import com.intellij.psi.util.CachedValuesManager import com.intellij.psi.util.CachedValuesManager
import com.intellij.psi.util.PsiModificationTracker import com.intellij.psi.util.PsiModificationTracker
import com.intellij.util.containers.SLRUCache import com.intellij.util.containers.SLRUCache
import org.jetbrains.kotlin.analyzer.AnalysisResult import org.jetbrains.kotlin.analyzer.AnalysisResult
import org.jetbrains.kotlin.analyzer.EmptyResolverForProject import org.jetbrains.kotlin.analyzer.EmptyResolverForProject
import org.jetbrains.kotlin.analyzer.ResolverForModule
import org.jetbrains.kotlin.context.GlobalContextImpl import org.jetbrains.kotlin.context.GlobalContextImpl
import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.CompositeBindingContext import org.jetbrains.kotlin.resolve.CompositeBindingContext
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
internal class ProjectResolutionFacade( internal class ProjectResolutionFacade(
private val debugString: String, private val debugString: String,
@@ -70,12 +73,20 @@ internal class ProjectResolutionFacade(
private val moduleResolverProvider: ModuleResolverProvider private val moduleResolverProvider: ModuleResolverProvider
get() = globalContext.storageManager.compute { cachedValue.value } get() = globalContext.storageManager.compute { cachedValue.value }
fun resolverForModuleInfo(moduleInfo: IdeaModuleInfo) = moduleResolverProvider.resolverForProject.resolverForModule(moduleInfo) private val resolverForProject get() = moduleResolverProvider.resolverForProject
fun tryGetResolverForModuleInfo(moduleInfo: IdeaModuleInfo) = moduleResolverProvider.resolverForProject.tryGetResolverForModule(moduleInfo)
fun resolverForDescriptor(moduleDescriptor: ModuleDescriptor) = moduleResolverProvider.resolverForProject.resolverForModuleDescriptor(moduleDescriptor) 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 { fun findModuleDescriptor(ideaModuleInfo: IdeaModuleInfo): ModuleDescriptor {
return moduleResolverProvider.resolverForProject.descriptorForModule(ideaModuleInfo) return resolverForProject.descriptorForModule(ideaModuleInfo)
} }
private val analysisResults = CachedValuesManager.getManager(project).createCachedValue( private val analysisResults = CachedValuesManager.getManager(project).createCachedValue(
@@ -69,7 +69,7 @@ internal class ResolutionFacadeImpl(
?: getFrontendService(moduleInfo, AbsentDescriptorHandler::class.java).diagnoseDescriptorNotFound(declaration) ?: getFrontendService(moduleInfo, AbsentDescriptorHandler::class.java).diagnoseDescriptorNotFound(declaration)
} }
else { else {
val resolveSession = projectFacade.resolverForModuleInfo(declaration.getModuleInfo()).componentProvider.get<ResolveSession>() val resolveSession = projectFacade.resolverForElement(declaration).componentProvider.get<ResolveSession>()
resolveSession.resolveToDescriptor(declaration) resolveSession.resolveToDescriptor(declaration)
} }
} }
@@ -81,11 +81,11 @@ internal class ResolutionFacadeImpl(
} }
override fun <T : Any> getFrontendService(element: PsiElement, serviceClass: Class<T>): T { override fun <T : Any> getFrontendService(element: PsiElement, serviceClass: Class<T>): T {
return getFrontendService(element.getModuleInfo(), serviceClass) return projectFacade.resolverForElement(element).componentProvider.getService(serviceClass)
} }
override fun <T : Any> tryGetFrontendService(element: PsiElement, serviceClass: Class<T>): T? { override fun <T : Any> tryGetFrontendService(element: PsiElement, serviceClass: Class<T>): T? {
return element.getModuleInfos().firstNotNullResult { projectFacade.tryGetResolverForModuleInfo(it)?.componentProvider?.tryGetService(serviceClass) } return projectFacade.resolverForElement(element).componentProvider.tryGetService(serviceClass)
} }
fun <T : Any> getFrontendService(ideaModuleInfo: IdeaModuleInfo, serviceClass: Class<T>): T { fun <T : Any> getFrontendService(ideaModuleInfo: IdeaModuleInfo, serviceClass: Class<T>): T {
@@ -36,6 +36,7 @@ import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.Visibility import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.idea.KotlinLanguage import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.idea.caches.resolve.getJavaOrKotlinMemberDescriptor 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.project.TargetPlatformDetector
import org.jetbrains.kotlin.idea.refactoring.changeSignature.KotlinMethodDescriptor.Kind import org.jetbrains.kotlin.idea.refactoring.changeSignature.KotlinMethodDescriptor.Kind
import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.KotlinCallableDefinitionUsage import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.KotlinCallableDefinitionUsage
@@ -528,7 +529,7 @@ fun KotlinChangeInfo.getAffectedCallables(): Collection<UsageInfo> = methodDescr
fun ChangeInfo.toJetChangeInfo( fun ChangeInfo.toJetChangeInfo(
originalChangeSignatureDescriptor: KotlinMethodDescriptor, originalChangeSignatureDescriptor: KotlinMethodDescriptor,
resolutionFacade: ResolutionFacade? = null resolutionFacade: ResolutionFacade = method.javaResolutionFacade()
): KotlinChangeInfo { ): KotlinChangeInfo {
val method = method as PsiMethod val method = method as PsiMethod
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.getJavaClassDescriptor import org.jetbrains.kotlin.idea.caches.resolve.getJavaClassDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade 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.idea.resolve.ResolutionFacade
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.allChildren import org.jetbrains.kotlin.psi.psiUtil.allChildren
@@ -66,7 +67,7 @@ fun KotlinMemberInfo.getChildrenToAnalyze(): List<PsiElement> {
} }
internal fun KtNamedDeclaration.resolveToDescriptorWrapperAware(resolutionFacade: ResolutionFacade? = null): DeclarationDescriptor { 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) return (resolutionFacade ?: getResolutionFacade()).resolveToDescriptor(this)
} }