From 4531080858a6fffacf4f4ce6ddb64aa0f8a01cc9 Mon Sep 17 00:00:00 2001 From: Jinseong Jeon Date: Wed, 3 Aug 2022 00:49:22 -0700 Subject: [PATCH] AA: introduce KtNotUnderContentRootModule impl to standalone mode to gracefully handle element/file/etc without a binding module. This could happen, e.g., 1) source PSI created from KtPsiFactory, which uses literally dummy.kt 2) debugger that creates a code fragment on-the-fly 3) on-air analysis of non-physical files --- .../standalone/RegisterComponentService.java | 8 ++++++ .../StandaloneAnalysisAPISessionBuilder.kt | 1 + .../structure/impl/KtModuleProviderImpl.kt | 21 ++++++++++++-- .../project/structure/impl/KtModuleUtils.kt | 5 ++-- .../impl/KtNotUnderContentRootModuleImpl.kt | 28 +++++++++++++++++++ 5 files changed, 57 insertions(+), 6 deletions(-) create mode 100644 analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/project/structure/impl/KtNotUnderContentRootModuleImpl.kt diff --git a/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/api/standalone/RegisterComponentService.java b/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/api/standalone/RegisterComponentService.java index cd808b52cf4..4e9d431d736 100644 --- a/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/api/standalone/RegisterComponentService.java +++ b/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/api/standalone/RegisterComponentService.java @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.analysis.api.standalone; import com.intellij.mock.MockProject; import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirResolveSessionService; import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.LLFirLibrarySessionFactory; +import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.LLFirNonUnderContentRootSessionFactory; class RegisterComponentService { static void registerLLFirLibrarySessionFactory(MockProject project) { @@ -17,6 +18,13 @@ class RegisterComponentService { ); } + static void registerLLFirNonUnderContentRootSessionFactory(MockProject project) { + project.registerService( + LLFirNonUnderContentRootSessionFactory.class, + new LLFirNonUnderContentRootSessionFactory(project) + ); + } + static void registerLLFirResolveSessionService(MockProject project) { project.registerService( LLFirResolveSessionService.class, diff --git a/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/api/standalone/StandaloneAnalysisAPISessionBuilder.kt b/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/api/standalone/StandaloneAnalysisAPISessionBuilder.kt index 9a8aacf4598..3ab435be0fe 100644 --- a/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/api/standalone/StandaloneAnalysisAPISessionBuilder.kt +++ b/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/api/standalone/StandaloneAnalysisAPISessionBuilder.kt @@ -144,6 +144,7 @@ public class StandaloneAnalysisAPISessionBuilder( ) registerService(LLFirBuiltinsSessionFactory::class.java, LLFirBuiltinsSessionFactory(this)) RegisterComponentService.registerLLFirLibrarySessionFactory(this) + RegisterComponentService.registerLLFirNonUnderContentRootSessionFactory(this) RegisterComponentService.registerLLFirResolveSessionService(this) registerService( PackagePartProviderFactory::class.java, diff --git a/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/project/structure/impl/KtModuleProviderImpl.kt b/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/project/structure/impl/KtModuleProviderImpl.kt index d0c81464209..33ecee8c8aa 100644 --- a/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/project/structure/impl/KtModuleProviderImpl.kt +++ b/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/project/structure/impl/KtModuleProviderImpl.kt @@ -6,23 +6,38 @@ package org.jetbrains.kotlin.analysis.project.structure.impl import com.intellij.psi.PsiElement +import com.intellij.psi.PsiFile import com.intellij.psi.PsiFileSystemItem import com.intellij.psi.PsiJavaFile +import com.intellij.util.containers.ContainerUtil import org.jetbrains.kotlin.analysis.api.standalone.base.project.structure.StandaloneProjectFactory.findJvmRootsForJavaFiles import org.jetbrains.kotlin.analysis.project.structure.* -import org.jetbrains.kotlin.platform.TargetPlatform internal class KtModuleProviderImpl( internal val mainModules: List, ) : ProjectStructureProvider() { + private val ktNotUnderContentRootModuleWithoutPsiFile by lazy { + KtNotUnderContentRootModuleImpl( + moduleDescription = "Standalone-not-under-content-root-module-without-psi-file" + ) + } + + private val notUnderContentRootModuleCache = ContainerUtil.createConcurrentWeakMap() + override fun getKtModuleForKtElement(element: PsiElement): KtModule { val containingFileAsPsiFile = element.containingFile - ?: error("Can't get containing PsiFile for ${element.text}") + ?: return ktNotUnderContentRootModuleWithoutPsiFile // If an [element] is created on the fly, e.g., via [KtPsiFactory], // its containing [PsiFile] may not have [VirtualFile]. // That also means the [element] is not bound to any [KtModule] either. val containingFileAsVirtualFile = containingFileAsPsiFile.virtualFile - ?: error("Can't get containing VirtualFile for ${element.text} in $containingFileAsPsiFile") + ?: return notUnderContentRootModuleCache.getOrPut(containingFileAsPsiFile) { + KtNotUnderContentRootModuleImpl( + moduleDescription = "Standalone-not-under-content-root-module-for-$containingFileAsPsiFile", + psiFile = containingFileAsPsiFile + ) + } + return mainModules.first { module -> containingFileAsVirtualFile in module.contentScope } diff --git a/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/project/structure/impl/KtModuleUtils.kt b/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/project/structure/impl/KtModuleUtils.kt index ceb708451e3..59cc87b3d23 100644 --- a/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/project/structure/impl/KtModuleUtils.kt +++ b/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/project/structure/impl/KtModuleUtils.kt @@ -28,12 +28,11 @@ import org.jetbrains.kotlin.cli.jvm.config.jvmModularRoots import org.jetbrains.kotlin.config.CommonConfigurationKeys import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.JVMConfigurationKeys -import org.jetbrains.kotlin.config.JvmTarget import org.jetbrains.kotlin.js.resolve.JsPlatformAnalyzerServices import org.jetbrains.kotlin.platform.TargetPlatform import org.jetbrains.kotlin.platform.isCommon import org.jetbrains.kotlin.platform.js.isJs -import org.jetbrains.kotlin.platform.jvm.JdkPlatform +import org.jetbrains.kotlin.platform.jvm.JvmPlatforms import org.jetbrains.kotlin.platform.jvm.isJvm import org.jetbrains.kotlin.platform.konan.isNative import org.jetbrains.kotlin.psi.KtFile @@ -102,7 +101,7 @@ internal fun buildKtModuleProviderByCompilerConfiguration( ): ProjectStructureProvider = buildProjectStructureProvider { addModule( buildKtSourceModule { - val platform = TargetPlatform(setOf(JdkPlatform(JvmTarget.DEFAULT))) + val platform = JvmPlatforms.defaultJvmPlatform val moduleName = compilerConfig.get(CommonConfigurationKeys.MODULE_NAME) ?: "" val libraryRoots = compilerConfig.jvmModularRoots + compilerConfig.jvmClasspathRoots diff --git a/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/project/structure/impl/KtNotUnderContentRootModuleImpl.kt b/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/project/structure/impl/KtNotUnderContentRootModuleImpl.kt new file mode 100644 index 00000000000..ea808a44427 --- /dev/null +++ b/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/project/structure/impl/KtNotUnderContentRootModuleImpl.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.analysis.project.structure.impl + +import com.intellij.psi.PsiFile +import com.intellij.psi.search.GlobalSearchScope +import org.jetbrains.kotlin.analysis.project.structure.KtModule +import org.jetbrains.kotlin.analysis.project.structure.KtNotUnderContentRootModule +import org.jetbrains.kotlin.platform.TargetPlatform +import org.jetbrains.kotlin.platform.jvm.JvmPlatforms +import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices + +internal class KtNotUnderContentRootModuleImpl( + override val directRegularDependencies: List = emptyList(), + override val directRefinementDependencies: List = emptyList(), + override val directFriendDependencies: List = emptyList(), + override val platform: TargetPlatform = JvmPlatforms.defaultJvmPlatform, + psiFile: PsiFile? = null, + override val moduleDescription: String, +) : KtNotUnderContentRootModule, KtModuleWithPlatform { + override val analyzerServices: PlatformDependentAnalyzerServices = super.analyzerServices + + override val contentScope: GlobalSearchScope = + if (psiFile != null) GlobalSearchScope.fileScope(psiFile) else GlobalSearchScope.EMPTY_SCOPE +} \ No newline at end of file