Improve ResolutionFacade api: it stores moduleInfo and provides moduleDescriptor

Remove some redundant parameters passed along with ResolutionFacade
This commit is contained in:
Pavel V. Talanov
2015-08-20 17:47:37 +03:00
parent a802ab5300
commit 608345df7b
27 changed files with 151 additions and 162 deletions
@@ -38,7 +38,7 @@ public fun JetExpression.computeTypeInfoInContext(
expectedType: JetType = TypeUtils.NO_EXPECTED_TYPE,
isStatement: Boolean = false
): JetTypeInfo {
return contextExpression.getResolutionFacade().frontendService<ExpressionTypingServices>(contextExpression)
return contextExpression.getResolutionFacade().frontendService<ExpressionTypingServices>()
.getTypeInfo(scope, this, expectedType, dataFlowInfo, trace, isStatement)
}
@@ -91,9 +91,9 @@ public class IDELightClassGenerationSupport extends LightClassGenerationSupport
Collections.sort(sortedFiles, scopeFileComparator);
JetFile file = sortedFiles.get(0);
ResolveSession session = KotlinCacheService.getInstance(file.getProject()).getLazyResolveSession(file);
forceResolvePackageDeclarations(files, session);
return new LightClassConstructionContext(session.getBindingContext(), session.getModuleDescriptor());
ResolveSession resolveSession = ResolvePackage.getResolutionFacade(file).getFrontendService(ResolveSession.class);
forceResolvePackageDeclarations(files, resolveSession);
return new LightClassConstructionContext(resolveSession.getBindingContext(), resolveSession.getModuleDescriptor());
}
@NotNull
@@ -101,7 +101,7 @@ public class IDELightClassGenerationSupport extends LightClassGenerationSupport
public LightClassConstructionContext getContextForClassOrObject(@NotNull JetClassOrObject classOrObject) {
ResolutionFacade resolutionFacade = ResolvePackage.getResolutionFacade(classOrObject);
ModuleDescriptor moduleDescriptor = resolutionFacade.findModuleDescriptor(classOrObject);
ModuleDescriptor moduleDescriptor = resolutionFacade.getModuleDescriptor();
BindingContext bindingContext = resolutionFacade.analyze(classOrObject, BodyResolveMode.FULL);
if (classOrObject.isLocal()) {
ClassDescriptor descriptor = bindingContext.get(BindingContext.CLASS, classOrObject);
@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.idea.caches.resolve
import com.intellij.psi.*
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.idea.resolve.frontendService
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.load.java.sources.JavaSourceElement
import org.jetbrains.kotlin.load.java.structure.*
@@ -29,7 +28,7 @@ import org.jetbrains.kotlin.resolve.scopes.JetScope
private fun PsiElement.getJavaDescriptorResolver(): JavaDescriptorResolver {
@suppress("DEPRECATED_SYMBOL_WITH_MESSAGE")
return KotlinCacheService.getInstance(getProject()).getGlobalFacade(JvmPlatform).frontendService<JavaDescriptorResolver>(this)
return KotlinCacheService.getInstance(project).getProjectService(JvmPlatform, this.getModuleInfo(), javaClass<JavaDescriptorResolver>())
}
fun PsiMethod.getJavaMethodDescriptor(): FunctionDescriptor? {
@@ -25,6 +25,7 @@ import com.intellij.psi.util.CachedValuesManager
import com.intellij.psi.util.PsiModificationTracker
import com.intellij.util.containers.SLRUCache
import org.jetbrains.kotlin.analyzer.EmptyResolverForProject
import org.jetbrains.kotlin.container.getService
import org.jetbrains.kotlin.idea.project.AnalyzerFacadeProvider
import org.jetbrains.kotlin.idea.project.TargetPlatformDetector
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
@@ -35,7 +36,6 @@ import org.jetbrains.kotlin.psi.JetElement
import org.jetbrains.kotlin.psi.JetFile
import org.jetbrains.kotlin.resolve.TargetPlatform
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
import org.jetbrains.kotlin.resolve.lazy.ResolveSession
import org.jetbrains.kotlin.utils.keysToMap
import kotlin.platform.platformStatic
@@ -53,7 +53,7 @@ public class KotlinCacheService(val project: Project) {
private val globalFacadesPerPlatform = listOf(JvmPlatform, JsPlatform).keysToMap { platform -> GlobalFacade(platform) }
private inner class GlobalFacade(platform: TargetPlatform) {
val facadeForLibraries = ResolutionFacadeImpl(project) {
val facadeForLibraries = ProjectResolutionFacade(project) {
globalResolveSessionProvider(
project,
platform,
@@ -66,7 +66,7 @@ public class KotlinCacheService(val project: Project) {
)
}
val facadeForModules = ResolutionFacadeImpl(project) {
val facadeForModules = ProjectResolutionFacade(project) {
globalResolveSessionProvider(
project,
platform,
@@ -77,13 +77,15 @@ public class KotlinCacheService(val project: Project) {
}
deprecated("Use JetElement.getResolutionFacade(), please avoid introducing new usages")
public fun getGlobalFacade(platform: TargetPlatform): ResolutionFacade = globalFacade(platform)
public fun <T> getProjectService(platform: TargetPlatform, ideaModuleInfo: IdeaModuleInfo, serviceClass: Class<T>): T {
return globalFacade(platform).resolverForModuleInfo(ideaModuleInfo).componentProvider.getService(serviceClass)
}
private fun globalFacade(platform: TargetPlatform) = globalFacadesPerPlatform[platform]!!.facadeForModules
private fun librariesFacade(platform: TargetPlatform) = globalFacadesPerPlatform[platform]!!.facadeForLibraries
private fun createFacadeForSyntheticFiles(files: Set<JetFile>): ResolutionFacadeImpl {
private fun createFacadeForSyntheticFiles(files: Set<JetFile>): ProjectResolutionFacade {
// we assume that all files come from the same module
val targetPlatform = files.map { TargetPlatformDetector.getPlatform(it) }.toSet().single()
val syntheticFileModule = files.map { it.getModuleInfo() }.toSet().single()
@@ -94,7 +96,7 @@ public class KotlinCacheService(val project: Project) {
return when {
syntheticFileModule is ModuleSourceInfo -> {
val dependentModules = syntheticFileModule.getDependentModules()
ResolutionFacadeImpl(project) {
ProjectResolutionFacade(project) {
globalResolveSessionProvider(
project,
targetPlatform,
@@ -107,7 +109,7 @@ public class KotlinCacheService(val project: Project) {
}
syntheticFileModule is LibrarySourceInfo || syntheticFileModule is NotUnderContentRootModuleInfo -> {
ResolutionFacadeImpl(project) {
ProjectResolutionFacade(project) {
globalResolveSessionProvider(
project,
targetPlatform,
@@ -124,7 +126,7 @@ public class KotlinCacheService(val project: Project) {
// currently the only known scenario is when we cannot determine that file is a library source
// (file under both classes and sources root)
LOG.warn("Creating cache with synthetic files ($files) in classes of library $syntheticFileModule")
ResolutionFacadeImpl(project) {
ProjectResolutionFacade(project) {
globalResolveSessionProvider(
project,
targetPlatform,
@@ -142,14 +144,14 @@ public class KotlinCacheService(val project: Project) {
private val syntheticFileCachesLock = Any()
private val slruCacheProvider = CachedValueProvider {
CachedValueProvider.Result(object : SLRUCache<Set<JetFile>, ResolutionFacadeImpl>(2, 3) {
override fun createValue(files: Set<JetFile>): ResolutionFacadeImpl {
CachedValueProvider.Result(object : SLRUCache<Set<JetFile>, ProjectResolutionFacade>(2, 3) {
override fun createValue(files: Set<JetFile>): ProjectResolutionFacade {
return createFacadeForSyntheticFiles(files)
}
}, LibraryModificationTracker.getInstance(project), ProjectRootModificationTracker.getInstance(project))
}
private fun getFacadeForSyntheticFiles(files: Set<JetFile>): ResolutionFacadeImpl {
private fun getFacadeForSyntheticFiles(files: Set<JetFile>): ProjectResolutionFacade {
return synchronized(syntheticFileCachesLock) {
//NOTE: computations inside createCacheForSyntheticFiles depend on project root structure
// so we additionally drop the whole slru cache on change
@@ -157,24 +159,16 @@ public class KotlinCacheService(val project: Project) {
}
}
public fun getLazyResolveSession(element: JetElement): ResolveSession {
val file = element.getContainingJetFile()
return getFacadeToAnalyzeFiles(listOf(file)).getLazyResolveSession(file)
}
private fun getFacadeToAnalyzeFiles(files: Collection<JetFile>): ResolutionFacadeImpl {
private fun getFacadeToAnalyzeFiles(files: Collection<JetFile>): ResolutionFacade {
val syntheticFiles = findSyntheticFiles(files)
return if (syntheticFiles.isNotEmpty()) {
val file = files.first()
val projectFacade = if (syntheticFiles.isNotEmpty()) {
getFacadeForSyntheticFiles(syntheticFiles)
}
else {
val firstFile = files.firstOrNull()
val targetPlatform = if (firstFile != null)
TargetPlatformDetector.getPlatform(firstFile)
else
TargetPlatformDetector.getDefaultPlatform()
globalFacade(targetPlatform)
globalFacade(TargetPlatformDetector.getPlatform(file))
}
return ResolutionFacadeImpl(projectFacade, file.getModuleInfo())
}
private fun findSyntheticFiles(files: Collection<JetFile>) = files.map {
@@ -196,7 +190,7 @@ private fun globalResolveSessionProvider(
platform: TargetPlatform,
dependencies: Collection<Any>,
moduleFilter: (IdeaModuleInfo) -> Boolean,
reuseDataFrom: ResolutionFacadeImpl? = null,
reuseDataFrom: ProjectResolutionFacade? = null,
syntheticFiles: Collection<JetFile> = listOf(),
logProcessCanceled: Boolean = false
): CachedValueProvider.Result<ModuleResolverProvider> {
@@ -37,53 +37,20 @@ import org.jetbrains.kotlin.resolve.CompositeBindingContext
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.resolve.lazy.ResolveSession
private class ResolutionFacadeImpl(
override val project: Project,
private class ProjectResolutionFacade(
val project: Project,
computeModuleResolverProvider: () -> CachedValueProvider.Result<ModuleResolverProvider>
) : ResolutionFacade {
) {
private val resolverCache = SynchronizedCachedValue(project, computeModuleResolverProvider, trackValue = false)
val moduleResolverProvider: ModuleResolverProvider
get() = resolverCache.getValue()
public fun getLazyResolveSession(element: JetElement): ResolveSession {
return resolverForModuleInfo(element.getModuleInfo()).componentProvider.get<ResolveSession>()
}
fun resolverForModuleInfo(moduleInfo: IdeaModuleInfo) = moduleResolverProvider.resolverForProject.resolverForModule(moduleInfo)
fun resolverForDescriptor(moduleDescriptor: ModuleDescriptor) = moduleResolverProvider.resolverForProject.resolverForModuleDescriptor(moduleDescriptor)
private fun resolverForModuleInfo(moduleInfo: IdeaModuleInfo) = moduleResolverProvider.resolverForProject.resolverForModule(moduleInfo)
private fun resolverForDescriptor(moduleDescriptor: ModuleDescriptor) = moduleResolverProvider.resolverForProject.resolverForModuleDescriptor(moduleDescriptor)
override fun <T> getFrontendService(element: PsiElement, serviceClass: Class<T>): T {
return resolverForModuleInfo(element.getModuleInfo()).componentProvider.getService(serviceClass)
}
override fun <T> getFrontendService(moduleDescriptor: ModuleDescriptor, serviceClass: Class<T>): T {
return resolverForDescriptor(moduleDescriptor).componentProvider.getService(serviceClass)
}
override fun <T> getIdeService(element: PsiElement, serviceClass: Class<T>): T {
return resolverForModuleInfo(element.getModuleInfo()).componentProvider.create(serviceClass)
}
override fun <T> getIdeService(moduleDescriptor: ModuleDescriptor, serviceClass: Class<T>): T {
return resolverForDescriptor(moduleDescriptor).componentProvider.create(serviceClass)
}
override fun analyze(element: JetElement, bodyResolveMode: BodyResolveMode): BindingContext {
val resolveElementCache = getFrontendService(element, javaClass<ResolveElementCache>())
return resolveElementCache.resolveToElement(element, bodyResolveMode)
}
override fun findModuleDescriptor(element: JetElement): ModuleDescriptor {
return moduleResolverProvider.resolverForProject.descriptorForModule(element.getModuleInfo())
}
override fun resolveToDescriptor(declaration: JetDeclaration): DeclarationDescriptor {
return getLazyResolveSession(declaration).resolveToDescriptor(declaration)
}
override fun analyzeFullyAndGetResult(elements: Collection<JetElement>): AnalysisResult {
return getAnalysisResultsForElements(elements)
fun findModuleDescriptor(ideaModuleInfo: IdeaModuleInfo): ModuleDescriptor {
return moduleResolverProvider.resolverForProject.descriptorForModule(ideaModuleInfo)
}
private val analysisResults = CachedValuesManager.getManager(project).createCachedValue(
@@ -114,6 +81,51 @@ private class ResolutionFacadeImpl(
AnalysisResult.error(bindingContext, withError.error)
else
//TODO: (module refactoring) several elements are passed here in debugger
AnalysisResult.success(bindingContext, getLazyResolveSession(elements.first()).getModuleDescriptor())
AnalysisResult.success(bindingContext, findModuleDescriptor(elements.first().getModuleInfo()))
}
}
private class ResolutionFacadeImpl(
private val projectFacade: ProjectResolutionFacade,
private val moduleInfo: IdeaModuleInfo
) : ResolutionFacade {
override val project: Project
get() = projectFacade.project
//TODO: ideally we would like to store moduleDescriptor once and for all
// but there are some usages that use resolutionFacade and mutate the psi leading to recomputation of underlying structures
override val moduleDescriptor: ModuleDescriptor
get() = projectFacade.findModuleDescriptor(moduleInfo)
override fun analyze(element: JetElement, bodyResolveMode: BodyResolveMode): BindingContext {
val resolveElementCache = getFrontendService(element, javaClass<ResolveElementCache>())
return resolveElementCache.resolveToElement(element, bodyResolveMode)
}
override fun analyzeFullyAndGetResult(elements: Collection<JetElement>): AnalysisResult
= projectFacade.getAnalysisResultsForElements(elements)
override fun resolveToDescriptor(declaration: JetDeclaration): DeclarationDescriptor {
val resolveSession = projectFacade.resolverForModuleInfo(declaration.getModuleInfo()).componentProvider.get<ResolveSession>()
return resolveSession.resolveToDescriptor(declaration)
}
override fun <T> getFrontendService(serviceClass: Class<T>): T = getFrontendService(moduleInfo, serviceClass)
override fun <T> getIdeService(serviceClass: Class<T>): T {
return projectFacade.resolverForModuleInfo(moduleInfo).componentProvider.create(serviceClass)
}
override fun <T> getFrontendService(element: PsiElement, serviceClass: Class<T>): T {
return getFrontendService(element.getModuleInfo(), serviceClass)
}
fun <T> getFrontendService(ideaModuleInfo: IdeaModuleInfo, serviceClass: Class<T>): T {
return projectFacade.resolverForModuleInfo(ideaModuleInfo).componentProvider.getService(serviceClass)
}
override fun <T> getFrontendService(moduleDescriptor: ModuleDescriptor, serviceClass: Class<T>): T {
return projectFacade.resolverForDescriptor(moduleDescriptor).componentProvider.getService(serviceClass)
}
}
@@ -46,7 +46,7 @@ public fun JetDeclaration.resolveToDescriptor(): DeclarationDescriptor {
public fun JetFile.resolveImportReference(fqName: FqName): Collection<DeclarationDescriptor> {
val facade = getResolutionFacade()
return facade.resolveImportReference(project, facade.findModuleDescriptor(this), fqName)
return facade.resolveImportReference(facade.moduleDescriptor, fqName)
}
//NOTE: the difference between analyze and analyzeFully is 'intentionally' unclear
@@ -61,11 +61,11 @@ public fun JetElement.analyze(bodyResolveMode: BodyResolveMode = BodyResolveMode
public fun JetElement.analyzeAndGetResult(): AnalysisResult {
val resolutionFacade = getResolutionFacade()
return AnalysisResult.success(resolutionFacade.analyze(this), resolutionFacade.findModuleDescriptor(this))
return AnalysisResult.success(resolutionFacade.analyze(this), resolutionFacade.moduleDescriptor)
}
public fun JetElement.findModuleDescriptor(): ModuleDescriptor {
return getResolutionFacade().findModuleDescriptor(this)
return getResolutionFacade().moduleDescriptor
}
public fun JetElement.analyzeFully(): BindingContext {
@@ -77,12 +77,11 @@ public fun JetElement.analyzeFullyAndGetResult(vararg extraFiles: JetFile): Anal
}
public fun ResolutionFacade.resolveImportReference(
project: Project,
moduleDescriptor: ModuleDescriptor,
fqName: FqName
): Collection<DeclarationDescriptor> {
val importDirective = JetPsiFactory(project).createImportDirective(ImportPath(fqName, false))
val qualifiedExpressionResolver = this.frontendService<QualifiedExpressionResolver>(moduleDescriptor)
val qualifiedExpressionResolver = this.getFrontendService(moduleDescriptor, javaClass<QualifiedExpressionResolver>())
return qualifiedExpressionResolver.processImportReference(
importDirective, moduleDescriptor, BindingTraceContext(), QualifiedExpressionResolver.LookupMode.EVERYTHING).getAllDescriptors()
}
@@ -98,5 +97,5 @@ public fun getResolveScope(file: JetFile): GlobalSearchScope {
}
public fun ResolutionFacade.getFileTopLevelScope(file: JetFile): JetScope {
return frontendService<FileScopeProvider>(file).getFileScope(file)
return frontendService<FileScopeProvider>().getFileScope(file)
}