diff --git a/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AnalyzerFacade.kt b/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AnalyzerFacade.kt index fba5511a14f..b941cc6b72b 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AnalyzerFacade.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AnalyzerFacade.kt @@ -165,7 +165,7 @@ abstract class AnalyzerFacade { modulesContent: (M) -> ModuleContent, platformParameters: P, targetEnvironment: TargetEnvironment = CompilerEnvironment, - builtIns: (M) -> KotlinBuiltIns = { DefaultBuiltIns.Instance }, + builtIns: KotlinBuiltIns = DefaultBuiltIns.Instance, delegateResolver: ResolverForProject = EmptyResolverForProject(), packagePartProviderFactory: (M, ModuleContent) -> PackagePartProvider = { _, _ -> PackagePartProvider.Empty }, firstDependency: M? = null, @@ -175,7 +175,7 @@ abstract class AnalyzerFacade { val storageManager = projectContext.storageManager val resolverForProject = ResolverForProjectImpl(debugName, modules.keysToMap { module -> - ModuleDescriptorImpl(module.name, storageManager, builtIns(module), modulePlatforms(module), module.capabilities) + ModuleDescriptorImpl(module.name, storageManager, builtIns, modulePlatforms(module), module.capabilities) }, delegateResolver) for (module in modules) { diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/MultiModuleJavaAnalysisCustomTest.kt b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/MultiModuleJavaAnalysisCustomTest.kt index c492b99c3b4..73606e4516d 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/MultiModuleJavaAnalysisCustomTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/MultiModuleJavaAnalysisCustomTest.kt @@ -76,7 +76,7 @@ class MultiModuleJavaAnalysisCustomTest : KtUsefulTestCase() { val moduleName = javaClass.name.asString().toLowerCase().first().toString() modules.first { it._name == moduleName } }, - builtIns = { builtIns }, + builtIns = builtIns, modulePlatforms = { MultiTargetPlatform.Specific("JVM") } ) diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/BuiltInsCache.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/BuiltInsCache.kt deleted file mode 100644 index c0d2e3b63e1..00000000000 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/BuiltInsCache.kt +++ /dev/null @@ -1,86 +0,0 @@ -/* - * 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.context.GlobalContextImpl -import org.jetbrains.kotlin.descriptors.ModuleDescriptor -import org.jetbrains.kotlin.idea.project.getLanguageVersionSettings -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 = object : SLRUCache(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, project) - 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 = project.getLanguageVersionSettings().supportsFeature(LanguageFeature.AdditionalBuiltInsMembers) - sdkBuiltIns.initialize( - sdkModuleDescriptor!!, // sdk is not null for JvmBuiltIns because of calculateBuiltIns - isAdditionalBuiltInsFeatureSupported) - builtInsCache.cache.put(isAdditionalBuiltInsFeatureSupported, sdkBuiltIns) - } - return builtInsCache - } - } -} \ No newline at end of file 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 b0a89abc085..9afc18578af 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 @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.idea.caches.resolve +import com.intellij.openapi.components.service import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.project.Project import com.intellij.openapi.projectRoots.Sdk @@ -29,8 +30,10 @@ 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.analyzer.LanguageSettingsProvider import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.caches.resolve.KotlinCacheService +import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.container.getService import org.jetbrains.kotlin.container.tryGetService import org.jetbrains.kotlin.context.GlobalContext @@ -54,6 +57,11 @@ import java.lang.IllegalStateException internal val LOG = Logger.getInstance(KotlinCacheService::class.java) +// For every different instance of these settings we must create a different builtIns instance and thus a different moduleDescriptor graph +// since in the current implementation types from one module are leaking into other modules' resolution +// meaning that we can't just change those setting on a per module basis +data class PlatformAnalysisSettings(val platform: TargetPlatform, val sdk: Sdk?, val isAdditionalBuiltInFeaturesSupported: Boolean) + class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { override fun getResolutionFacade(elements: List): ResolutionFacade { return getFacadeToAnalyzeFiles(elements.map { it.containingKtFile }) @@ -61,10 +69,10 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { override fun getSuppressionCache(): KotlinSuppressCache = kotlinSuppressCache.value - private val globalFacadesPerPlatformAndSdk: SLRUCache, GlobalFacade> = - object : SLRUCache, GlobalFacade>(2 * 3, 2 * 3) { - override fun createValue(key: Pair): GlobalFacade { - return GlobalFacade(key.first, key.second) + private val globalFacadesPerPlatformAndSdk: SLRUCache = + object : SLRUCache(2 * 3 * 2, 2 * 3 * 2) { + override fun createValue(settings: PlatformAnalysisSettings): GlobalFacade { + return GlobalFacade(settings) } } @@ -87,15 +95,15 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { ): ProjectResolutionFacade { val sdk = findJdk(dependenciesModuleInfo.dependencies, project) val platform = JvmPlatform // TODO: Js scripts? - val sdkFacade = GlobalFacade(platform, sdk).facadeForSdk + val facadeKey = PlatformAnalysisSettings(platform, sdk, true) + val sdkFacade = GlobalFacade(facadeKey).facadeForSdk val globalContext = sdkFacade.globalContext.contextWithNewLockAndCompositeExceptionTracker() return ProjectResolutionFacade( "facadeForScriptDependencies", project, globalContext, globalResolveSessionProvider( "dependencies of scripts", - platform, - sdk, + facadeKey, reuseDataFrom = sdkFacade, allModules = dependenciesModuleInfo.dependencies(), //TODO: provide correct trackers @@ -111,15 +119,14 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { } - private inner class GlobalFacade(platform: TargetPlatform, sdk: Sdk?) { + private inner class GlobalFacade(settings: PlatformAnalysisSettings) { private val sdkContext = GlobalContext() val facadeForSdk = ProjectResolutionFacade( "facadeForSdk", project, sdkContext, globalResolveSessionProvider( - "sdk $sdk", - platform, - sdk, + "sdk ${settings.sdk}", + settings, moduleFilter = { it is SdkInfo }, dependencies = listOf( LibraryModificationTracker.getInstance(project), @@ -132,9 +139,8 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { "facadeForLibraries", project, librariesContext, globalResolveSessionProvider( - "project libraries for platform $platform", - platform, - sdk, + "project libraries for platform ${settings.sdk}", + settings, reuseDataFrom = facadeForSdk, moduleFilter = { it is LibraryInfo }, dependencies = listOf( @@ -150,9 +156,8 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { "facadeForModules", project, modulesContext, globalResolveSessionProvider( - "project source roots and libraries for platform $platform", - platform, - sdk, + "project source roots and libraries for platform ${settings.platform}", + settings, reuseDataFrom = facadeForLibraries, moduleFilter = { !it.isLibraryClasses() }, dependencies = listOf(PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT)) @@ -161,20 +166,28 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { @Deprecated("Use JetElement.getResolutionFacade(), please avoid introducing new usages") fun getProjectService(platform: TargetPlatform, ideaModuleInfo: IdeaModuleInfo, serviceClass: Class): T { - return globalFacade(platform, ideaModuleInfo.sdk).resolverForModuleInfo(ideaModuleInfo).componentProvider.getService(serviceClass) + val settings = PlatformAnalysisSettings(platform, ideaModuleInfo.sdk, ideaModuleInfo.supportsAdditionalBuiltInsMembers()) + return globalFacade(settings).resolverForModuleInfo(ideaModuleInfo).componentProvider.getService(serviceClass) + } + + private fun IdeaModuleInfo.supportsAdditionalBuiltInsMembers(): Boolean { + return project.service() + .getLanguageVersionSettings(this, project) + .supportsFeature(LanguageFeature.AdditionalBuiltInsMembers) } fun tryGetProjectService(platform: TargetPlatform, ideaModuleInfo: IdeaModuleInfo, serviceClass: Class): T? { - return globalFacade(platform, ideaModuleInfo.sdk).tryGetResolverForModuleInfo(ideaModuleInfo)?.componentProvider?.tryGetService(serviceClass) + val settings = PlatformAnalysisSettings(platform, ideaModuleInfo.sdk, ideaModuleInfo.supportsAdditionalBuiltInsMembers()) + return globalFacade(settings).tryGetResolverForModuleInfo(ideaModuleInfo)?.componentProvider?.tryGetService(serviceClass) } - private fun globalFacade(platform: TargetPlatform, sdk: Sdk?) = - getOrBuildGlobalFacade(platform, sdk).facadeForModules + private fun globalFacade(settings: PlatformAnalysisSettings) = + getOrBuildGlobalFacade(settings).facadeForModules - private fun librariesFacade(platform: TargetPlatform, sdk: Sdk?) = getOrBuildGlobalFacade(platform, sdk).facadeForLibraries + private fun librariesFacade(settings: PlatformAnalysisSettings) = getOrBuildGlobalFacade(settings).facadeForLibraries @Synchronized - private fun getOrBuildGlobalFacade(platform: TargetPlatform, sdk: Sdk?) = globalFacadesPerPlatformAndSdk[Pair(platform, sdk)] + private fun getOrBuildGlobalFacade(settings: PlatformAnalysisSettings) = globalFacadesPerPlatformAndSdk[settings] private val IdeaModuleInfo.sdk: Sdk? get() = dependencies().firstIsInstanceOrNull()?.sdk @@ -183,6 +196,7 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { val targetPlatform = files.map { TargetPlatformDetector.getPlatform(it) }.toSet().single() val syntheticFileModule = files.map(KtFile::getModuleInfo).toSet().single() val sdk = syntheticFileModule.sdk + val settings = PlatformAnalysisSettings(targetPlatform, sdk, syntheticFileModule.supportsAdditionalBuiltInsMembers()) val filesModificationTracker: ModificationTracker // File copies are created during completion and receive correct modification events through POM. // Dummy files created e.g. by J2K do not receive events. @@ -205,8 +219,7 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { ): (GlobalContextImpl, Project) -> ModuleResolverProvider { return globalResolveSessionProvider( debugName, - targetPlatform, - sdk, + settings, syntheticFiles = files, reuseDataFrom = reuseDataFrom, moduleFilter = moduleFilter, @@ -218,7 +231,7 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { return when { syntheticFileModule is ModuleSourceInfo -> { val dependentModules = syntheticFileModule.getDependentModules() - val modulesFacade = globalFacade(targetPlatform, sdk) + val modulesFacade = globalFacade(settings) val globalContext = modulesFacade.globalContext.contextWithNewLockAndCompositeExceptionTracker() ProjectResolutionFacade( "facadeForSynthetic in ModuleSourceInfo", @@ -261,7 +274,7 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { } syntheticFileModule is LibrarySourceInfo || syntheticFileModule is NotUnderContentRootModuleInfo -> { - val librariesFacade = librariesFacade(targetPlatform, sdk) + val librariesFacade = librariesFacade(settings) val globalContext = librariesFacade.globalContext.contextWithNewLockAndCompositeExceptionTracker() ProjectResolutionFacade( "facadeForSynthetic in LibrarySourceInfo or NotUnderContentRootModuleInfo", @@ -362,7 +375,8 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { } private fun getResolutionFacadeByModuleInfo(moduleInfo: IdeaModuleInfo, platform: TargetPlatform): ResolutionFacade { - val projectFacade = globalFacade(platform, moduleInfo.sdk) + val settings = PlatformAnalysisSettings(platform, moduleInfo.sdk, moduleInfo.supportsAdditionalBuiltInsMembers()) + val projectFacade = globalFacade(settings) return ResolutionFacadeImpl(projectFacade, moduleInfo) } @@ -382,8 +396,7 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { private fun globalResolveSessionProvider( debugName: String, - platform: TargetPlatform, - sdk: Sdk?, + settings: PlatformAnalysisSettings, dependencies: Collection, moduleFilter: (IdeaModuleInfo) -> Boolean, reuseDataFrom: ProjectResolutionFacade? = null, @@ -394,11 +407,10 @@ private fun globalResolveSessionProvider( val delegateResolverForProject = delegateResolverProvider?.resolverForProject ?: EmptyResolverForProject() createModuleResolverProvider( - debugName, project, globalContext, sdk, - platform, + debugName, project, globalContext, settings, syntheticFiles, delegateResolverForProject, moduleFilter, allModules, - delegateResolverProvider?.builtInsCache, + delegateResolverProvider?.builtIns, dependencies ) } 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 9072a26dff2..35c6e1149ae 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 @@ -26,39 +26,34 @@ import com.intellij.openapi.roots.LibraryOrderEntry import com.intellij.openapi.roots.ModuleRootManager import org.jetbrains.kotlin.analyzer.AnalyzerFacade import org.jetbrains.kotlin.analyzer.ModuleContent -import org.jetbrains.kotlin.analyzer.ModuleInfo import org.jetbrains.kotlin.analyzer.ResolverForProject +import org.jetbrains.kotlin.builtins.DefaultBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.context.GlobalContextImpl import org.jetbrains.kotlin.context.withProject import org.jetbrains.kotlin.idea.project.AnalyzerFacadeProvider import org.jetbrains.kotlin.idea.project.IdeaEnvironment +import org.jetbrains.kotlin.js.resolve.JsPlatform import org.jetbrains.kotlin.load.java.structure.JavaClass import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl +import org.jetbrains.kotlin.platform.JvmBuiltIns import org.jetbrains.kotlin.psi.KtFile -import org.jetbrains.kotlin.resolve.TargetPlatform import org.jetbrains.kotlin.resolve.jvm.JvmPlatformParameters +import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform fun createModuleResolverProvider( debugName: String, project: Project, globalContext: GlobalContextImpl, - sdk: Sdk?, - platform: TargetPlatform, + analysisSettings: PlatformAnalysisSettings, syntheticFiles: Collection, delegateResolver: ResolverForProject, moduleFilter: (IdeaModuleInfo) -> Boolean, allModules: Collection?, - builtInsCache: BuiltInsCache?, // this cache is null only for SDK resolver provider + providedBuiltIns: KotlinBuiltIns?, // null means create new builtins based on SDK dependencies: Collection ): ModuleResolverProvider { - var sdkBuiltIns: KotlinBuiltIns? = null - - val builtInsProvider: (ModuleInfo) -> KotlinBuiltIns = builtInsCache?.let { it::getBuiltIns } ?: run { - sdkBuiltIns = BuiltInsCache.calculateBuiltIns(platform, sdk, globalContext); - - { _: ModuleInfo -> sdkBuiltIns!! } - } + val builtIns = providedBuiltIns ?: createBuiltIns(analysisSettings, globalContext) val allModuleInfos = (allModules ?: collectAllModuleInfosFromIdeaModel(project)).toHashSet() @@ -81,10 +76,10 @@ fun createModuleResolverProvider( return AnalyzerFacade.setupResolverForProject( debugName, globalContext.withProject(project), modulesToCreateResolversFor, - { module -> AnalyzerFacadeProvider.getAnalyzerFacade(module.platform ?: platform) }, - modulesContent, jvmPlatformParameters, IdeaEnvironment, builtInsProvider, + { module -> AnalyzerFacadeProvider.getAnalyzerFacade(module.platform ?: analysisSettings.platform) }, + modulesContent, jvmPlatformParameters, IdeaEnvironment, builtIns, delegateResolver, { _, c -> IDEPackagePartProvider(c.moduleContentScope) }, - sdk?.let { SdkInfo(project, it) }, + analysisSettings.sdk?.let { SdkInfo(project, it) }, modulePlatforms = { module -> module.platform?.multiTargetPlatform }, packageOracleFactory = project.service() ) @@ -92,15 +87,14 @@ fun createModuleResolverProvider( val resolverForProject = createResolverForProject() - val newBuiltInsCache = builtInsCache ?: run { - val sdkModuleDescriptor = sdk?.let { resolverForProject.descriptorForModule(SdkInfo(project, it)) } - - BuiltInsCache.createCacheAndInitializeBuiltIns(project, platform, sdk, sdkModuleDescriptor, sdkBuiltIns!!, globalContext) + if (providedBuiltIns == null && builtIns is JvmBuiltIns) { + val sdkModuleDescriptor = analysisSettings.sdk!!.let { resolverForProject.descriptorForModule(SdkInfo(project, it)) } + builtIns.initialize(sdkModuleDescriptor, analysisSettings.isAdditionalBuiltInFeaturesSupported) } return ModuleResolverProviderImpl( resolverForProject, - newBuiltInsCache, + builtIns, dependencies + listOf(globalContext.exceptionTracker) ) } @@ -130,6 +124,13 @@ fun collectAllModuleInfosFromIdeaModel(project: Project): List { return collectAllModuleInfos } +private fun createBuiltIns(settings: PlatformAnalysisSettings, sdkContext: GlobalContextImpl): KotlinBuiltIns = when { + settings.platform is JsPlatform -> JsPlatform.builtIns + settings.platform is JvmPlatform && settings.sdk != null -> JvmBuiltIns(sdkContext.storageManager) + else -> DefaultBuiltIns.Instance + +} + fun getAllProjectSdks(): Collection { return ProjectJdkTable.getInstance().allJdks.toList() } @@ -137,12 +138,12 @@ fun getAllProjectSdks(): Collection { interface ModuleResolverProvider { val resolverForProject: ResolverForProject - val builtInsCache: BuiltInsCache + val builtIns: KotlinBuiltIns val cacheDependencies: Collection } class ModuleResolverProviderImpl( override val resolverForProject: ResolverForProject, - override val builtInsCache: BuiltInsCache, + override val builtIns: KotlinBuiltIns, override val cacheDependencies: Collection ) : ModuleResolverProvider diff --git a/idea/testData/multiModuleHighlighting/languageVersionsViaFacets/m1/m1.kt b/idea/testData/multiModuleHighlighting/languageVersionsViaFacets/m1/m1.kt new file mode 100644 index 00000000000..fb7184047cf --- /dev/null +++ b/idea/testData/multiModuleHighlighting/languageVersionsViaFacets/m1/m1.kt @@ -0,0 +1,9 @@ +package languageVersion1_1 + +public fun useJavaMap1_1(): java.util.HashMap { + val g = java.util.HashMap() + g.values.removeIf { it < 5 } + return g +} + +val use1_0 = languageVersion1_0.useJavaMap1_0().values.removeIf { it < 5 } \ No newline at end of file diff --git a/idea/testData/multiModuleHighlighting/languageVersionsViaFacets/m2/m2.kt b/idea/testData/multiModuleHighlighting/languageVersionsViaFacets/m2/m2.kt new file mode 100644 index 00000000000..b480ee4fd6f --- /dev/null +++ b/idea/testData/multiModuleHighlighting/languageVersionsViaFacets/m2/m2.kt @@ -0,0 +1,10 @@ +package languageVersion1_0 + +public fun useJavaMap1_0(): java.util.HashMap { + val g = java.util.HashMap() + g.values.removeIf { it < 5 } + return g +} + +val use1_1 = languageVersion1_1.useJavaMap1_1().values.removeIf { it < 5 } + diff --git a/idea/tests/org/jetbrains/kotlin/idea/caches/resolve/MultiModuleHighlightingTest.kt b/idea/tests/org/jetbrains/kotlin/idea/caches/resolve/MultiModuleHighlightingTest.kt index eee52a252cf..378393c26a3 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/caches/resolve/MultiModuleHighlightingTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/caches/resolve/MultiModuleHighlightingTest.kt @@ -16,15 +16,21 @@ package org.jetbrains.kotlin.idea.caches.resolve +import com.intellij.facet.FacetManager import com.intellij.openapi.module.Module import com.intellij.openapi.roots.DependencyScope import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess import org.jetbrains.kotlin.analyzer.ModuleInfo import org.jetbrains.kotlin.analyzer.ResolverForModuleComputationTracker +import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime import org.jetbrains.kotlin.config.JvmTarget +import org.jetbrains.kotlin.config.LanguageVersion import org.jetbrains.kotlin.config.TargetPlatformKind import org.jetbrains.kotlin.idea.completion.test.withServiceRegistered +import org.jetbrains.kotlin.idea.facet.KotlinFacetConfiguration +import org.jetbrains.kotlin.idea.facet.KotlinFacetType +import org.jetbrains.kotlin.idea.util.application.runWriteAction import org.jetbrains.kotlin.test.KotlinTestUtils class MultiModuleHighlightingTest : AbstractMultiModuleHighlightingTest() { @@ -107,6 +113,34 @@ class MultiModuleHighlightingTest : AbstractMultiModuleHighlightingTest() { checkHighlightingInAllFiles() } + fun testLanguageVersionsViaFacets() { + val m1 = module("m1", useFullJdk = true).setupKotlinFacet { + settings.languageLevel = LanguageVersion.KOTLIN_1_1 + } + val m2 = module("m2", useFullJdk = true).setupKotlinFacet { + settings.languageLevel = LanguageVersion.KOTLIN_1_0 + } + + m1.addDependency(m2) + m2.addDependency(m1) + + checkHighlightingInAllFiles() + } + + private fun Module.setupKotlinFacet(configure: KotlinFacetConfiguration.() -> Unit) = apply { + runWriteAction { + val facet = FacetManager.getInstance(this).addFacet(KotlinFacetType.INSTANCE, KotlinFacetType.NAME, null) + val configuration = facet.configuration + + // this is actually needed so facet settings object is in a valid state + configuration.settings.compilerArguments = K2JVMCompilerArguments() + // make sure module-specific settings are used + configuration.settings.useProjectSettings = false + + configuration.configure() + } + } + class MultiPlatform : AbstractMultiModuleHighlightingTest() { override val testPath get() = super.testPath + "multiplatform/"