[Commonizer] Process expect/actual cross-module dependencies in source-based tests
This commit is contained in:
+77
-3
@@ -7,6 +7,9 @@ package org.jetbrains.kotlin.descriptors.commonizer
|
|||||||
|
|
||||||
import com.intellij.openapi.Disposable
|
import com.intellij.openapi.Disposable
|
||||||
import com.intellij.testFramework.PlatformTestUtil.lowercaseFirstLetter
|
import com.intellij.testFramework.PlatformTestUtil.lowercaseFirstLetter
|
||||||
|
import org.jetbrains.kotlin.analyzer.ModuleInfo
|
||||||
|
import org.jetbrains.kotlin.analyzer.common.CommonDependenciesContainer
|
||||||
|
import org.jetbrains.kotlin.analyzer.common.CommonPlatformAnalyzerServices
|
||||||
import org.jetbrains.kotlin.analyzer.common.CommonResolverForModuleFactory
|
import org.jetbrains.kotlin.analyzer.common.CommonResolverForModuleFactory
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
|
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||||
@@ -14,14 +17,19 @@ import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
|||||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||||
import org.jetbrains.kotlin.config.languageVersionSettings
|
import org.jetbrains.kotlin.config.languageVersionSettings
|
||||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.PackageFragmentProvider
|
||||||
|
import org.jetbrains.kotlin.descriptors.commonizer.SourceModuleRoot.Companion.COMMON_TARGET_NAME
|
||||||
import org.jetbrains.kotlin.descriptors.commonizer.utils.assertCommonizationPerformed
|
import org.jetbrains.kotlin.descriptors.commonizer.utils.assertCommonizationPerformed
|
||||||
import org.jetbrains.kotlin.descriptors.commonizer.utils.assertIsDirectory
|
import org.jetbrains.kotlin.descriptors.commonizer.utils.assertIsDirectory
|
||||||
import org.jetbrains.kotlin.descriptors.commonizer.utils.assertModulesAreEqual
|
import org.jetbrains.kotlin.descriptors.commonizer.utils.assertModulesAreEqual
|
||||||
import org.jetbrains.kotlin.descriptors.commonizer.utils.assertValidModule
|
import org.jetbrains.kotlin.descriptors.commonizer.utils.assertValidModule
|
||||||
|
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.platform.CommonPlatforms
|
import org.jetbrains.kotlin.platform.CommonPlatforms
|
||||||
|
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.psi.KtPsiFactory
|
import org.jetbrains.kotlin.psi.KtPsiFactory
|
||||||
|
import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices
|
||||||
import org.jetbrains.kotlin.test.KotlinTestUtils.*
|
import org.jetbrains.kotlin.test.KotlinTestUtils.*
|
||||||
import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase
|
import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@@ -85,8 +93,6 @@ abstract class AbstractCommonizationFromSourcesTest : KtUsefulTestCase() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private const val COMMON_TARGET_NAME = "common"
|
|
||||||
|
|
||||||
private data class SourceModuleRoot(
|
private data class SourceModuleRoot(
|
||||||
val targetName: String,
|
val targetName: String,
|
||||||
val root: File
|
val root: File
|
||||||
@@ -100,6 +106,8 @@ private data class SourceModuleRoot(
|
|||||||
targetName = directory.name,
|
targetName = directory.name,
|
||||||
root = directory
|
root = directory
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const val COMMON_TARGET_NAME = "common"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,6 +153,7 @@ private class AnalyzedModule<T : Target>(
|
|||||||
fun <T : Target> create(
|
fun <T : Target> create(
|
||||||
target: T,
|
target: T,
|
||||||
sourceModuleRoot: SourceModuleRoot,
|
sourceModuleRoot: SourceModuleRoot,
|
||||||
|
commonSourceModuleRoot: SourceModuleRoot? = null,
|
||||||
parentDisposable: Disposable
|
parentDisposable: Disposable
|
||||||
): AnalyzedModule<T> {
|
): AnalyzedModule<T> {
|
||||||
val moduleName: String = sourceModuleRoot.root.parentFile.parentFile.name
|
val moduleName: String = sourceModuleRoot.root.parentFile.parentFile.name
|
||||||
@@ -155,6 +164,7 @@ private class AnalyzedModule<T : Target>(
|
|||||||
module = analyze(
|
module = analyze(
|
||||||
moduleName = moduleName,
|
moduleName = moduleName,
|
||||||
moduleRoot = sourceModuleRoot.root,
|
moduleRoot = sourceModuleRoot.root,
|
||||||
|
commonModuleRoot = commonSourceModuleRoot?.root,
|
||||||
parentDisposable = parentDisposable
|
parentDisposable = parentDisposable
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -163,6 +173,37 @@ private class AnalyzedModule<T : Target>(
|
|||||||
private fun analyze(
|
private fun analyze(
|
||||||
moduleName: String,
|
moduleName: String,
|
||||||
moduleRoot: File,
|
moduleRoot: File,
|
||||||
|
commonModuleRoot: File?,
|
||||||
|
parentDisposable: Disposable
|
||||||
|
): ModuleDescriptor {
|
||||||
|
val commonModule: ModuleDescriptor? = if (commonModuleRoot != null) {
|
||||||
|
analyzeModule(
|
||||||
|
moduleName = "common" + moduleName.capitalize(),
|
||||||
|
moduleRoot = commonModuleRoot,
|
||||||
|
dependencyContainer = null, // common module does not have any specific dependencies
|
||||||
|
parentDisposable = parentDisposable
|
||||||
|
)
|
||||||
|
} else null
|
||||||
|
|
||||||
|
val module: ModuleDescriptor = analyzeModule(
|
||||||
|
moduleName = moduleName,
|
||||||
|
moduleRoot = moduleRoot,
|
||||||
|
dependencyContainer = commonModule?.let(::CommonizedCommonDependenciesContainer), // platform module has dependencies to common module
|
||||||
|
parentDisposable = parentDisposable
|
||||||
|
)
|
||||||
|
|
||||||
|
if (commonModule != null) {
|
||||||
|
check(commonModule in module.expectedByModules)
|
||||||
|
check(commonModule in module.allDependencyModules)
|
||||||
|
}
|
||||||
|
|
||||||
|
return module
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun analyzeModule(
|
||||||
|
moduleName: String,
|
||||||
|
moduleRoot: File,
|
||||||
|
dependencyContainer: CommonDependenciesContainer?,
|
||||||
parentDisposable: Disposable
|
parentDisposable: Disposable
|
||||||
): ModuleDescriptor {
|
): ModuleDescriptor {
|
||||||
val configuration: CompilerConfiguration = newConfiguration()
|
val configuration: CompilerConfiguration = newConfiguration()
|
||||||
@@ -186,7 +227,8 @@ private class AnalyzedModule<T : Target>(
|
|||||||
moduleName = Name.special("<$moduleName>"),
|
moduleName = Name.special("<$moduleName>"),
|
||||||
dependOnBuiltIns = true,
|
dependOnBuiltIns = true,
|
||||||
languageVersionSettings = environment.configuration.languageVersionSettings,
|
languageVersionSettings = environment.configuration.languageVersionSettings,
|
||||||
targetPlatform = CommonPlatforms.defaultCommonPlatform
|
targetPlatform = CommonPlatforms.defaultCommonPlatform,
|
||||||
|
dependenciesContainer = dependencyContainer
|
||||||
) { content ->
|
) { content ->
|
||||||
environment.createPackagePartProvider(content.moduleContentScope)
|
environment.createPackagePartProvider(content.moduleContentScope)
|
||||||
}.moduleDescriptor
|
}.moduleDescriptor
|
||||||
@@ -224,6 +266,7 @@ private class AnalyzedModules(
|
|||||||
|
|
||||||
val commonizedPlatformModules: Map<InputTarget, AnalyzedModule<InputTarget>> = createInputTargetModules(
|
val commonizedPlatformModules: Map<InputTarget, AnalyzedModule<InputTarget>> = createInputTargetModules(
|
||||||
sourceModuleRoots = sourceModuleRoots.commonizedPlatformRoots,
|
sourceModuleRoots = sourceModuleRoots.commonizedPlatformRoots,
|
||||||
|
commonSourceModuleRoot = sourceModuleRoots.commonizedCommonRoot,
|
||||||
parentDisposable = parentDisposable
|
parentDisposable = parentDisposable
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -236,17 +279,48 @@ private class AnalyzedModules(
|
|||||||
|
|
||||||
private fun createInputTargetModules(
|
private fun createInputTargetModules(
|
||||||
sourceModuleRoots: Map<String, SourceModuleRoot>,
|
sourceModuleRoots: Map<String, SourceModuleRoot>,
|
||||||
|
commonSourceModuleRoot: SourceModuleRoot? = null,
|
||||||
parentDisposable: Disposable
|
parentDisposable: Disposable
|
||||||
): Map<InputTarget, AnalyzedModule<InputTarget>> = sourceModuleRoots.map { (targetName, sourceModuleRoot) ->
|
): Map<InputTarget, AnalyzedModule<InputTarget>> = sourceModuleRoots.map { (targetName, sourceModuleRoot) ->
|
||||||
AnalyzedModule.create(
|
AnalyzedModule.create(
|
||||||
target = InputTarget(targetName),
|
target = InputTarget(targetName),
|
||||||
sourceModuleRoot = sourceModuleRoot,
|
sourceModuleRoot = sourceModuleRoot,
|
||||||
|
commonSourceModuleRoot = commonSourceModuleRoot,
|
||||||
parentDisposable = parentDisposable
|
parentDisposable = parentDisposable
|
||||||
)
|
)
|
||||||
}.associateBy { it.target }
|
}.associateBy { it.target }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class CommonizedCommonDependenciesContainer(
|
||||||
|
private val commonModule: ModuleDescriptor
|
||||||
|
) : CommonDependenciesContainer {
|
||||||
|
private val commonModuleInfo = object : ModuleInfo {
|
||||||
|
override val name: Name get() = commonModule.name
|
||||||
|
|
||||||
|
override fun dependencies(): List<ModuleInfo> = listOf(this)
|
||||||
|
override fun dependencyOnBuiltIns(): ModuleInfo.DependencyOnBuiltIns = ModuleInfo.DependencyOnBuiltIns.LAST
|
||||||
|
|
||||||
|
override val platform: TargetPlatform get() = CommonPlatforms.defaultCommonPlatform
|
||||||
|
override val analyzerServices: PlatformDependentAnalyzerServices get() = CommonPlatformAnalyzerServices
|
||||||
|
}
|
||||||
|
|
||||||
|
override val moduleInfos: List<ModuleInfo> get() = listOf(commonModuleInfo)
|
||||||
|
|
||||||
|
override fun moduleDescriptorForModuleInfo(moduleInfo: ModuleInfo): ModuleDescriptor {
|
||||||
|
if (moduleInfo !== commonModuleInfo)
|
||||||
|
error("Unknown module info $moduleInfo")
|
||||||
|
|
||||||
|
return commonModule
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun registerDependencyForAllModules(moduleInfo: ModuleInfo, descriptorForModule: ModuleDescriptorImpl) = Unit
|
||||||
|
override fun packageFragmentProviderForModuleInfo(moduleInfo: ModuleInfo): PackageFragmentProvider? = null
|
||||||
|
|
||||||
|
override val friendModuleInfos: List<ModuleInfo> get() = emptyList()
|
||||||
|
override val refinesModuleInfos: List<ModuleInfo> get() = listOf(commonModuleInfo)
|
||||||
|
}
|
||||||
|
|
||||||
private fun Map<InputTarget, ModuleDescriptor>.toCommonizationParameters(): Parameters = Parameters().also {
|
private fun Map<InputTarget, ModuleDescriptor>.toCommonizationParameters(): Parameters = Parameters().also {
|
||||||
forEach { (target, moduleDescriptor) ->
|
forEach { (target, moduleDescriptor) ->
|
||||||
it.addTarget(
|
it.addTarget(
|
||||||
|
|||||||
+4
@@ -8,6 +8,8 @@ package org.jetbrains.kotlin.descriptors.commonizer.utils
|
|||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.commonizer.CommonizationPerformed
|
import org.jetbrains.kotlin.descriptors.commonizer.CommonizationPerformed
|
||||||
import org.jetbrains.kotlin.descriptors.commonizer.Result
|
import org.jetbrains.kotlin.descriptors.commonizer.Result
|
||||||
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||||
import org.jetbrains.kotlin.test.util.DescriptorValidator.*
|
import org.jetbrains.kotlin.test.util.DescriptorValidator.*
|
||||||
import org.jetbrains.kotlin.types.ErrorUtils
|
import org.jetbrains.kotlin.types.ErrorUtils
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@@ -41,6 +43,8 @@ fun assertModulesAreEqual(expected: ModuleDescriptor, actual: ModuleDescriptor,
|
|||||||
|
|
||||||
fun assertValidModule(module: ModuleDescriptor) = validate(
|
fun assertValidModule(module: ModuleDescriptor) = validate(
|
||||||
object : ValidationVisitor() {
|
object : ValidationVisitor() {
|
||||||
|
override fun validateScope(scopeOwner: DeclarationDescriptor?, scope: MemberScope, collector: DiagnosticCollector) = Unit
|
||||||
|
|
||||||
override fun visitModuleDeclaration(descriptor: ModuleDescriptor, collector: DiagnosticCollector): Boolean {
|
override fun visitModuleDeclaration(descriptor: ModuleDescriptor, collector: DiagnosticCollector): Boolean {
|
||||||
assertValid(descriptor)
|
assertValid(descriptor)
|
||||||
return super.visitModuleDeclaration(descriptor, collector)
|
return super.visitModuleDeclaration(descriptor, collector)
|
||||||
|
|||||||
Reference in New Issue
Block a user