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 fa4f7d8740d..34705e1bf31 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 @@ -32,6 +32,7 @@ import org.jetbrains.kotlin.builtins.DefaultBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.caches.resolve.KotlinCacheService import org.jetbrains.kotlin.container.getService +import org.jetbrains.kotlin.context.GlobalContext import org.jetbrains.kotlin.context.GlobalContextImpl import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor import org.jetbrains.kotlin.idea.project.AnalyzerFacadeProvider @@ -65,55 +66,69 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { } } - private val globalContext = GlobalContext(logProcessCanceled = true) - // TODO: soft reference? // TODO: cache by script definition? private val facadeForScriptDependencies by lazy { - ProjectResolutionFacade(project, globalContext.storageManager) { - globalResolveSessionProvider( - "dependencies of scripts", - project, - JvmPlatform, // TODO: Js scripts? - null, // TODO: provide sdk via dependencies - commonGlobalContext = globalContext, - allModules = listOf(ScriptDependenciesModuleInfo(project)), - dependencies = listOf( - LibraryModificationTracker.getInstance(project), //TODO: provide correct trackers - ProjectRootModificationTracker.getInstance(project) - ), - moduleFilter = { true } - ) - } + val globalContext = GlobalContext() + ProjectResolutionFacade( + project, globalContext, + globalResolveSessionProvider( + "dependencies of scripts", + JvmPlatform, // TODO: Js scripts? + null, // TODO: provide sdk via dependencies + allModules = listOf(ScriptDependenciesModuleInfo(project)), + dependencies = listOf( + LibraryModificationTracker.getInstance(project), //TODO: provide correct trackers + ProjectRootModificationTracker.getInstance(project) + ), + moduleFilter = { true } + ) + ) } private inner class GlobalFacade(platform: TargetPlatform, sdk: Sdk?) { - val facadeForLibraries = ProjectResolutionFacade(project, globalContext.storageManager) { - globalResolveSessionProvider( - "project libraries for platform $platform", - project, - platform, - sdk, - commonGlobalContext = globalContext, - moduleFilter = { it.isLibraryClasses() }, - dependencies = listOf( - LibraryModificationTracker.getInstance(project), - ProjectRootModificationTracker.getInstance(project) - ) - ) - } + private val sdkContext = GlobalContext() + val facadeForSdk = ProjectResolutionFacade( + project, sdkContext, + globalResolveSessionProvider( + "sdk $sdk", + platform, + sdk, + moduleFilter = { it is SdkInfo }, + dependencies = listOf( + LibraryModificationTracker.getInstance(project), + ProjectRootModificationTracker.getInstance(project) + ) + )) - val facadeForModules = ProjectResolutionFacade(project, globalContext.storageManager) { - globalResolveSessionProvider( - "project source roots and libraries for platform $platform", - project, - platform, - sdk, - commonGlobalContext = globalContext, - reuseDataFrom = facadeForLibraries, - moduleFilter = { !it.isLibraryClasses() }, - dependencies = listOf(PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT)) - } + private val librariesContext = sdkContext.contextWithNewLockAndCompositeExceptionTracker() + val facadeForLibraries = ProjectResolutionFacade( + project, librariesContext, + globalResolveSessionProvider( + "project libraries for platform $platform", + platform, + sdk, + reuseDataFrom = facadeForSdk, + moduleFilter = { it is LibraryInfo }, + dependencies = listOf( + LibraryModificationTracker.getInstance(project), + ProjectRootModificationTracker.getInstance(project) + ) + ) + ) + + + private val modulesContext = librariesContext.contextWithNewLockAndCompositeExceptionTracker() + val facadeForModules = ProjectResolutionFacade( + project, modulesContext, + globalResolveSessionProvider( + "project source roots and libraries for platform $platform", + platform, + sdk, + reuseDataFrom = facadeForLibraries, + moduleFilter = { !it.isLibraryClasses() }, + dependencies = listOf(PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT)) + ) } @Deprecated("Use JetElement.getResolutionFacade(), please avoid introducing new usages") @@ -146,13 +161,11 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { fun makeGlobalResolveSessionProvider(reuseDataFrom: ProjectResolutionFacade? = null, moduleFilter: (IdeaModuleInfo) -> Boolean = { true }, allModules: Collection? = null - ): CachedValueProvider.Result { + ): (GlobalContextImpl, Project) -> CachedValueProvider.Result { return globalResolveSessionProvider( debugName, - project, targetPlatform, sdk, - commonGlobalContext = globalContext, syntheticFiles = files, reuseDataFrom = reuseDataFrom, moduleFilter = moduleFilter, @@ -164,30 +177,38 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { return when { syntheticFileModule is ModuleSourceInfo -> { val dependentModules = syntheticFileModule.getDependentModules() - ProjectResolutionFacade(project, globalContext.storageManager) { - makeGlobalResolveSessionProvider( - reuseDataFrom = globalFacade(targetPlatform, sdk), - moduleFilter = { it in dependentModules }) - } + val modulesFacade = globalFacade(targetPlatform, sdk) + val globalContext = modulesFacade.globalContext.contextWithNewLockAndCompositeExceptionTracker() + ProjectResolutionFacade( + project, globalContext, + makeGlobalResolveSessionProvider( + reuseDataFrom = modulesFacade, + moduleFilter = { it in dependentModules }) + ) } syntheticFileModule is ScriptModuleInfo || syntheticFileModule is ScriptDependenciesModuleInfo -> { - ProjectResolutionFacade(project, globalContext.storageManager) { - makeGlobalResolveSessionProvider( - reuseDataFrom = facadeForScriptDependencies, - allModules = listOf(syntheticFileModule) + syntheticFileModule.dependencies(), - moduleFilter = { it == syntheticFileModule } - ) - } + val globalContext = facadeForScriptDependencies.globalContext.contextWithNewLockAndCompositeExceptionTracker() + ProjectResolutionFacade( + project, globalContext, + makeGlobalResolveSessionProvider( + reuseDataFrom = facadeForScriptDependencies, + moduleFilter = { it == syntheticFileModule }, + allModules = syntheticFileModule.dependencies() + ) + ) } syntheticFileModule is LibrarySourceInfo || syntheticFileModule is NotUnderContentRootModuleInfo -> { - ProjectResolutionFacade(project, globalContext.storageManager) { - makeGlobalResolveSessionProvider( - reuseDataFrom = librariesFacade(targetPlatform, sdk), - moduleFilter = { it == syntheticFileModule } - ) - } + val librariesFacade = librariesFacade(targetPlatform, sdk) + val globalContext = librariesFacade.globalContext.contextWithNewLockAndCompositeExceptionTracker() + ProjectResolutionFacade( + project, globalContext, + makeGlobalResolveSessionProvider( + reuseDataFrom = librariesFacade, + moduleFilter = { it == syntheticFileModule } + ) + ) } syntheticFileModule.isLibraryClasses() -> { @@ -195,9 +216,11 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { // 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") - ProjectResolutionFacade(project, globalContext.storageManager) { - makeGlobalResolveSessionProvider() - } + val globalContext = GlobalContext() + ProjectResolutionFacade( + project, globalContext, + makeGlobalResolveSessionProvider() + ) } else -> throw IllegalStateException("Unknown IdeaModuleInfo ${syntheticFileModule.javaClass}") @@ -278,40 +301,40 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { private fun globalResolveSessionProvider( debugName: String, - project: Project, platform: TargetPlatform, sdk: Sdk?, dependencies: Collection, moduleFilter: (IdeaModuleInfo) -> Boolean, - commonGlobalContext: GlobalContextImpl, reuseDataFrom: ProjectResolutionFacade? = null, syntheticFiles: Collection = listOf(), allModules: Collection? = null // null means create resolvers for modules from idea model -): CachedValueProvider.Result { +): (GlobalContextImpl, Project) -> CachedValueProvider.Result = { globalContext, project -> val delegateResolverProvider = reuseDataFrom?.moduleResolverProvider val delegateResolverForProject = delegateResolverProvider?.resolverForProject ?: EmptyResolverForProject() - val globalContext = commonGlobalContext.withCompositeExceptionTrackerUnderSameLock() - val builtIns: KotlinBuiltIns = when (platform) { - is JsPlatform -> JsPlatform.builtIns - is JvmPlatform -> JvmBuiltIns(globalContext.storageManager) + val reusedBuiltIns = delegateResolverProvider?.builtIns + val newBuiltIns: KotlinBuiltIns? = when { + reusedBuiltIns != null -> null + platform is JsPlatform -> JsPlatform.builtIns + platform is JvmPlatform && sdk != null -> JvmBuiltIns(globalContext.storageManager) else -> DefaultBuiltIns.Instance } + val builtIns = reusedBuiltIns ?: newBuiltIns!! val moduleResolverProvider = createModuleResolverProvider( debugName, project, globalContext, sdk, AnalyzerFacadeProvider.getAnalyzerFacade(platform), syntheticFiles, delegateResolverForProject, moduleFilter, - allModules, builtIns + allModules, + builtIns ) - if (builtIns is JvmBuiltIns) { - val moduleInfoToUse = sdk?.let { SdkInfo(project, it) } ?: moduleResolverProvider.resolverForProject.allModules.firstOrNull() - if (moduleInfoToUse != null) { - builtIns.setOwnerModuleDescriptor(moduleResolverProvider.resolverForProject.descriptorForModule(moduleInfoToUse)) - } + if (newBuiltIns is JvmBuiltIns) { + val sdkInfo = SdkInfo(project, sdk!!) + newBuiltIns.setOwnerModuleDescriptor(moduleResolverProvider.resolverForProject.descriptorForModule(sdkInfo)) } val allDependencies = dependencies + listOf(moduleResolverProvider.exceptionTracker) - return CachedValueProvider.Result.create(moduleResolverProvider, allDependencies) + CachedValueProvider.Result.create(moduleResolverProvider, allDependencies) } + diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/ModuleDependencyMapper.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/ModuleDependencyMapper.kt index 55d724e36d0..d56a354a85f 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/ModuleDependencyMapper.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/ModuleDependencyMapper.kt @@ -80,6 +80,7 @@ fun createModuleResolverProvider( return ModuleResolverProviderImpl( resolverForProject, + builtIns, globalContext ) } @@ -112,11 +113,13 @@ private fun collectAllModuleInfosFromIdeaModel(project: Project): List + val builtIns: KotlinBuiltIns } class ModuleResolverProviderImpl( override val resolverForProject: ResolverForProject, - val globalContext: GlobalContextImpl + override val builtIns: KotlinBuiltIns, + globalContext: GlobalContextImpl ) : ModuleResolverProvider { override val exceptionTracker: ExceptionTracker = globalContext.exceptionTracker } 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 a0b636ca955..f370a8e92cc 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 @@ -1,5 +1,5 @@ /* - * Copyright 2010-2015 JetBrains s.r.o. + * Copyright 2010-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,6 +25,7 @@ import com.intellij.util.containers.SLRUCache import org.jetbrains.kotlin.analyzer.AnalysisResult import org.jetbrains.kotlin.container.get import org.jetbrains.kotlin.container.getService +import org.jetbrains.kotlin.context.GlobalContextImpl import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.idea.project.ResolveElementCache @@ -36,20 +37,19 @@ import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.CompositeBindingContext import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.resolve.lazy.ResolveSession -import org.jetbrains.kotlin.storage.StorageManager internal class ProjectResolutionFacade( val project: Project, - private val storageManager: StorageManager, - computeModuleResolverProvider: () -> CachedValueProvider.Result + val globalContext: GlobalContextImpl, + computeModuleResolverProvider: (GlobalContextImpl, Project) -> CachedValueProvider.Result ) { private val cachedValue = CachedValuesManager.getManager(project).createCachedValue( - computeModuleResolverProvider, + { computeModuleResolverProvider(globalContext, project) }, /* trackValue = */ false ) val moduleResolverProvider: ModuleResolverProvider - get() = storageManager.compute { cachedValue.value } + get() = globalContext.storageManager.compute { cachedValue.value } fun resolverForModuleInfo(moduleInfo: IdeaModuleInfo) = moduleResolverProvider.resolverForProject.resolverForModule(moduleInfo) fun resolverForDescriptor(moduleDescriptor: ModuleDescriptor) = moduleResolverProvider.resolverForProject.resolverForModuleDescriptor(moduleDescriptor) diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/globalContextUtils.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/globalContextUtils.kt index 8b485da4671..b1d104ba1e2 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/globalContextUtils.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/globalContextUtils.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2015 JetBrains s.r.o. + * Copyright 2010-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,15 +17,12 @@ package org.jetbrains.kotlin.idea.caches.resolve import org.jetbrains.kotlin.context.GlobalContextImpl -import org.jetbrains.kotlin.storage.LockBasedStorageManager import org.jetbrains.kotlin.storage.ExceptionTracker -import com.intellij.openapi.progress.ProcessCanceledException -import com.intellij.openapi.diagnostic.Logger +import org.jetbrains.kotlin.storage.LockBasedStorageManager -fun GlobalContextImpl.withCompositeExceptionTrackerUnderSameLock(): GlobalContextImpl { +internal fun GlobalContextImpl.contextWithNewLockAndCompositeExceptionTracker(): GlobalContextImpl { val newExceptionTracker = CompositeExceptionTracker(this.exceptionTracker) - val newStorageManager = LockBasedStorageManager.createDelegatingWithSameLock(this.storageManager, newExceptionTracker) - return GlobalContextImpl(newStorageManager, newExceptionTracker) + return GlobalContextImpl(LockBasedStorageManager.createWithExceptionHandling(newExceptionTracker), newExceptionTracker) } private class CompositeExceptionTracker(val delegate: ExceptionTracker) : ExceptionTracker() { @@ -33,22 +30,3 @@ private class CompositeExceptionTracker(val delegate: ExceptionTracker) : Except return super.getModificationCount() + delegate.modificationCount } } - -private class ExceptionTrackerWithProcessCanceledReport() : ExceptionTracker() { - override fun handleException(throwable: Throwable): RuntimeException { - if (throwable is ProcessCanceledException) { - LOG.info("ProcessCancelException was thrown while analyzing libraries. Cache has to be rebuilt.") - } - throw super.handleException(throwable) - } - - - companion object { - val LOG = Logger.getInstance(ExceptionTrackerWithProcessCanceledReport::class.java) - } -} - -fun GlobalContext(logProcessCanceled: Boolean): GlobalContextImpl { - val tracker = if (logProcessCanceled) ExceptionTrackerWithProcessCanceledReport() else ExceptionTracker() - return GlobalContextImpl(LockBasedStorageManager.createWithExceptionHandling(tracker), tracker) -}