diff --git a/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/util/LibraryUtils.kt b/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/util/LibraryUtils.kt index 929010107c9..b4fbae5904f 100644 --- a/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/util/LibraryUtils.kt +++ b/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/util/LibraryUtils.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.analysis.api.impl.base.util +import com.intellij.openapi.vfs.StandardFileSystems import com.intellij.openapi.vfs.VfsUtilCore import com.intellij.openapi.vfs.VirtualFile import com.intellij.openapi.vfs.impl.jar.CoreJarFileSystem @@ -22,8 +23,23 @@ object LibraryUtils { jar: Path, jarFileSystem: CoreJarFileSystem = CoreJarFileSystem(), ): Collection { - val root = jarFileSystem.refreshAndFindFileByPath(jar.toAbsolutePath().toString() + JAR_SEPARATOR)!! + return jarFileSystem.refreshAndFindFileByPath(jar.toAbsolutePath().toString() + JAR_SEPARATOR) + ?.let { getAllVirtualFilesFromRoot(it) } ?: emptySet() + } + /** + * Get all [VirtualFile]s inside the given [dir] (of [Path]) + */ + fun getAllVirtualFilesFromDirectory( + dir: Path, + ): Collection { + val fs = StandardFileSystems.local() + return fs.findFileByPath(dir.toAbsolutePath().toString())?.let { getAllVirtualFilesFromRoot(it) } ?: return emptySet() + } + + private fun getAllVirtualFilesFromRoot( + root: VirtualFile + ): Collection { val files = mutableSetOf() VfsUtilCore.iterateChildrenRecursively( root, diff --git a/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/project/structure/impl/KtModuleByCompilerConfiguration.kt b/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/project/structure/impl/KtModuleByCompilerConfiguration.kt index b84358e2c84..18e512249ec 100644 --- a/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/project/structure/impl/KtModuleByCompilerConfiguration.kt +++ b/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/project/structure/impl/KtModuleByCompilerConfiguration.kt @@ -55,38 +55,53 @@ internal class KtSourceModuleByCompilerConfiguration( jarFileSystem: CoreJarFileSystem, ) : BaseKtModuleByCompilerConfiguration(compilerConfig, project), KtSourceModule { override val directRegularDependencies: List by lazy { - (compilerConfig.jvmModularRoots + compilerConfig.jvmClasspathRoots).map { - KtLibraryModuleByCompilerConfiguration(compilerConfig, project, it.toPath(), jarFileSystem) + val libraryRoots = compilerConfig.jvmModularRoots + compilerConfig.jvmClasspathRoots + val libraryRootsByType = libraryRoots.groupBy { it.isDirectory } + buildList { + libraryRootsByType[true]?.let { directories -> + directories.forEach { + // E.g., project/app/build/intermediates/javac/debug/classes + val root = it.toPath() + val virtualFilesProvider = { LibraryUtils.getAllVirtualFilesFromDirectory(root) } + add(KtLibraryModuleByCompilerConfiguration(compilerConfig, project, virtualFilesProvider, root)) + } + } + libraryRootsByType[false]?.let { jars -> + jars.forEach { + // E.g., project/libs/libA/a.jar + val root = it.toPath() + val virtualFilesProvider = { LibraryUtils.getAllVirtualFilesFromJar(root, jarFileSystem) } + add(KtLibraryModuleByCompilerConfiguration(compilerConfig, project, virtualFilesProvider, root)) + } + } } } - override val contentScope: GlobalSearchScope = + override val contentScope: GlobalSearchScope by lazy { TopDownAnalyzerFacadeForJVM.newModuleSearchScope(project, ktFiles) + } } internal class KtLibraryModuleByCompilerConfiguration( compilerConfig: CompilerConfiguration, project: Project, - private val jar: Path, - jarFileSystem: CoreJarFileSystem, + virtualFilesProvider: () -> Collection, + private val root: Path, ) : BaseKtModuleByCompilerConfiguration(compilerConfig, project), KtLibraryModule { override val directRegularDependencies: List get() = emptyList() - internal val virtualFiles: Collection by lazy { - LibraryUtils.getAllVirtualFilesFromJar(jar, jarFileSystem) - } - override val libraryName: String get() = moduleName override val librarySources: KtLibrarySourceModule? get() = null - override val contentScope: GlobalSearchScope = - GlobalSearchScope.filesScope(project, virtualFiles) + override val contentScope: GlobalSearchScope by lazy { + GlobalSearchScope.filesScope(project, virtualFilesProvider()) + } private val binaryRoots by lazy { - listOf(jar) + listOf(root) } override fun getBinaryRoots(): Collection = binaryRoots diff --git a/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/project/structure/impl/ProjectStructureProviderByCompilerConfiguration.kt b/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/project/structure/impl/ProjectStructureProviderByCompilerConfiguration.kt index 23ad2e4dbcd..528d33ba459 100644 --- a/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/project/structure/impl/ProjectStructureProviderByCompilerConfiguration.kt +++ b/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/project/structure/impl/ProjectStructureProviderByCompilerConfiguration.kt @@ -28,7 +28,7 @@ internal class ProjectStructureProviderByCompilerConfiguration( val path = Paths.get(srcRoot) if (Files.isDirectory(path)) { // E.g., project/app/src - Files.walk(Paths.get(srcRoot)) + Files.walk(path) .filter(Files::isRegularFile) .forEach { add(it.toString()) } } else { @@ -42,13 +42,12 @@ internal class ProjectStructureProviderByCompilerConfiguration( private val sourceModule = KtSourceModuleByCompilerConfiguration(compilerConfig, project, ktFiles, jarFileSystem) override fun getKtModuleForKtElement(element: PsiElement): KtModule { - val containingFilePath = element.containingFile.virtualFile.path - return if (containingFilePath in sourceFiles) { + val containingFile = element.containingFile.virtualFile + return if (containingFile.path in sourceFiles) { sourceModule } else { - sourceModule.directRegularDependencies.find { libModule -> - (libModule as KtLibraryModuleByCompilerConfiguration).virtualFiles.any { it.path == containingFilePath } - } ?: error("Can't find module for $containingFilePath") + sourceModule.directRegularDependencies.find { libModule -> containingFile in libModule.contentScope } + ?: error("Can't find module for ${containingFile.path}") } } }