Create different KotlinBuiltIns for modules with different language feature settings.

For sdkModule we create builtIns with default language feature settings.
Also when we create sdkModuleResolverProvider we create builtIns cache.
Then for every other module we get builtIns cached by value isAdditionalBuiltInsFeatureSupported.
This commit is contained in:
Stanislav Erokhin
2017-01-28 06:05:58 +03:00
committed by Dmitry Jemerov
parent 7c0cdf90cf
commit e38ca44595
6 changed files with 122 additions and 47 deletions
@@ -157,7 +157,7 @@ abstract class AnalyzerFacade<in P : PlatformAnalysisParameters> {
modulesContent: (M) -> ModuleContent, modulesContent: (M) -> ModuleContent,
platformParameters: P, platformParameters: P,
targetEnvironment: TargetEnvironment = CompilerEnvironment, targetEnvironment: TargetEnvironment = CompilerEnvironment,
builtIns: KotlinBuiltIns = DefaultBuiltIns.Instance, builtIns: (M) -> KotlinBuiltIns = { DefaultBuiltIns.Instance },
delegateResolver: ResolverForProject<M> = EmptyResolverForProject(), delegateResolver: ResolverForProject<M> = EmptyResolverForProject(),
packagePartProviderFactory: (M, ModuleContent) -> PackagePartProvider = { _, _ -> PackagePartProvider.Empty }, packagePartProviderFactory: (M, ModuleContent) -> PackagePartProvider = { _, _ -> PackagePartProvider.Empty },
firstDependency: M? = null, firstDependency: M? = null,
@@ -170,7 +170,7 @@ abstract class AnalyzerFacade<in P : PlatformAnalysisParameters> {
modules.forEach { modules.forEach {
module -> module ->
descriptorByModule[module] = descriptorByModule[module] =
ModuleDescriptorImpl(module.name, storageManager, builtIns, ModuleDescriptorImpl(module.name, storageManager, builtIns(module),
modulePlatforms(module), moduleSources(module), module.capabilities) modulePlatforms(module), moduleSources(module), module.capabilities)
} }
return ResolverForProjectImpl(debugName, descriptorByModule, delegateResolver) return ResolverForProjectImpl(debugName, descriptorByModule, delegateResolver)
@@ -74,7 +74,7 @@ class MultiModuleJavaAnalysisCustomTest : KtUsefulTestCase() {
val moduleName = javaClass.name.asString().toLowerCase().first().toString() val moduleName = javaClass.name.asString().toLowerCase().first().toString()
modules.first { it._name == moduleName } modules.first { it._name == moduleName }
}, },
builtIns = builtIns, builtIns = { builtIns },
modulePlatforms = { MultiTargetPlatform.Specific("JVM") } modulePlatforms = { MultiTargetPlatform.Specific("JVM") }
) )
@@ -44,7 +44,10 @@ class JvmBuiltIns @JvmOverloads constructor(
JvmBuiltInsSettings( JvmBuiltInsSettings(
builtInsModule, storageManager, builtInsModule, storageManager,
{ ownerModuleDescriptor.sure { "JvmBuiltins has not been initialized properly" } }, { ownerModuleDescriptor.sure { "JvmBuiltins has not been initialized properly" } },
{ isAdditionalBuiltInsFeatureSupported } {
ownerModuleDescriptor.sure { "JvmBuiltins has not been initialized properly" }
isAdditionalBuiltInsFeatureSupported
}
) )
} }
@@ -0,0 +1,86 @@
/*
* Copyright 2010-2017 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.idea.caches.resolve
import com.intellij.openapi.project.Project
import com.intellij.openapi.projectRoots.Sdk
import com.intellij.util.containers.SLRUCache
import org.jetbrains.kotlin.analyzer.LanguageSettingsProvider
import org.jetbrains.kotlin.analyzer.ModuleInfo
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
import org.jetbrains.kotlin.context.GlobalContextImpl
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.js.resolve.JsPlatform
import org.jetbrains.kotlin.platform.JvmBuiltIns
import org.jetbrains.kotlin.resolve.TargetPlatform
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
class BuiltInsCache private constructor(
private val project: Project,
platform: TargetPlatform,
sdk: Sdk?,
sdkModuleDescriptor: ModuleDescriptor?,
sdkContext: GlobalContextImpl
) {
private val cache: SLRUCache<Boolean, KotlinBuiltIns> = object : SLRUCache<Boolean, KotlinBuiltIns>(2, 2) {
override fun createValue(key: Boolean): KotlinBuiltIns {
val builtIns = calculateBuiltIns(platform, sdk, sdkContext)
if (builtIns is JvmBuiltIns) {
builtIns.initialize(sdkModuleDescriptor!!, key)
}
return builtIns
}
}
fun getBuiltIns(moduleInfo: ModuleInfo): KotlinBuiltIns {
val languageFeatureSettings = LanguageSettingsProvider.getInstance(project).getLanguageVersionSettings(moduleInfo)
return cache.get(languageFeatureSettings.supportsFeature(LanguageFeature.AdditionalBuiltInsMembers))
}
companion object {
fun calculateBuiltIns(platform: TargetPlatform, sdk: Sdk?, sdkContext: GlobalContextImpl): KotlinBuiltIns = when {
platform is JsPlatform -> JsPlatform.builtIns
platform is JvmPlatform && sdk != null -> JvmBuiltIns(sdkContext.storageManager)
else -> DefaultBuiltIns.Instance
}
fun createCacheAndInitializeBuiltIns(
project: Project,
platform: TargetPlatform,
sdk: Sdk?,
sdkModuleDescriptor: ModuleDescriptor?,
sdkBuiltIns: KotlinBuiltIns,
sdkContext: GlobalContextImpl
): BuiltInsCache {
val builtInsCache = BuiltInsCache(project, platform, sdk, sdkModuleDescriptor, sdkContext)
if (sdkBuiltIns is JvmBuiltIns) {
val isAdditionalBuiltInsFeatureSupported = LanguageVersionSettingsImpl.DEFAULT.supportsFeature(LanguageFeature.AdditionalBuiltInsMembers)
sdkBuiltIns.initialize(
sdkModuleDescriptor!!, // sdk is not null for JvmBuiltIns because of calculateBuiltIns
isAdditionalBuiltInsFeatureSupported)
builtInsCache.cache.put(isAdditionalBuiltInsFeatureSupported, sdkBuiltIns)
}
return builtInsCache
}
}
}
@@ -29,31 +29,23 @@ 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.EmptyResolverForProject import org.jetbrains.kotlin.analyzer.EmptyResolverForProject
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.caches.resolve.KotlinCacheService import org.jetbrains.kotlin.caches.resolve.KotlinCacheService
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.container.get
import org.jetbrains.kotlin.container.getService import org.jetbrains.kotlin.container.getService
import org.jetbrains.kotlin.context.GlobalContext import org.jetbrains.kotlin.context.GlobalContext
import org.jetbrains.kotlin.context.GlobalContextImpl import org.jetbrains.kotlin.context.GlobalContextImpl
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.idea.core.script.ScriptDependenciesModificationTracker import org.jetbrains.kotlin.idea.core.script.ScriptDependenciesModificationTracker
import org.jetbrains.kotlin.idea.project.AnalyzerFacadeProvider
import org.jetbrains.kotlin.idea.project.TargetPlatformDetector import org.jetbrains.kotlin.idea.project.TargetPlatformDetector
import org.jetbrains.kotlin.idea.project.outOfBlockModificationCount import org.jetbrains.kotlin.idea.project.outOfBlockModificationCount
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
import org.jetbrains.kotlin.js.resolve.JsPlatform
import org.jetbrains.kotlin.platform.JvmBuiltIns
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.TargetPlatform import org.jetbrains.kotlin.resolve.TargetPlatform
import org.jetbrains.kotlin.resolve.diagnostics.KotlinSuppressCache import org.jetbrains.kotlin.resolve.diagnostics.KotlinSuppressCache
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.script.KotlinScriptExternalDependencies
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
import org.jetbrains.kotlin.utils.addToStdlib.sumByLong import org.jetbrains.kotlin.utils.addToStdlib.sumByLong
import java.lang.AssertionError import java.lang.AssertionError
@@ -377,32 +369,12 @@ private fun globalResolveSessionProvider(
val delegateResolverProvider = reuseDataFrom?.moduleResolverProvider val delegateResolverProvider = reuseDataFrom?.moduleResolverProvider
val delegateResolverForProject = delegateResolverProvider?.resolverForProject ?: EmptyResolverForProject() val delegateResolverForProject = delegateResolverProvider?.resolverForProject ?: EmptyResolverForProject()
val reusedBuiltIns = delegateResolverProvider?.builtIns createModuleResolverProvider(
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, debugName, project, globalContext, sdk,
AnalyzerFacadeProvider.getAnalyzerFacade(platform), platform,
syntheticFiles, delegateResolverForProject, moduleFilter, syntheticFiles, delegateResolverForProject, moduleFilter,
allModules, allModules,
builtIns, delegateResolverProvider?.builtInsCache,
dependencies dependencies
) )
if (newBuiltIns is JvmBuiltIns) {
val sdkInfo = SdkInfo(project, sdk!!)
newBuiltIns.initialize(
moduleResolverProvider.resolverForProject.descriptorForModule(sdkInfo),
moduleResolverProvider.resolverForProject.resolverForModule(sdkInfo)
.componentProvider.get<LanguageVersionSettings>()
.supportsFeature(LanguageFeature.AdditionalBuiltInsMembers))
}
moduleResolverProvider
} }
@@ -23,19 +23,20 @@ import com.intellij.openapi.projectRoots.Sdk
import com.intellij.openapi.roots.JdkOrderEntry import com.intellij.openapi.roots.JdkOrderEntry
import com.intellij.openapi.roots.LibraryOrderEntry import com.intellij.openapi.roots.LibraryOrderEntry
import com.intellij.openapi.roots.ModuleRootManager import com.intellij.openapi.roots.ModuleRootManager
import org.jetbrains.kotlin.analyzer.AnalyzerFacade
import org.jetbrains.kotlin.analyzer.ModuleContent import org.jetbrains.kotlin.analyzer.ModuleContent
import org.jetbrains.kotlin.analyzer.ModuleInfo
import org.jetbrains.kotlin.analyzer.ResolverForProject import org.jetbrains.kotlin.analyzer.ResolverForProject
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.context.GlobalContextImpl import org.jetbrains.kotlin.context.GlobalContextImpl
import org.jetbrains.kotlin.context.withProject import org.jetbrains.kotlin.context.withProject
import org.jetbrains.kotlin.descriptors.SourceKind import org.jetbrains.kotlin.descriptors.SourceKind
import org.jetbrains.kotlin.idea.project.AnalyzerFacadeProvider
import org.jetbrains.kotlin.idea.project.IdeaEnvironment import org.jetbrains.kotlin.idea.project.IdeaEnvironment
import org.jetbrains.kotlin.idea.project.TargetPlatformDetector import org.jetbrains.kotlin.idea.project.TargetPlatformDetector
import org.jetbrains.kotlin.load.java.structure.JavaClass import org.jetbrains.kotlin.load.java.structure.JavaClass
import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.MultiTargetPlatform import org.jetbrains.kotlin.resolve.TargetPlatform
import org.jetbrains.kotlin.resolve.jvm.JvmPlatformParameters import org.jetbrains.kotlin.resolve.jvm.JvmPlatformParameters
fun createModuleResolverProvider( fun createModuleResolverProvider(
@@ -43,14 +44,21 @@ fun createModuleResolverProvider(
project: Project, project: Project,
globalContext: GlobalContextImpl, globalContext: GlobalContextImpl,
sdk: Sdk?, sdk: Sdk?,
analyzerFacade: AnalyzerFacade<JvmPlatformParameters>, platform: TargetPlatform,
syntheticFiles: Collection<KtFile>, syntheticFiles: Collection<KtFile>,
delegateResolver: ResolverForProject<IdeaModuleInfo>, delegateResolver: ResolverForProject<IdeaModuleInfo>,
moduleFilter: (IdeaModuleInfo) -> Boolean, moduleFilter: (IdeaModuleInfo) -> Boolean,
allModules: Collection<IdeaModuleInfo>?, allModules: Collection<IdeaModuleInfo>?,
builtIns: KotlinBuiltIns, builtInsCache: BuiltInsCache?, // this cache is null only for SDK resolver provider
dependencies: Collection<Any> dependencies: Collection<Any>
): ModuleResolverProvider { ): ModuleResolverProvider {
var sdkBuiltIns: KotlinBuiltIns? = null
val builtInsProvider: (ModuleInfo) -> KotlinBuiltIns = builtInsCache?.let { it::getBuiltIns } ?: run {
sdkBuiltIns = BuiltInsCache.calculateBuiltIns(platform, sdk, globalContext);
{ _: ModuleInfo -> sdkBuiltIns!! }
}
val allModuleInfos = (allModules ?: collectAllModuleInfosFromIdeaModel(project)).toHashSet() val allModuleInfos = (allModules ?: collectAllModuleInfosFromIdeaModel(project)).toHashSet()
@@ -71,10 +79,10 @@ fun createModuleResolverProvider(
psiClass.getNullableModuleInfo() psiClass.getNullableModuleInfo()
} }
val resolverForProject = analyzerFacade.setupResolverForProject( return AnalyzerFacadeProvider.getAnalyzerFacade(platform).setupResolverForProject(
debugName, globalContext.withProject(project), modulesToCreateResolversFor, modulesContent, debugName, globalContext.withProject(project), modulesToCreateResolversFor, modulesContent,
jvmPlatformParameters, IdeaEnvironment, builtIns, jvmPlatformParameters, IdeaEnvironment, builtInsProvider,
delegateResolver, { m, c -> IDEPackagePartProvider(c.moduleContentScope) }, delegateResolver, { _, c -> IDEPackagePartProvider(c.moduleContentScope) },
sdk?.let { SdkInfo(project, it) }, sdk?.let { SdkInfo(project, it) },
modulePlatforms = { moduleInfo -> modulePlatforms = { moduleInfo ->
val module = (moduleInfo as? ModuleSourceInfo)?.module val module = (moduleInfo as? ModuleSourceInfo)?.module
@@ -89,14 +97,19 @@ fun createModuleResolverProvider(
} }
) )
return resolverForProject
} }
val resolverForProject = createResolverForProject() val resolverForProject = createResolverForProject()
val newBuiltInsCache = builtInsCache ?: run {
val sdkModuleDescriptor = sdk?.let { resolverForProject.descriptorForModule(SdkInfo(project, it)) }
BuiltInsCache.createCacheAndInitializeBuiltIns(project, platform, sdk, sdkModuleDescriptor, sdkBuiltIns!!, globalContext)
}
return ModuleResolverProviderImpl( return ModuleResolverProviderImpl(
resolverForProject, resolverForProject,
builtIns, newBuiltInsCache,
dependencies + listOf(globalContext.exceptionTracker) dependencies + listOf(globalContext.exceptionTracker)
) )
} }
@@ -133,11 +146,12 @@ fun getAllProjectSdks(): Collection<Sdk> {
interface ModuleResolverProvider { interface ModuleResolverProvider {
val resolverForProject: ResolverForProject<IdeaModuleInfo> val resolverForProject: ResolverForProject<IdeaModuleInfo>
val builtIns: KotlinBuiltIns val builtInsCache: BuiltInsCache
val cacheDependencies: Collection<Any> val cacheDependencies: Collection<Any>
} }
class ModuleResolverProviderImpl( class ModuleResolverProviderImpl(
override val resolverForProject: ResolverForProject<IdeaModuleInfo>, override val resolverForProject: ResolverForProject<IdeaModuleInfo>,
override val builtIns: KotlinBuiltIns, override val builtInsCache: BuiltInsCache,
override val cacheDependencies: Collection<Any>) : ModuleResolverProvider override val cacheDependencies: Collection<Any>
) : ModuleResolverProvider