[LL FIR] KT-55329 Support transitive dependsOn dependencies in LL FIR
- In contrast to other kinds of dependencies, `dependsOn` dependencies must be followed transitively. - Add `transitiveDependsOnDependencies` to `KtModule`. These dependencies are calculated lazily with a topological sort. They are added to the dependency provider when it's built in `LLFirSessionFactory`. ^KT-55329 fixed
This commit is contained in:
committed by
teamcity
parent
1803bd36cc
commit
d6cb75ca91
+1
-1
@@ -17,7 +17,6 @@ import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken
|
|||||||
import org.jetbrains.kotlin.analysis.api.symbols.KtBackingFieldSymbol
|
import org.jetbrains.kotlin.analysis.api.symbols.KtBackingFieldSymbol
|
||||||
import org.jetbrains.kotlin.analysis.api.symbols.KtDeclarationSymbol
|
import org.jetbrains.kotlin.analysis.api.symbols.KtDeclarationSymbol
|
||||||
import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol
|
import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol
|
||||||
import org.jetbrains.kotlin.analysis.api.symbols.KtValueParameterSymbol
|
|
||||||
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolKind
|
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolKind
|
||||||
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolWithKind
|
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolWithKind
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.KtLibraryModule
|
import org.jetbrains.kotlin.analysis.project.structure.KtLibraryModule
|
||||||
@@ -72,6 +71,7 @@ internal class KtFe10SymbolContainingDeclarationProvider(
|
|||||||
override fun getBinaryRoots(): Collection<Path> = listOf(libraryPath)
|
override fun getBinaryRoots(): Collection<Path> = listOf(libraryPath)
|
||||||
override val directRegularDependencies: List<KtModule> = emptyList()
|
override val directRegularDependencies: List<KtModule> = emptyList()
|
||||||
override val directDependsOnDependencies: List<KtModule> = emptyList()
|
override val directDependsOnDependencies: List<KtModule> = emptyList()
|
||||||
|
override val transitiveDependsOnDependencies: List<KtModule> = emptyList()
|
||||||
override val directFriendDependencies: List<KtModule> = emptyList()
|
override val directFriendDependencies: List<KtModule> = emptyList()
|
||||||
override val contentScope: GlobalSearchScope = ProjectScope.getLibrariesScope(project)
|
override val contentScope: GlobalSearchScope = ProjectScope.getLibrariesScope(project)
|
||||||
override val platform: TargetPlatform
|
override val platform: TargetPlatform
|
||||||
|
|||||||
+2
@@ -10,6 +10,7 @@ import com.intellij.psi.search.GlobalSearchScope
|
|||||||
import org.jetbrains.kotlin.analysis.project.structure.KtLibraryModule
|
import org.jetbrains.kotlin.analysis.project.structure.KtLibraryModule
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.KtLibrarySourceModule
|
import org.jetbrains.kotlin.analysis.project.structure.KtLibrarySourceModule
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
||||||
|
import org.jetbrains.kotlin.analysis.project.structure.computeTransitiveDependsOnDependencies
|
||||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||||
import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices
|
import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
@@ -25,6 +26,7 @@ internal class KtLibraryModuleImpl(
|
|||||||
override val libraryName: String,
|
override val libraryName: String,
|
||||||
override val librarySources: KtLibrarySourceModule?,
|
override val librarySources: KtLibrarySourceModule?,
|
||||||
) : KtLibraryModule, KtModuleWithPlatform {
|
) : KtLibraryModule, KtModuleWithPlatform {
|
||||||
|
override val transitiveDependsOnDependencies: List<KtModule> by lazy { computeTransitiveDependsOnDependencies(directDependsOnDependencies) }
|
||||||
override val analyzerServices: PlatformDependentAnalyzerServices = super.analyzerServices
|
override val analyzerServices: PlatformDependentAnalyzerServices = super.analyzerServices
|
||||||
|
|
||||||
override fun getBinaryRoots(): Collection<Path> = binaryRoots
|
override fun getBinaryRoots(): Collection<Path> = binaryRoots
|
||||||
|
|||||||
+2
@@ -10,6 +10,7 @@ import com.intellij.psi.search.GlobalSearchScope
|
|||||||
import org.jetbrains.kotlin.analysis.project.structure.KtLibraryModule
|
import org.jetbrains.kotlin.analysis.project.structure.KtLibraryModule
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.KtLibrarySourceModule
|
import org.jetbrains.kotlin.analysis.project.structure.KtLibrarySourceModule
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
||||||
|
import org.jetbrains.kotlin.analysis.project.structure.computeTransitiveDependsOnDependencies
|
||||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||||
import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices
|
import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices
|
||||||
|
|
||||||
@@ -23,5 +24,6 @@ internal class KtLibrarySourceModuleImpl(
|
|||||||
override val libraryName: String,
|
override val libraryName: String,
|
||||||
override val binaryLibrary: KtLibraryModule,
|
override val binaryLibrary: KtLibraryModule,
|
||||||
) : KtLibrarySourceModule, KtModuleWithPlatform {
|
) : KtLibrarySourceModule, KtModuleWithPlatform {
|
||||||
|
override val transitiveDependsOnDependencies: List<KtModule> by lazy { computeTransitiveDependsOnDependencies(directDependsOnDependencies) }
|
||||||
override val analyzerServices: PlatformDependentAnalyzerServices = super.analyzerServices
|
override val analyzerServices: PlatformDependentAnalyzerServices = super.analyzerServices
|
||||||
}
|
}
|
||||||
+2
@@ -10,6 +10,7 @@ import com.intellij.psi.PsiFile
|
|||||||
import com.intellij.psi.search.GlobalSearchScope
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.KtNotUnderContentRootModule
|
import org.jetbrains.kotlin.analysis.project.structure.KtNotUnderContentRootModule
|
||||||
|
import org.jetbrains.kotlin.analysis.project.structure.computeTransitiveDependsOnDependencies
|
||||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||||
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
|
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
|
||||||
import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices
|
import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices
|
||||||
@@ -24,6 +25,7 @@ internal class KtNotUnderContentRootModuleImpl(
|
|||||||
override val moduleDescription: String,
|
override val moduleDescription: String,
|
||||||
override val project: Project,
|
override val project: Project,
|
||||||
) : KtNotUnderContentRootModule, KtModuleWithPlatform {
|
) : KtNotUnderContentRootModule, KtModuleWithPlatform {
|
||||||
|
override val transitiveDependsOnDependencies: List<KtModule> by lazy { computeTransitiveDependsOnDependencies(directDependsOnDependencies) }
|
||||||
override val analyzerServices: PlatformDependentAnalyzerServices = super.analyzerServices
|
override val analyzerServices: PlatformDependentAnalyzerServices = super.analyzerServices
|
||||||
|
|
||||||
override val contentScope: GlobalSearchScope =
|
override val contentScope: GlobalSearchScope =
|
||||||
|
|||||||
+2
@@ -9,6 +9,7 @@ import com.intellij.openapi.project.Project
|
|||||||
import com.intellij.psi.search.GlobalSearchScope
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.KtSdkModule
|
import org.jetbrains.kotlin.analysis.project.structure.KtSdkModule
|
||||||
|
import org.jetbrains.kotlin.analysis.project.structure.computeTransitiveDependsOnDependencies
|
||||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||||
import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices
|
import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
@@ -23,6 +24,7 @@ internal class KtSdkModuleImpl(
|
|||||||
private val binaryRoots: Collection<Path>,
|
private val binaryRoots: Collection<Path>,
|
||||||
override val sdkName: String,
|
override val sdkName: String,
|
||||||
) : KtSdkModule, KtModuleWithPlatform {
|
) : KtSdkModule, KtModuleWithPlatform {
|
||||||
|
override val transitiveDependsOnDependencies: List<KtModule> by lazy { computeTransitiveDependsOnDependencies(directDependsOnDependencies) }
|
||||||
override val analyzerServices: PlatformDependentAnalyzerServices = super.analyzerServices
|
override val analyzerServices: PlatformDependentAnalyzerServices = super.analyzerServices
|
||||||
|
|
||||||
override fun getBinaryRoots(): Collection<Path> = binaryRoots
|
override fun getBinaryRoots(): Collection<Path> = binaryRoots
|
||||||
|
|||||||
+2
@@ -10,6 +10,7 @@ import com.intellij.psi.PsiFileSystemItem
|
|||||||
import com.intellij.psi.search.GlobalSearchScope
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule
|
import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule
|
||||||
|
import org.jetbrains.kotlin.analysis.project.structure.computeTransitiveDependsOnDependencies
|
||||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||||
import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices
|
import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices
|
||||||
@@ -25,5 +26,6 @@ internal class KtSourceModuleImpl(
|
|||||||
override val languageVersionSettings: LanguageVersionSettings,
|
override val languageVersionSettings: LanguageVersionSettings,
|
||||||
internal val sourceRoots: List<PsiFileSystemItem>,
|
internal val sourceRoots: List<PsiFileSystemItem>,
|
||||||
) : KtSourceModule, KtModuleWithPlatform {
|
) : KtSourceModule, KtModuleWithPlatform {
|
||||||
|
override val transitiveDependsOnDependencies: List<KtModule> by lazy { computeTransitiveDependsOnDependencies(directDependsOnDependencies) }
|
||||||
override val analyzerServices: PlatformDependentAnalyzerServices = super.analyzerServices
|
override val analyzerServices: PlatformDependentAnalyzerServices = super.analyzerServices
|
||||||
}
|
}
|
||||||
+4
-4
@@ -9,10 +9,7 @@ import com.intellij.openapi.project.Project
|
|||||||
import com.intellij.psi.PsiFile
|
import com.intellij.psi.PsiFile
|
||||||
import com.intellij.psi.search.GlobalSearchScope
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
import com.intellij.psi.search.ProjectScope
|
import com.intellij.psi.search.ProjectScope
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.KtLibraryModule
|
import org.jetbrains.kotlin.analysis.project.structure.*
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.KtLibrarySourceModule
|
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule
|
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM
|
import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM
|
||||||
import org.jetbrains.kotlin.cli.jvm.config.jvmClasspathRoots
|
import org.jetbrains.kotlin.cli.jvm.config.jvmClasspathRoots
|
||||||
import org.jetbrains.kotlin.cli.jvm.config.jvmModularRoots
|
import org.jetbrains.kotlin.cli.jvm.config.jvmModularRoots
|
||||||
@@ -60,6 +57,8 @@ abstract class KtModuleByCompilerConfiguration(
|
|||||||
.map { moduleProvider.getModule(it.moduleName) }
|
.map { moduleProvider.getModule(it.moduleName) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val transitiveDependsOnDependencies: List<KtModule> by lazy { computeTransitiveDependsOnDependencies(directDependsOnDependencies) }
|
||||||
|
|
||||||
val directFriendDependencies: List<KtModule> by lazy(LazyThreadSafetyMode.PUBLICATION) {
|
val directFriendDependencies: List<KtModule> by lazy(LazyThreadSafetyMode.PUBLICATION) {
|
||||||
buildList {
|
buildList {
|
||||||
testModule.friendDependencies.mapTo(this) { moduleProvider.getModule(it.moduleName) }
|
testModule.friendDependencies.mapTo(this) { moduleProvider.getModule(it.moduleName) }
|
||||||
@@ -140,6 +139,7 @@ private class LibraryByRoots(
|
|||||||
override val libraryName: String get() = "Test Library"
|
override val libraryName: String get() = "Test Library"
|
||||||
override val directRegularDependencies: List<KtModule> get() = emptyList()
|
override val directRegularDependencies: List<KtModule> get() = emptyList()
|
||||||
override val directDependsOnDependencies: List<KtModule> get() = emptyList()
|
override val directDependsOnDependencies: List<KtModule> get() = emptyList()
|
||||||
|
override val transitiveDependsOnDependencies: List<KtModule> get() = emptyList()
|
||||||
override val directFriendDependencies: List<KtModule> get() = emptyList()
|
override val directFriendDependencies: List<KtModule> get() = emptyList()
|
||||||
override val contentScope: GlobalSearchScope get() = ProjectScope.getLibrariesScope(project)
|
override val contentScope: GlobalSearchScope get() = ProjectScope.getLibrariesScope(project)
|
||||||
override val platform: TargetPlatform get() = module.platform
|
override val platform: TargetPlatform get() = module.platform
|
||||||
|
|||||||
+15
-8
@@ -14,10 +14,17 @@ import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices
|
|||||||
import org.jetbrains.kotlin.test.getAnalyzerServices
|
import org.jetbrains.kotlin.test.getAnalyzerServices
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
|
|
||||||
interface KtModuleWithModifiableDependencies {
|
abstract class KtModuleWithModifiableDependencies {
|
||||||
val directRegularDependencies: MutableList<KtModule>
|
abstract val directRegularDependencies: MutableList<KtModule>
|
||||||
val directDependsOnDependencies: MutableList<KtModule>
|
abstract val directDependsOnDependencies: MutableList<KtModule>
|
||||||
val directFriendDependencies: MutableList<KtModule>
|
abstract val directFriendDependencies: MutableList<KtModule>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When dependencies are modifiable, transitive `dependsOn` dependencies must be recomputed each time as [directDependsOnDependencies]
|
||||||
|
* may have been mutated.
|
||||||
|
*/
|
||||||
|
val transitiveDependsOnDependencies: List<KtModule>
|
||||||
|
get() = computeTransitiveDependsOnDependencies(directDependsOnDependencies)
|
||||||
}
|
}
|
||||||
|
|
||||||
class KtSourceModuleImpl(
|
class KtSourceModuleImpl(
|
||||||
@@ -26,7 +33,7 @@ class KtSourceModuleImpl(
|
|||||||
override val languageVersionSettings: LanguageVersionSettings,
|
override val languageVersionSettings: LanguageVersionSettings,
|
||||||
override val project: Project,
|
override val project: Project,
|
||||||
override val contentScope: GlobalSearchScope,
|
override val contentScope: GlobalSearchScope,
|
||||||
) : KtSourceModule, KtModuleWithModifiableDependencies {
|
) : KtModuleWithModifiableDependencies(), KtSourceModule {
|
||||||
override val analyzerServices: PlatformDependentAnalyzerServices get() = platform.getAnalyzerServices()
|
override val analyzerServices: PlatformDependentAnalyzerServices get() = platform.getAnalyzerServices()
|
||||||
|
|
||||||
override val directRegularDependencies: MutableList<KtModule> = mutableListOf()
|
override val directRegularDependencies: MutableList<KtModule> = mutableListOf()
|
||||||
@@ -40,7 +47,7 @@ class KtJdkModuleImpl(
|
|||||||
override val contentScope: GlobalSearchScope,
|
override val contentScope: GlobalSearchScope,
|
||||||
override val project: Project,
|
override val project: Project,
|
||||||
private val binaryRoots: Collection<Path>,
|
private val binaryRoots: Collection<Path>,
|
||||||
) : KtSdkModule, KtModuleWithModifiableDependencies {
|
) : KtModuleWithModifiableDependencies(), KtSdkModule {
|
||||||
override val analyzerServices: PlatformDependentAnalyzerServices
|
override val analyzerServices: PlatformDependentAnalyzerServices
|
||||||
get() = platform.getAnalyzerServices()
|
get() = platform.getAnalyzerServices()
|
||||||
|
|
||||||
@@ -58,7 +65,7 @@ class KtLibraryModuleImpl(
|
|||||||
override val project: Project,
|
override val project: Project,
|
||||||
private val binaryRoots: Collection<Path>,
|
private val binaryRoots: Collection<Path>,
|
||||||
override var librarySources: KtLibrarySourceModule?,
|
override var librarySources: KtLibrarySourceModule?,
|
||||||
) : KtLibraryModule, KtModuleWithModifiableDependencies {
|
) : KtModuleWithModifiableDependencies(), KtLibraryModule {
|
||||||
override val analyzerServices: PlatformDependentAnalyzerServices get() = platform.getAnalyzerServices()
|
override val analyzerServices: PlatformDependentAnalyzerServices get() = platform.getAnalyzerServices()
|
||||||
override fun getBinaryRoots(): Collection<Path> = binaryRoots
|
override fun getBinaryRoots(): Collection<Path> = binaryRoots
|
||||||
|
|
||||||
@@ -73,7 +80,7 @@ class KtLibrarySourceModuleImpl(
|
|||||||
override val contentScope: GlobalSearchScope,
|
override val contentScope: GlobalSearchScope,
|
||||||
override val project: Project,
|
override val project: Project,
|
||||||
override val binaryLibrary: KtLibraryModule,
|
override val binaryLibrary: KtLibraryModule,
|
||||||
) : KtLibrarySourceModule, KtModuleWithModifiableDependencies {
|
) : KtModuleWithModifiableDependencies(), KtLibrarySourceModule {
|
||||||
override val analyzerServices: PlatformDependentAnalyzerServices get() = platform.getAnalyzerServices()
|
override val analyzerServices: PlatformDependentAnalyzerServices get() = platform.getAnalyzerServices()
|
||||||
|
|
||||||
override val directRegularDependencies: MutableList<KtModule> = mutableListOf()
|
override val directRegularDependencies: MutableList<KtModule> = mutableListOf()
|
||||||
|
|||||||
+27
-17
@@ -113,26 +113,36 @@ internal object LLFirSessionFactory {
|
|||||||
register(FirSwitchableExtensionDeclarationsSymbolProvider::class, it)
|
register(FirSwitchableExtensionDeclarationsSymbolProvider::class, it)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getOrCreateSessionForDependency(dependency: KtModule): LLFirSession? = when (dependency) {
|
||||||
|
is KtBuiltinsModule -> null // build in is already added
|
||||||
|
is KtBinaryModule -> LLFirLibrarySessionFactory.getInstance(project).getLibrarySession(dependency, sessionsCache)
|
||||||
|
is KtSourceModule -> {
|
||||||
|
createSourcesSession(
|
||||||
|
project,
|
||||||
|
dependency,
|
||||||
|
globalResolveComponents,
|
||||||
|
sessionInvalidator,
|
||||||
|
sessionsCache,
|
||||||
|
librariesSessionFactory = librariesSessionFactory,
|
||||||
|
configureSession = configureSession,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
is KtNotUnderContentRootModule -> error("Module $module cannot depend on ${dependency::class}: $dependency")
|
||||||
|
is KtLibrarySourceModule -> error("Module $module cannot depend on ${dependency::class}: $dependency")
|
||||||
|
}
|
||||||
|
|
||||||
val dependencyProvider = LLFirDependentModuleProvidersBySessions(this) {
|
val dependencyProvider = LLFirDependentModuleProvidersBySessions(this) {
|
||||||
module.directRegularDependencies.mapNotNullTo(this) { dependency ->
|
module.directRegularDependencies.mapNotNullTo(this, ::getOrCreateSessionForDependency)
|
||||||
when (dependency) {
|
|
||||||
is KtBuiltinsModule -> null // build in is already added
|
// The dependency provider needs to have access to all direct and indirect `dependsOn` dependencies, as `dependsOn`
|
||||||
is KtBinaryModule -> LLFirLibrarySessionFactory.getInstance(project).getLibrarySession(dependency, sessionsCache)
|
// dependencies are transitive.
|
||||||
is KtSourceModule -> {
|
val directRegularDependenciesSet = module.directRegularDependencies.toSet()
|
||||||
createSourcesSession(
|
module.transitiveDependsOnDependencies.forEach { dependency ->
|
||||||
project,
|
if (dependency !in directRegularDependenciesSet) {
|
||||||
dependency,
|
getOrCreateSessionForDependency(dependency)?.let(::add)
|
||||||
globalResolveComponents,
|
|
||||||
sessionInvalidator,
|
|
||||||
sessionsCache,
|
|
||||||
librariesSessionFactory = librariesSessionFactory,
|
|
||||||
configureSession = configureSession,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
is KtNotUnderContentRootModule -> error("Module $module cannot depend on ${dependency::class}: $dependency")
|
|
||||||
is KtLibrarySourceModule -> error("Module $module cannot depend on ${dependency::class}: $dependency")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
add(builtinsSession)
|
add(builtinsSession)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
@@ -79,6 +79,9 @@ private class KtNotUnderContentRootModuleForTest(
|
|||||||
override val directDependsOnDependencies: List<KtModule>
|
override val directDependsOnDependencies: List<KtModule>
|
||||||
get() = emptyList()
|
get() = emptyList()
|
||||||
|
|
||||||
|
override val transitiveDependsOnDependencies: List<KtModule>
|
||||||
|
get() = emptyList()
|
||||||
|
|
||||||
override val directFriendDependencies: List<KtModule>
|
override val directFriendDependencies: List<KtModule>
|
||||||
get() = emptyList()
|
get() = emptyList()
|
||||||
|
|
||||||
|
|||||||
+12
-3
@@ -25,7 +25,7 @@ public sealed interface KtModule {
|
|||||||
* A list of Regular dependencies. Regular dependency allows the current module to see symbols from the dependent module. In the case
|
* A list of Regular dependencies. Regular dependency allows the current module to see symbols from the dependent module. In the case
|
||||||
* of a source set, it can be either the source set it depends on, a library, or an SDK.
|
* of a source set, it can be either the source set it depends on, a library, or an SDK.
|
||||||
*
|
*
|
||||||
* The dependencies list is non-transitive and should not include the current module.
|
* The dependencies list is non-transitive and does not include the current module.
|
||||||
*/
|
*/
|
||||||
public val directRegularDependencies: List<KtModule>
|
public val directRegularDependencies: List<KtModule>
|
||||||
|
|
||||||
@@ -35,14 +35,22 @@ public sealed interface KtModule {
|
|||||||
* A `dependsOn` dependency expresses that the current module can provide `actual` declarations for `expect` declarations from the
|
* A `dependsOn` dependency expresses that the current module can provide `actual` declarations for `expect` declarations from the
|
||||||
* dependent module, as well as see internal symbols of the dependent module.
|
* dependent module, as well as see internal symbols of the dependent module.
|
||||||
*
|
*
|
||||||
* `dependsOn` dependencies are transitive, but the list is not a transitive closure. The list should not include the current module.
|
* `dependsOn` dependencies are transitive, but the list is not a transitive closure. The list does not include the current module.
|
||||||
*/
|
*/
|
||||||
public val directDependsOnDependencies: List<KtModule>
|
public val directDependsOnDependencies: List<KtModule>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A list of [directDependsOnDependencies] and all of their parents (directly and indirectly), sorted topologically with the nearest
|
||||||
|
* dependencies first in the list. The list does not include the current module.
|
||||||
|
*
|
||||||
|
* @see computeTransitiveDependsOnDependencies
|
||||||
|
*/
|
||||||
|
public val transitiveDependsOnDependencies: List<KtModule>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A list of Friend dependencies. Friend dependencies express that the current module may see internal symbols of the dependent module.
|
* A list of Friend dependencies. Friend dependencies express that the current module may see internal symbols of the dependent module.
|
||||||
*
|
*
|
||||||
* The dependencies list is non-transitive and should not include the current module.
|
* The dependencies list is non-transitive and does not include the current module.
|
||||||
*/
|
*/
|
||||||
public val directFriendDependencies: List<KtModule>
|
public val directFriendDependencies: List<KtModule>
|
||||||
|
|
||||||
@@ -159,6 +167,7 @@ public class KtBuiltinsModule(
|
|||||||
) : KtBinaryModule {
|
) : KtBinaryModule {
|
||||||
override val directRegularDependencies: List<KtModule> get() = emptyList()
|
override val directRegularDependencies: List<KtModule> get() = emptyList()
|
||||||
override val directDependsOnDependencies: List<KtModule> get() = emptyList()
|
override val directDependsOnDependencies: List<KtModule> get() = emptyList()
|
||||||
|
override val transitiveDependsOnDependencies: List<KtModule> get() = emptyList()
|
||||||
override val directFriendDependencies: List<KtModule> get() = emptyList()
|
override val directFriendDependencies: List<KtModule> get() = emptyList()
|
||||||
override val contentScope: GlobalSearchScope get() = GlobalSearchScope.EMPTY_SCOPE
|
override val contentScope: GlobalSearchScope get() = GlobalSearchScope.EMPTY_SCOPE
|
||||||
override fun getBinaryRoots(): Collection<Path> = emptyList()
|
override fun getBinaryRoots(): Collection<Path> = emptyList()
|
||||||
|
|||||||
+13
-1
@@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.analysis.project.structure
|
package org.jetbrains.kotlin.analysis.project.structure
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.utils.topologicalSort
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A list of all modules that the current module can depend on with regular dependency.
|
* A list of all modules that the current module can depend on with regular dependency.
|
||||||
*
|
*
|
||||||
@@ -51,4 +53,14 @@ public fun KtModule.allDirectDependencies(): Sequence<KtModule> =
|
|||||||
* @see KtModule.directFriendDependencies
|
* @see KtModule.directFriendDependencies
|
||||||
*/
|
*/
|
||||||
public inline fun <reified M : KtModule> KtModule.allDirectDependenciesOfType(): Sequence<M> =
|
public inline fun <reified M : KtModule> KtModule.allDirectDependenciesOfType(): Sequence<M> =
|
||||||
allDirectDependencies().filterIsInstance<M>()
|
allDirectDependencies().filterIsInstance<M>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes the transitive `dependsOn` dependencies of [directDependsOnDependencies]. [computeTransitiveDependsOnDependencies] is the
|
||||||
|
* default computation strategy to provide [KtModule.transitiveDependsOnDependencies].
|
||||||
|
*
|
||||||
|
* The algorithm is a depth-first search-based topological sort. `dependsOn` dependencies cannot be cyclical and thus form a DAG, which
|
||||||
|
* allows the application of a topological sort.
|
||||||
|
*/
|
||||||
|
public fun computeTransitiveDependsOnDependencies(directDependsOnDependencies: List<KtModule>): List<KtModule> =
|
||||||
|
topologicalSort(directDependsOnDependencies) { this.directDependsOnDependencies }
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
// FIR_IDENTICAL
|
// FIR_IDENTICAL
|
||||||
// FIR_IDE_IGNORE
|
|
||||||
|
|
||||||
// MODULE: common
|
// MODULE: common
|
||||||
// TARGET_PLATFORM: Common
|
// TARGET_PLATFORM: Common
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
// FIR_IDENTICAL
|
// FIR_IDENTICAL
|
||||||
// FIR_IDE_IGNORE
|
|
||||||
// !LANGUAGE: +MultiPlatformProjects
|
// !LANGUAGE: +MultiPlatformProjects
|
||||||
// TARGET_BACKEND: JVM
|
// TARGET_BACKEND: JVM
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* 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.utils
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sorts [nodes] topologically collecting direct edges via [dependencies]. [nodes] and [dependencies] must form a directed, acyclic graph.
|
||||||
|
* [topologicalSort] will throw an [IllegalStateException] if it encounters a cycle.
|
||||||
|
*
|
||||||
|
* The algorithm is based on depth-first search, starting in order from each node in [nodes]. Kahn's algorithm is harder to apply to the
|
||||||
|
* ad-hoc dependency structure because it's not easily apparent whether a node has no other incoming edges.
|
||||||
|
*
|
||||||
|
* For example, consider the following structure: `C -> A, C -> B, B -> A`. The resulting order should be `[C, B, A]`. However, `A` is
|
||||||
|
* first in the list of dependencies of `C`. Without a way to find the incoming edge from `B` to `A` while processing `C -> A`, a naive
|
||||||
|
* implementation of Kahn's algorithm might order `A` before `B`.
|
||||||
|
*/
|
||||||
|
fun <A> topologicalSort(nodes: Iterable<A>, dependencies: A.() -> Iterable<A>): List<A> {
|
||||||
|
val visiting = mutableSetOf<A>()
|
||||||
|
val visited = mutableSetOf<A>()
|
||||||
|
|
||||||
|
fun visit(node: A) {
|
||||||
|
if (node in visited) return
|
||||||
|
if (node in visiting) throw IllegalStateException("Cannot compute a topological sort: The node $node is in a cycle.")
|
||||||
|
|
||||||
|
// Keeping track of the nodes that are being visited allows the algorithm to throw an exception in case of a cycle. The input should
|
||||||
|
// never be cyclic, but this approach gives some additional safety in case of bugs.
|
||||||
|
visiting.add(node)
|
||||||
|
node.dependencies().forEach(::visit)
|
||||||
|
visiting.remove(node)
|
||||||
|
|
||||||
|
visited.add(node)
|
||||||
|
}
|
||||||
|
|
||||||
|
nodes.forEach(::visit)
|
||||||
|
|
||||||
|
// The paper algorithm inserts nodes at the head of the result list. Because our `visited` set remembers elements in their order of
|
||||||
|
// insertion, the result needs to be reversed.
|
||||||
|
return visited.toMutableList().apply { reverse() }
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user