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
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 cd808b5..4e9d431 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 @@
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 @@
);
}
+ 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 9a8aacf..3ab435be 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 @@
)
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 d0c8146..33ecee8 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<KtModule>,
) : ProjectStructureProvider() {
+ private val ktNotUnderContentRootModuleWithoutPsiFile by lazy {
+ KtNotUnderContentRootModuleImpl(
+ moduleDescription = "Standalone-not-under-content-root-module-without-psi-file"
+ )
+ }
+
+ private val notUnderContentRootModuleCache = ContainerUtil.createConcurrentWeakMap<PsiFile, KtNotUnderContentRootModule>()
+
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 ceb7084..59cc87b 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.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 @@
): ProjectStructureProvider = buildProjectStructureProvider {
addModule(
buildKtSourceModule {
- val platform = TargetPlatform(setOf(JdkPlatform(JvmTarget.DEFAULT)))
+ val platform = JvmPlatforms.defaultJvmPlatform
val moduleName = compilerConfig.get(CommonConfigurationKeys.MODULE_NAME) ?: "<no module name provided>"
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 0000000..ea808a4
--- /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<KtModule> = emptyList(),
+ override val directRefinementDependencies: List<KtModule> = emptyList(),
+ override val directFriendDependencies: List<KtModule> = 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