[Analysis API] Extract dangling file module computation

Use the same code for creating dangling file modules inside tests,
the stand-alone API, and in the IDE.
This commit is contained in:
Yan Zhulanow
2023-11-13 21:19:24 +09:00
committed by Space Team
parent 441f3e0209
commit 2899822102
4 changed files with 90 additions and 45 deletions
@@ -17,7 +17,6 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.LLFirBu
import org.jetbrains.kotlin.analysis.project.structure.*
import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.analysisContext
import org.jetbrains.kotlin.serialization.deserialization.builtins.BuiltInSerializerProtocol
import org.jetbrains.kotlin.utils.KotlinExceptionWithAttachments
@@ -40,38 +39,39 @@ internal class KtStandaloneProjectStructureProvider(
LLFirBuiltinsSessionFactory.getInstance(project).getBuiltinsSession(platform).ktModule as KtBuiltinsModule
}
override fun getNotUnderContentRootModule(project: Project, file: PsiFile?): KtNotUnderContentRootModule {
if (file == null) {
return ktNotUnderContentRootModuleWithoutPsiFile
}
return notUnderContentRootModuleCache.getOrPut(file) {
KtNotUnderContentRootModuleImpl(
name = file.name,
moduleDescription = "Standalone-not-under-content-root-module-for-$file",
file = file,
project = project,
)
}
}
@OptIn(KtModuleStructureInternals::class)
override fun getModule(element: PsiElement, contextualModule: KtModule?): KtModule {
val containingFileAsPsiFile = element.containingFile
val containingFile = element.containingFile
?: return ktNotUnderContentRootModuleWithoutPsiFile
// If an [element] is created on the fly, e.g., via [KtPsiFactory],
// its containing [PsiFile] may not have [VirtualFile].
// We can attempt to use an associated [analysisContext] (from [KtPsiFactory]) if any.
// If both fail, the [element] is not bound to any [KtModule], and we bail out early
// by returning a [KtNotUnderContentRootModule] (for that specific unbound file).
val containingFileAsVirtualFile = containingFileAsPsiFile.virtualFile
?: (containingFileAsPsiFile as? KtFile)?.analysisContext?.containingFile?.virtualFile
?: return notUnderContentRootModuleCache.getOrPut(containingFileAsPsiFile) {
KtNotUnderContentRootModuleImpl(
name = containingFileAsPsiFile.name,
moduleDescription = "Standalone-not-under-content-root-module-for-$containingFileAsPsiFile",
file = containingFileAsPsiFile,
project = project,
)
}
if (containingFileAsVirtualFile.extension == BuiltInSerializerProtocol.BUILTINS_FILE_EXTENSION) {
val virtualFile = containingFile.virtualFile
?: error("${containingFile.name} is not a physical file")
if (virtualFile.extension == BuiltInSerializerProtocol.BUILTINS_FILE_EXTENSION) {
return builtinsModule
}
containingFileAsVirtualFile.analysisExtensionFileContextModule?.let { return it }
computeSpecialModule(containingFile)?.let { return it }
return allKtModules.firstOrNull { module ->
containingFileAsVirtualFile in module.contentScope
}
return allKtModules.firstOrNull { module -> virtualFile in module.contentScope }
?: throw KotlinExceptionWithAttachments("Cannot find KtModule; see the attachment for more details.")
.withAttachment(
containingFileAsVirtualFile.path,
virtualFile.path,
allKtModules.joinToString(separator = System.lineSeparator()) { it.asDebugString() }
)
}