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 descriptorForModule(moduleInfo: M): ModuleDescriptor
abstract fun resolverForModuleDescriptor(descriptor: ModuleDescriptor): ResolverForModule
abstract fun diagnoseUnknownModuleInfo(infos: List<ModuleInfo>): Nothing
abstract val name: String
abstract val allModules: Collection<M>
@@ -70,8 +71,9 @@ class EmptyResolverForProject<M : ModuleInfo> : ResolverForProject<M>() {
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<M> = listOf()
override fun diagnoseUnknownModuleInfo(infos: List<ModuleInfo>) = throw IllegalStateException("Should not be called for $infos")
}
class ResolverForProjectImpl<M : ModuleInfo>(
@@ -164,11 +166,14 @@ class ResolverForProjectImpl<M : ModuleInfo>(
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<ModuleInfo>) =
throw AssertionError("$name does not know how to resolve $infos")
private fun doGetDescriptorForModule(module: M): ModuleDescriptorImpl {
if (module in modules) {
return projectContext.storageManager.compute {
@@ -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 <T : DeclarationDescriptorWithSource> Collection<T>.findByJavaElemen
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 {
return IDELanguageSettingsProvider
.getLanguageVersionSettings(this, project)
.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) =
getOrBuildGlobalFacade(settings).facadeForModules
@@ -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(
@@ -69,7 +69,7 @@ internal class ResolutionFacadeImpl(
?: getFrontendService(moduleInfo, AbsentDescriptorHandler::class.java).diagnoseDescriptorNotFound(declaration)
}
else {
val resolveSession = projectFacade.resolverForModuleInfo(declaration.getModuleInfo()).componentProvider.get<ResolveSession>()
val resolveSession = projectFacade.resolverForElement(declaration).componentProvider.get<ResolveSession>()
resolveSession.resolveToDescriptor(declaration)
}
}
@@ -81,11 +81,11 @@ internal class ResolutionFacadeImpl(
}
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? {
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 {
@@ -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<UsageInfo> = methodDescr
fun ChangeInfo.toJetChangeInfo(
originalChangeSignatureDescriptor: KotlinMethodDescriptor,
resolutionFacade: ResolutionFacade? = null
resolutionFacade: ResolutionFacade = method.javaResolutionFacade()
): KotlinChangeInfo {
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.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<PsiElement> {
}
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)
}