diff --git a/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/project/structure/builder/KtSourceModuleBuilder.kt b/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/project/structure/builder/KtSourceModuleBuilder.kt index 1f5e17993a7..9234300bb58 100644 --- a/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/project/structure/builder/KtSourceModuleBuilder.kt +++ b/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/project/structure/builder/KtSourceModuleBuilder.kt @@ -5,18 +5,22 @@ package org.jetbrains.kotlin.analysis.project.structure.builder -import com.intellij.psi.PsiFileSystemItem +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.psi.PsiManager import com.intellij.psi.search.GlobalSearchScope import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule import org.jetbrains.kotlin.analysis.project.structure.impl.KtSourceModuleImpl +import org.jetbrains.kotlin.analysis.project.structure.impl.collectSourceFilePaths import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreProjectEnvironment import org.jetbrains.kotlin.config.ApiVersion import org.jetbrains.kotlin.config.LanguageVersion import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl +import java.nio.file.Path import kotlin.contracts.ExperimentalContracts import kotlin.contracts.InvocationKind import kotlin.contracts.contract +import kotlin.io.path.isDirectory @KtModuleBuilderDsl public class KtSourceModuleBuilder( @@ -25,19 +29,22 @@ public class KtSourceModuleBuilder( public lateinit var moduleName: String public var languageVersionSettings: LanguageVersionSettings = LanguageVersionSettingsImpl(LanguageVersion.LATEST_STABLE, ApiVersion.LATEST) - public lateinit var contentScope: GlobalSearchScope - private val sourceRoots: MutableList = mutableListOf() + private val sourceRoots: MutableList = mutableListOf() - public fun addSourceRoot(file: PsiFileSystemItem) { - sourceRoots.add(file) + public fun addSourceRoot(path: Path) { + sourceRoots.add(path) } - public fun addSourceRoots(files: Collection) { - sourceRoots.addAll(files) + public fun addSourceRoots(paths: Collection) { + sourceRoots.addAll(paths) } override fun build(): KtSourceModule { + val virtualFiles = collectVirtualFilesByRoots() + val psiManager = PsiManager.getInstance(kotlinCoreProjectEnvironment.project) + val psiFiles = virtualFiles.mapNotNull { psiManager.findFile(it) } + val contentScope = GlobalSearchScope.filesScope(kotlinCoreProjectEnvironment.project, virtualFiles) return KtSourceModuleImpl( directRegularDependencies, directDependsOnDependencies, @@ -47,9 +54,26 @@ public class KtSourceModuleBuilder( kotlinCoreProjectEnvironment.project, moduleName, languageVersionSettings, - sourceRoots, + psiFiles, ) } + + private fun collectVirtualFilesByRoots(): List { + val localFileSystem = kotlinCoreProjectEnvironment.environment.localFileSystem + return buildList { + for (root in sourceRoots) { + val files = if (root.isDirectory()) { + collectSourceFilePaths(root) + } else { + listOf(root) + } + for (file in files) { + val virtualFile = localFileSystem.findFileByIoFile(file.toFile()) ?: continue + add(virtualFile) + } + } + } + } } @OptIn(ExperimentalContracts::class) 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 95a3a4884e4..316836bdcfe 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 @@ -15,7 +15,6 @@ import org.jetbrains.kotlin.analysis.api.standalone.base.project.structure.KtSta import org.jetbrains.kotlin.analysis.project.structure.builder.* import org.jetbrains.kotlin.analyzer.common.CommonPlatformAnalyzerServices import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreProjectEnvironment -import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM import org.jetbrains.kotlin.cli.jvm.config.javaSourceRoots import org.jetbrains.kotlin.cli.jvm.config.jvmClasspathRoots import org.jetbrains.kotlin.cli.jvm.config.jvmModularRoots @@ -67,7 +66,7 @@ internal fun getSourceFilePaths( val path = Paths.get(srcRoot) if (Files.isDirectory(path)) { // E.g., project/app/src - collectSourceFilePaths(path, this) + addAll(collectSourceFilePaths(path)) if (includeDirectoryRoot) { add(path) } @@ -80,19 +79,17 @@ internal fun getSourceFilePaths( } /** - * Collect source file path from the given [root] store them in [result]. + * Collect source file path from the given [root] * * E.g., for `project/app/src` as a [root], this will walk the file tree and * collect all `.kt`, `.kts`, and `.java` files under that folder. * * Note that this util gracefully skips [IOException] during file tree traversal. */ -private fun collectSourceFilePaths( - root: Path, - result: MutableSet -) { +internal fun collectSourceFilePaths(root: Path): List { // NB: [Files#walk] throws an exception if there is an issue during IO. // With [Files#walkFileTree] with a custom visitor, we can take control of exception handling. + val result = mutableListOf() Files.walkFileTree( root, object : SimpleFileVisitor() { @@ -125,6 +122,7 @@ private fun collectSourceFilePaths( } } ) + return result } internal inline fun getPsiFilesFromPaths( @@ -197,13 +195,7 @@ internal fun buildKtModuleProviderByCompilerConfiguration( addModuleDependencies(moduleName) - contentScope = TopDownAnalyzerFacadeForJVM.newModuleSearchScope(kotlinCoreProjectEnvironment.project, ordinaryFiles) - addSourceRoots( - getPsiFilesFromPaths( - kotlinCoreProjectEnvironment, - getSourceFilePaths(compilerConfig, includeDirectoryRoot = true) - ) - ) + addSourceRoots(compilerConfig.javaSourceRoots.map { Paths.get(it) }) }.apply(::addModule)