[Test] Support friend modules in new test infrastructure

This commit is contained in:
Dmitriy Novozhilov
2020-12-28 15:32:12 +03:00
committed by TeamCityServer
parent 7e92fb8eb9
commit 065255adbe
5 changed files with 60 additions and 15 deletions
@@ -91,11 +91,13 @@ object TopDownAnalyzerFacadeForJVM {
declarationProviderFactory: (StorageManager, Collection<KtFile>) -> DeclarationProviderFactory = ::FileBasedDeclarationProviderFactory,
sourceModuleSearchScope: GlobalSearchScope = newModuleSearchScope(project, files),
klibList: List<KotlinLibrary> = emptyList(),
explicitModuleDependencyList: List<ModuleDescriptorImpl> = emptyList()
explicitModuleDependencyList: List<ModuleDescriptorImpl> = emptyList(),
explicitModuleFriendsList: List<ModuleDescriptorImpl> = emptyList()
): AnalysisResult {
val container = createContainer(
project, files, trace, configuration, packagePartProvider, declarationProviderFactory, CompilerEnvironment,
sourceModuleSearchScope, klibList, explicitModuleDependencyList = explicitModuleDependencyList
sourceModuleSearchScope, klibList, explicitModuleDependencyList = explicitModuleDependencyList,
explicitModuleFriendsList = explicitModuleFriendsList
)
val module = container.get<ModuleDescriptor>()
@@ -140,7 +142,8 @@ object TopDownAnalyzerFacadeForJVM {
sourceModuleSearchScope: GlobalSearchScope = newModuleSearchScope(project, files),
klibList: List<KotlinLibrary> = emptyList(),
implicitsResolutionFilter: ImplicitsExtensionsResolutionFilter? = null,
explicitModuleDependencyList: List<ModuleDescriptorImpl> = emptyList()
explicitModuleDependencyList: List<ModuleDescriptorImpl> = emptyList(),
explicitModuleFriendsList: List<ModuleDescriptorImpl> = emptyList()
): ComponentProvider {
val jvmTarget = configuration.get(JVMConfigurationKeys.JVM_TARGET, JvmTarget.DEFAULT)
val languageVersionSettings = configuration.languageVersionSettings
@@ -263,9 +266,15 @@ object TopDownAnalyzerFacadeForJVM {
@Suppress("UNCHECKED_CAST")
addAll(explicitModuleDependencyList)
}
val friends = buildSet {
if (dependencyModule != null) {
add(dependencyModule)
}
addAll(explicitModuleFriendsList)
}
module.setDependencies(
dependencies,
if (dependencyModule != null) setOf(dependencyModule) else emptySet()
friends
)
module.initialize(
CompositePackageFragmentProvider(
@@ -18,6 +18,7 @@ data class TestModule(
val frontendKind: FrontendKind<*>,
val files: List<TestFile>,
val dependencies: List<DependencyDescription>,
val friends: List<DependencyDescription>,
val directives: RegisteredDirectives,
val languageVersionSettings: LanguageVersionSettings
) {
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.js.analyze.TopDownAnalyzerFacadeForJS
import org.jetbrains.kotlin.js.config.JsConfig
import org.jetbrains.kotlin.load.java.lazy.SingleModuleClassResolver
import org.jetbrains.kotlin.load.kotlin.ModuleVisibilityManager
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.native.FakeTopDownAnalyzerFacadeForNative
import org.jetbrains.kotlin.platform.isCommon
@@ -81,6 +82,10 @@ class ClassicFrontendFacade(
moduleDescriptorProvider.getModuleDescriptor(testModule)
}
val friendDescriptors = module.friends.filter { it.kind == DependencyKind.Source }.map {
moduleDescriptorProvider.getModuleDescriptor(dependencyProvider.getTestModule(it.moduleName))
}
var hasCommonModules = false
sourceDependencies.forEach {
val dependencyModule = dependencyProvider.getTestModule(it.moduleName)
@@ -104,6 +109,7 @@ class ClassicFrontendFacade(
packagePartProviderFactory,
ktFiles,
dependentDescriptors,
friendDescriptors,
hasCommonModules
)
moduleDescriptorProvider.replaceModuleDescriptorForModule(module, analysisResult.moduleDescriptor)
@@ -135,6 +141,7 @@ class ClassicFrontendFacade(
packagePartProviderFactory: (GlobalSearchScope) -> JvmPackagePartProvider,
files: List<KtFile>,
dependentDescriptors: List<ModuleDescriptorImpl>,
friendsDescriptors: List<ModuleDescriptorImpl>,
hasCommonModules: Boolean
): AnalysisResult {
val targetPlatform = module.targetPlatform
@@ -146,6 +153,7 @@ class ClassicFrontendFacade(
packagePartProviderFactory,
files,
dependentDescriptors,
friendsDescriptors,
hasCommonModules
)
targetPlatform.isJs() -> performJsModuleResolve(project, configuration, files, dependentDescriptors)
@@ -163,8 +171,12 @@ class ClassicFrontendFacade(
packagePartProviderFactory: (GlobalSearchScope) -> JvmPackagePartProvider,
files: List<KtFile>,
dependentDescriptors: List<ModuleDescriptorImpl>,
friendsDescriptors: List<ModuleDescriptorImpl>,
hasCommonModules: Boolean
): AnalysisResult {
val moduleVisibilityManager = ModuleVisibilityManager.SERVICE.getInstance(project)
configuration.getList(JVMConfigurationKeys.FRIEND_PATHS).forEach { moduleVisibilityManager.addFriendPath(it) }
val moduleTrace = NoScopeRecordCliBindingTrace()
if (!hasCommonModules) {
return TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(
@@ -173,13 +185,14 @@ class ClassicFrontendFacade(
moduleTrace,
configuration.copy(),
packagePartProviderFactory,
explicitModuleDependencyList = dependentDescriptors
explicitModuleDependencyList = dependentDescriptors,
explicitModuleFriendsList = friendsDescriptors
)
}
val moduleContentScope = GlobalSearchScope.allScope(project)
val moduleClassResolver = SingleModuleClassResolver()
val moduleContext = createModuleContext(module, project, dependentDescriptors) {
val moduleContext = createModuleContext(module, project, dependentDescriptors, friendsDescriptors) {
JvmBuiltIns(it, JvmBuiltIns.Kind.FROM_CLASS_LOADER)
}
val moduleDescriptor = moduleContext.module as ModuleDescriptorImpl
@@ -242,7 +255,7 @@ class ClassicFrontendFacade(
files: List<KtFile>,
): AnalysisResult {
val moduleTrace = NoScopeRecordCliBindingTrace()
val moduleContext = createModuleContext(module, project, dependentDescriptors = emptyList()) {
val moduleContext = createModuleContext(module, project, dependentDescriptors = emptyList(), friendsDescriptors = emptyList()) {
DefaultBuiltIns()
}
return FakeTopDownAnalyzerFacadeForNative.analyzeFilesWithGivenTrace(
@@ -275,6 +288,7 @@ class ClassicFrontendFacade(
module: TestModule,
project: Project,
dependentDescriptors: List<ModuleDescriptorImpl>,
friendsDescriptors: List<ModuleDescriptorImpl>,
builtInsFactory: (StorageManager) -> KotlinBuiltIns,
): ModuleContext {
val projectContext = ProjectContext(project, "test project context")
@@ -287,7 +301,7 @@ class ClassicFrontendFacade(
add(moduleDescriptor.builtIns.builtInsModule)
addAll(dependentDescriptors)
}
moduleDescriptor.setDependencies(dependencies)
moduleDescriptor.setDependencies(dependencies, friendsDescriptors.toSet())
return projectContext.withModule(moduleDescriptor)
}
@@ -20,7 +20,7 @@ import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirective
import org.jetbrains.kotlin.test.directives.LanguageSettingsDirectives
import org.jetbrains.kotlin.test.directives.model.DirectivesContainer
import org.jetbrains.kotlin.test.directives.model.RegisteredDirectives
import org.jetbrains.kotlin.test.model.BackendKinds
import org.jetbrains.kotlin.test.model.DependencyDescription
import org.jetbrains.kotlin.test.model.DependencyKind
import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.services.*
@@ -30,7 +30,12 @@ class ModuleStructureExtractorImpl(
) : ModuleStructureExtractor(testServices, additionalSourceProviders) {
companion object {
private val allowedExtensionsForFiles = listOf(".kt", ".kts", ".java")
private val moduleDirectiveRegex = """([\w-]+)(\((.*)\))?""".toRegex()
/*
* ([\w-]+) module name
* \((.*?)\) module dependencies
* (\((.*?)\))? module friends
*/
private val moduleDirectiveRegex = """([\w-]+)(\((.*?)\)(\((.*?)\))?)?""".toRegex()
}
override fun splitTestDataByModules(
@@ -66,6 +71,7 @@ class ModuleStructureExtractorImpl(
private var currentModuleTargetBackend: TargetBackend? = null
private var currentModuleLanguageVersionSettingsBuilder: LanguageVersionSettingsBuilder = initLanguageSettingsBuilder()
private var dependenciesOfCurrentModule = mutableListOf<DependencyDescription>()
private var friendsOfCurrentModule = mutableListOf<DependencyDescription>()
private var filesOfCurrentModule = mutableListOf<TestFile>()
private var currentFileName: String? = null
@@ -146,12 +152,16 @@ class ModuleStructureExtractorImpl(
} else {
finishGlobalDirectives()
}
val (moduleName, dependencies) = splitRawModuleStringToNameAndDependencies(values.joinToString(separator = " "))
val (moduleName, dependencies, friends) = splitRawModuleStringToNameAndDependencies(values.joinToString(separator = " "))
currentModuleName = moduleName
dependencies.mapTo(dependenciesOfCurrentModule) { name ->
val kind = defaultsProvider.defaultDependencyKind
DependencyDescription(name, kind, DependencyRelation.Dependency)
}
friends.mapTo(friendsOfCurrentModule) { name ->
val kind = defaultsProvider.defaultDependencyKind
DependencyDescription(name, kind, DependencyRelation.Dependency)
}
}
ModuleStructureDirectives.DEPENDENCY,
ModuleStructureDirectives.DEPENDS_ON -> {
@@ -190,12 +200,15 @@ class ModuleStructureExtractorImpl(
return true
}
private fun splitRawModuleStringToNameAndDependencies(moduleDirectiveString: String): Pair<String, List<String>> {
private fun splitRawModuleStringToNameAndDependencies(moduleDirectiveString: String): ModuleNameAndDependeciens {
val matchResult = moduleDirectiveRegex.matchEntire(moduleDirectiveString)
?: error("\"$moduleDirectiveString\" doesn't matches with pattern \"moduleName(dep1, dep2)\"")
val (name, _, dependencies) = matchResult.destructured
if (dependencies.isBlank()) return name to emptyList()
return name to dependencies.split(" ")
val (name, _, dependencies, _, friends) = matchResult.destructured
return ModuleNameAndDependeciens(
name,
dependencies.takeIf { it.isNotBlank() }?.split(" ") ?: emptyList(),
friends.takeIf { it.isNotBlank() }?.split(" ") ?: emptyList(),
)
}
private fun finishGlobalDirectives() {
@@ -216,6 +229,7 @@ class ModuleStructureExtractorImpl(
frontendKind = currentModuleFrontendKind ?: defaultsProvider.defaultFrontend,
files = filesOfCurrentModule,
dependencies = dependenciesOfCurrentModule,
friends = friendsOfCurrentModule,
directives = moduleDirectives,
languageVersionSettings = currentModuleLanguageVersionSettingsBuilder.build()
)
@@ -273,6 +287,7 @@ class ModuleStructureExtractorImpl(
currentModuleLanguageVersionSettingsBuilder = initLanguageSettingsBuilder()
filesOfCurrentModule = mutableListOf()
dependenciesOfCurrentModule = mutableListOf()
friendsOfCurrentModule = mutableListOf()
directivesBuilder = RegisteredDirectivesParser(directivesContainer, assertions)
}
@@ -302,6 +317,12 @@ class ModuleStructureExtractorImpl(
return defaultsProvider.newLanguageSettingsBuilder()
}
}
private data class ModuleNameAndDependeciens(
val name: String,
val dependencies: List<String>,
val friends: List<String>
)
}
private operator fun RegisteredDirectives.plus(other: RegisteredDirectives?): RegisteredDirectives {