From 9f2a03947c7aad5a892e5d88c3d1d5e944cf5d63 Mon Sep 17 00:00:00 2001 From: Dmitry Savvinov Date: Wed, 5 Jun 2019 12:36:12 +0300 Subject: [PATCH] [Resolve] Compute dependency on SDK properly Under COMPOSITE resolution mode (see ResolutionModeComponent) we have no fixed and globally known SDK, instead, for each module we have to find SDK it it's transitive dependencies. Currently, this is necessary in order to create proper JvmBuiltIns, which need dependency on SDK to be present in immediate dependencies. --- .../jetbrains/kotlin/analyzer/AnalyzerFacade.kt | 4 ++-- .../compiler/MultiModuleJavaAnalysisCustomTest.kt | 2 +- .../kotlin/idea/caches/project/getModuleInfo.kt | 15 +++++++++++++++ .../caches/resolve/ProjectResolutionFacade.kt | 9 +++++++-- 4 files changed, 25 insertions(+), 5 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AnalyzerFacade.kt b/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AnalyzerFacade.kt index 8a185ee46e5..ed6927d0638 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AnalyzerFacade.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AnalyzerFacade.kt @@ -96,7 +96,7 @@ class ResolverForProjectImpl( private val invalidateOnOOCB: Boolean, override val builtIns: KotlinBuiltIns = DefaultBuiltIns.Instance, private val delegateResolver: ResolverForProject = EmptyResolverForProject(), - private val firstDependency: M? = null, + private val sdkDependency: (M) -> M?, private val packageOracleFactory: PackageOracleFactory = PackageOracleFactory.OptimisticFactory, private val isReleaseCoroutines: Boolean? = null ) : ResolverForProject() { @@ -139,7 +139,7 @@ class ResolverForProjectImpl( LazyModuleDependencies( projectContext.storageManager, module, - firstDependency, + sdkDependency(module), this ) ) diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/MultiModuleJavaAnalysisCustomTest.kt b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/MultiModuleJavaAnalysisCustomTest.kt index 9915916de9e..e26bfb78744 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/MultiModuleJavaAnalysisCustomTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/MultiModuleJavaAnalysisCustomTest.kt @@ -96,7 +96,7 @@ class MultiModuleJavaAnalysisCustomTest : KtUsefulTestCase() { resolverForModuleFactoryByPlatform = { JvmResolverForModuleFactory(platformParameters, CompilerEnvironment, JvmPlatforms.defaultJvmPlatform) }, - builtIns = builtIns + sdkDependency = { null } ) builtIns.initialize( diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/getModuleInfo.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/getModuleInfo.kt index 0b8e464f536..aecb2f919c6 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/getModuleInfo.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/getModuleInfo.kt @@ -17,6 +17,7 @@ import org.jetbrains.kotlin.analyzer.ModuleInfo import org.jetbrains.kotlin.asJava.classes.FakeLightClassForFileOfPackage import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade import org.jetbrains.kotlin.asJava.elements.KtLightElement +import org.jetbrains.kotlin.caches.project.cacheInvalidatingOnRootModifications import org.jetbrains.kotlin.idea.caches.lightClasses.KtLightClassForDecompiledDeclaration import org.jetbrains.kotlin.idea.core.isInTestSourceContentKotlinAware import org.jetbrains.kotlin.idea.core.script.ScriptDependenciesManager @@ -28,7 +29,9 @@ import org.jetbrains.kotlin.idea.util.isKotlinBinary import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.getParentOfType import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition +import org.jetbrains.kotlin.types.typeUtil.lazyClosure import org.jetbrains.kotlin.utils.addIfNotNull +import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull import org.jetbrains.kotlin.utils.sure import org.jetbrains.kotlin.utils.yieldIfNotNull @@ -40,6 +43,18 @@ fun PsiElement.getNullableModuleInfo(): IdeaModuleInfo? = this.collectInfos(Modu fun PsiElement.getModuleInfos(): Sequence = this.collectInfos(ModuleInfoCollector.ToSequence) +private fun ModuleInfo.doFindSdk(): SdkInfo? = dependencies().lazyClosure { it.dependencies() }.firstIsInstanceOrNull() + +fun ModuleInfo.findSdkAcrossDependencies(): SdkInfo? { + return when (this) { + // It is important to check for cases of test/production explicitly, because we're using lambda's class + // of 'cacheInvalidatingOnRootModifications' as key for cache, and it should be different for Production/Source + is ModuleProductionSourceInfo -> module.cacheInvalidatingOnRootModifications { doFindSdk() } + is ModuleTestSourceInfo -> module.cacheInvalidatingOnRootModifications { doFindSdk() } + else -> doFindSdk() + } +} + fun getModuleInfoByVirtualFile(project: Project, virtualFile: VirtualFile): IdeaModuleInfo? = collectInfosByVirtualFile( project, virtualFile, 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 2bfb3e21765..da7919b0042 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 @@ -167,14 +167,19 @@ internal class ProjectResolutionFacade( }, builtIns = builtIns, delegateResolver = delegateResolverForProject, - firstDependency = (settings as PlatformAnalysisSettingsImpl).sdk?.let { SdkInfo(project, it) }, + sdkDependency = { module -> + if (settings is PlatformAnalysisSettingsImpl) + settings.sdk?.let { SdkInfo(project, it) } + else + module.findSdkAcrossDependencies() + }, packageOracleFactory = ServiceManager.getService(project, IdePackageOracleFactory::class.java), invalidateOnOOCB = invalidateOnOOCB, isReleaseCoroutines = settings.isReleaseCoroutines ) if (delegateBuiltIns == null && builtIns is JvmBuiltIns) { - val sdkModuleDescriptor = settings.sdk!!.let { + val sdkModuleDescriptor = (settings as PlatformAnalysisSettingsImpl).sdk!!.let { resolverForProject.descriptorForModule( SdkInfo(project, it) )