[AA] Support multi-module tests with mixed KtModule kinds

- This commit adds a `MODULE_KIND` directive to Analysis API tests which
  can be used to change a test module's `KtModule` kind from the default
  determined by the test's registered `KtModuleFactory` (which in turn
  depends on the `moduleKind` configured during test generation).
- The most important use case is the ability to have multi-module tests
  where a main module references symbols from a binary library module.
  This use case requires source configurations to compile libraries,
  which requires additional setup. This will be implemented in a
  following commit.

^KT-64468 Fixed
This commit is contained in:
Marco Pennekamp
2023-12-20 00:40:25 +01:00
committed by Space Team
parent 69a2bc9abc
commit d3d21b3f34
17 changed files with 187 additions and 103 deletions
@@ -38,7 +38,7 @@ object AnalysisApiFe10TestConfigurator : AnalysisApiTestConfigurator() {
override fun configureTest(builder: TestConfigurationBuilder, disposable: Disposable) { override fun configureTest(builder: TestConfigurationBuilder, disposable: Disposable) {
builder.apply { builder.apply {
useAdditionalService<KtModuleFactory> { KtSourceModuleFactory() } useAdditionalService<KtModuleFactory> { KtSourceModuleFactory }
} }
} }
@@ -13,7 +13,7 @@ import org.jetbrains.kotlin.analysis.api.standalone.base.project.structure.KtMod
import org.jetbrains.kotlin.analysis.api.standalone.base.project.structure.KtModuleWithFiles import org.jetbrains.kotlin.analysis.api.standalone.base.project.structure.KtModuleWithFiles
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.AnalysisApiFirTestServiceRegistrar import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.AnalysisApiFirTestServiceRegistrar
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.configureOptionalTestCompilerPlugin import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.configureOptionalTestCompilerPlugin
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.configurators.KtLibraryBinaryModuleFactory import org.jetbrains.kotlin.analysis.test.framework.project.structure.KtLibraryBinaryModuleFactory
import org.jetbrains.kotlin.analysis.test.framework.project.structure.KtModuleFactory import org.jetbrains.kotlin.analysis.test.framework.project.structure.KtModuleFactory
import org.jetbrains.kotlin.analysis.test.framework.project.structure.KtSourceModuleFactory import org.jetbrains.kotlin.analysis.test.framework.project.structure.KtSourceModuleFactory
import org.jetbrains.kotlin.analysis.test.framework.project.structure.TestModuleStructureFactory import org.jetbrains.kotlin.analysis.test.framework.project.structure.TestModuleStructureFactory
@@ -66,14 +66,11 @@ object StandaloneModeLibraryBinaryTestConfigurator : StandaloneModeConfiguratorB
} }
private class KtCombinedModuleFactory : KtModuleFactory { private class KtCombinedModuleFactory : KtModuleFactory {
private val sourceModuleFactory = KtSourceModuleFactory()
private val libraryBinaryModuleFactory = KtLibraryBinaryModuleFactory()
override fun createModule(testModule: TestModule, testServices: TestServices, project: Project): KtModuleWithFiles { override fun createModule(testModule: TestModule, testServices: TestServices, project: Project): KtModuleWithFiles {
return if (testModule.name == "app") { return if (testModule.name == "app") {
sourceModuleFactory.createModule(testModule, testServices, project) KtSourceModuleFactory.createModule(testModule, testServices, project)
} else { } else {
libraryBinaryModuleFactory.createModule(testModule, testServices, project) KtLibraryBinaryModuleFactory.createModule(testModule, testServices, project)
} }
} }
} }
@@ -5,10 +5,12 @@
package org.jetbrains.kotlin.analysis.test.framework package org.jetbrains.kotlin.analysis.test.framework
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.TestModuleKind
import org.jetbrains.kotlin.test.directives.model.SimpleDirectivesContainer import org.jetbrains.kotlin.test.directives.model.SimpleDirectivesContainer
object AnalysisApiTestDirectives : SimpleDirectivesContainer() { object AnalysisApiTestDirectives : SimpleDirectivesContainer() {
val MODULE_KIND by enumDirective<TestModuleKind>("Overrides the kind of `KtModule` that is built from the associated test module")
val DISABLE_DEPENDED_MODE by directive("Analysis in dependent mode should not be run in this test") val DISABLE_DEPENDED_MODE by directive("Analysis in dependent mode should not be run in this test")
val IGNORE_FE10 by directive("FE10 Analysis API implementation test should mot be run") val IGNORE_FE10 by directive("FE10 Analysis API implementation test should mot be run")
val IGNORE_FIR by directive("FIR Analysis API implementation test should mot be run") val IGNORE_FIR by directive("FIR Analysis API implementation test should mot be run")
} }
@@ -0,0 +1,36 @@
/*
* Copyright 2010-2023 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.analysis.test.framework.project.structure
import com.intellij.openapi.project.Project
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.analysis.api.standalone.base.project.structure.KtModuleWithFiles
import org.jetbrains.kotlin.analysis.test.framework.services.libraries.compiledLibraryProvider
import org.jetbrains.kotlin.analysis.test.framework.services.libraries.testModuleDecompiler
import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.services.TestServices
/**
* @see org.jetbrains.kotlin.analysis.test.framework.test.configurators.TestModuleKind.LibraryBinary
*/
object KtLibraryBinaryModuleFactory : KtModuleFactory {
override fun createModule(testModule: TestModule, testServices: TestServices, project: Project): KtModuleWithFiles {
val library = testServices.compiledLibraryProvider.compileToLibrary(testModule).artifact
val decompiledFiles = testServices.testModuleDecompiler.getAllPsiFilesFromLibrary(library, project)
return KtModuleWithFiles(
KtLibraryModuleImpl(
testModule.name,
testModule.targetPlatform,
GlobalSearchScope.filesScope(project, decompiledFiles.mapTo(mutableSetOf()) { it.virtualFile }),
project,
binaryRoots = listOf(library),
librarySources = null,
),
decompiledFiles
)
}
}
@@ -0,0 +1,56 @@
/*
* Copyright 2010-2023 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.analysis.test.framework.project.structure
import com.intellij.openapi.project.Project
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.analysis.api.impl.base.util.LibraryUtils
import org.jetbrains.kotlin.analysis.api.standalone.base.project.structure.KtModuleWithFiles
import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.services.TestServices
import org.jetbrains.kotlin.analysis.test.framework.services.libraries.compiledLibraryProvider
import java.nio.file.Path
/**
* @see org.jetbrains.kotlin.analysis.test.framework.test.configurators.TestModuleKind.LibrarySource
*/
object KtLibrarySourceModuleFactory : KtModuleFactory {
override fun createModule(testModule: TestModule, testServices: TestServices, project: Project): KtModuleWithFiles {
val (libraryJar, librarySourcesJar) = testServices.compiledLibraryProvider.compileToLibrary(testModule)
require(librarySourcesJar != null)
return createKtLibrarySourceModule(
libraryJar = libraryJar,
librarySourcesJar = librarySourcesJar,
testModule = testModule,
project = project,
)
}
}
fun createKtLibrarySourceModule(libraryJar: Path, librarySourcesJar: Path, testModule: TestModule, project: Project): KtModuleWithFiles {
val libraryKtModule = KtLibraryModuleImpl(
testModule.name,
testModule.targetPlatform,
GlobalSearchScope.filesScope(project, LibraryUtils.getAllVirtualFilesFromJar(libraryJar)),
project,
binaryRoots = listOf(libraryJar),
librarySources = null,
)
val decompiledPsiFilesFromSourceJar = LibraryUtils.getAllPsiFilesFromJar(librarySourcesJar, project)
val librarySourceKtModule = KtLibrarySourceModuleImpl(
testModule.name,
testModule.targetPlatform,
GlobalSearchScope.filesScope(project, decompiledPsiFilesFromSourceJar.map { it.virtualFile }),
project,
binaryLibrary = libraryKtModule,
)
libraryKtModule.librarySources = librarySourceKtModule
return KtModuleWithFiles(librarySourceKtModule, decompiledPsiFilesFromSourceJar)
}
@@ -7,6 +7,8 @@ package org.jetbrains.kotlin.analysis.test.framework.project.structure
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.analysis.api.standalone.base.project.structure.KtModuleWithFiles import org.jetbrains.kotlin.analysis.api.standalone.base.project.structure.KtModuleWithFiles
import org.jetbrains.kotlin.analysis.test.framework.AnalysisApiTestDirectives
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.TestModuleKind
import org.jetbrains.kotlin.test.model.TestModule import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.services.TestService import org.jetbrains.kotlin.test.services.TestService
import org.jetbrains.kotlin.test.services.TestServices import org.jetbrains.kotlin.test.services.TestServices
@@ -15,4 +17,26 @@ fun interface KtModuleFactory : TestService {
fun createModule(testModule: TestModule, testServices: TestServices, project: Project): KtModuleWithFiles fun createModule(testModule: TestModule, testServices: TestServices, project: Project): KtModuleWithFiles
} }
val TestServices.ktModuleFactory: KtModuleFactory by TestServices.testServiceAccessor() private val TestServices.ktModuleFactory: KtModuleFactory by TestServices.testServiceAccessor()
/**
* Returns the appropriate [KtModuleFactory] to build a [KtModule][org.jetbrains.kotlin.analysis.project.structure.KtModule] for the given
* [testModule].
*
* By default, the [KtModuleFactory] registered with these [TestServices] is returned. It may be overruled by the
* [MODULE_KIND][org.jetbrains.kotlin.analysis.test.framework.AnalysisApiTestDirectives.MODULE_KIND] directive for a specific test module.
*/
fun TestServices.getKtModuleFactoryForTestModule(testModule: TestModule): KtModuleFactory {
val explicitKinds = testModule.directives[AnalysisApiTestDirectives.MODULE_KIND]
if (explicitKinds.size > 1) {
throw IllegalArgumentException("A test module may only specify one `${AnalysisApiTestDirectives.MODULE_KIND.name}`.")
}
return when (explicitKinds.singleOrNull()) {
TestModuleKind.Source -> KtSourceModuleFactory
TestModuleKind.LibraryBinary -> KtLibraryBinaryModuleFactory
TestModuleKind.LibrarySource -> KtLibrarySourceModuleFactory
TestModuleKind.ScriptSource -> KtScriptModuleFactory
else -> ktModuleFactory
}
}
@@ -11,7 +11,10 @@ import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.model.TestModule import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.services.TestServices import org.jetbrains.kotlin.test.services.TestServices
class KtScriptModuleFactory : KtModuleFactory { /**
* @see org.jetbrains.kotlin.analysis.test.framework.test.configurators.TestModuleKind.ScriptSource
*/
object KtScriptModuleFactory : KtModuleFactory {
override fun createModule(testModule: TestModule, testServices: TestServices, project: Project): KtModuleWithFiles { override fun createModule(testModule: TestModule, testServices: TestServices, project: Project): KtModuleWithFiles {
val ktFile = TestModuleStructureFactory.createSourcePsiFiles(testModule, testServices, project).single() as KtFile val ktFile = TestModuleStructureFactory.createSourcePsiFiles(testModule, testServices, project).single() as KtFile
val module = KtScriptModuleImpl( val module = KtScriptModuleImpl(
@@ -11,7 +11,10 @@ import org.jetbrains.kotlin.analysis.api.standalone.base.project.structure.KtMod
import org.jetbrains.kotlin.test.model.TestModule import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.services.TestServices import org.jetbrains.kotlin.test.services.TestServices
class KtSourceModuleFactory : KtModuleFactory { /**
* @see org.jetbrains.kotlin.analysis.test.framework.test.configurators.TestModuleKind.Source
*/
object KtSourceModuleFactory : KtModuleFactory {
override fun createModule(testModule: TestModule, testServices: TestServices, project: Project): KtModuleWithFiles { override fun createModule(testModule: TestModule, testServices: TestServices, project: Project): KtModuleWithFiles {
val psiFiles = TestModuleStructureFactory.createSourcePsiFiles(testModule, testServices, project) val psiFiles = TestModuleStructureFactory.createSourcePsiFiles(testModule, testServices, project)
@@ -25,4 +28,4 @@ class KtSourceModuleFactory : KtModuleFactory {
return KtModuleWithFiles(module, psiFiles) return KtModuleWithFiles(module, psiFiles)
} }
} }
@@ -43,8 +43,9 @@ object TestModuleStructureFactory {
testServices: TestServices, testServices: TestServices,
project: Project project: Project
): KtModuleProjectStructure { ): KtModuleProjectStructure {
val moduleEntries = moduleStructure.modules val moduleEntries = moduleStructure.modules.map { testModule ->
.map { testModule -> testServices.ktModuleFactory.createModule(testModule, testServices, project) } testServices.getKtModuleFactoryForTestModule(testModule).createModule(testModule, testServices, project)
}
val moduleEntriesByName = moduleEntries.associateByName() val moduleEntriesByName = moduleEntries.associateByName()
@@ -48,10 +48,3 @@ enum class FrontendKind(val suffix: String) {
Fir("Fir"), Fir("Fir"),
Fe10("Fe10"), Fe10("Fe10"),
} }
enum class TestModuleKind(val suffix: String) {
Source("Source"),
LibraryBinary("LibraryBinary"),
LibrarySource("LibrarySource"),
ScriptSource("ScriptSource"),
}
@@ -0,0 +1,37 @@
/*
* Copyright 2010-2023 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.analysis.test.framework.test.configurators
/**
* In an Analysis API test configuration, the [TestModuleKind] determines the kind of the default
* [KtModule][org.jetbrains.kotlin.analysis.project.structure.KtModule]s used in the test. This essentially defines the context in which a
* test file is analyzed.
*
* The test module kind can also be overridden for a specific test module in multi-module tests using the
* [MODULE_KIND][org.jetbrains.kotlin.analysis.test.framework.AnalysisApiTestDirectives.MODULE_KIND] directive. This allows e.g. source
* module tests to refer to binary library dependencies.
*/
enum class TestModuleKind(val suffix: String) {
/**
* @see org.jetbrains.kotlin.analysis.test.framework.project.structure.KtSourceModuleFactory
*/
Source("Source"),
/**
* @see org.jetbrains.kotlin.analysis.test.framework.project.structure.KtLibraryBinaryModuleFactory
*/
LibraryBinary("LibraryBinary"),
/**
* @see org.jetbrains.kotlin.analysis.test.framework.project.structure.KtLibrarySourceModuleFactory
*/
LibrarySource("LibrarySource"),
/**
* @see org.jetbrains.kotlin.analysis.test.framework.project.structure.KtScriptModuleFactory
*/
ScriptSource("ScriptSource"),
}
@@ -7,15 +7,12 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.test.configurators
import com.intellij.openapi.Disposable import com.intellij.openapi.Disposable
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.analysis.api.impl.base.test.configurators.AnalysisApiBaseTestServiceRegistrar import org.jetbrains.kotlin.analysis.api.impl.base.test.configurators.AnalysisApiBaseTestServiceRegistrar
import org.jetbrains.kotlin.analysis.api.impl.base.test.configurators.AnalysisApiDecompiledCodeTestServiceRegistrar import org.jetbrains.kotlin.analysis.api.impl.base.test.configurators.AnalysisApiDecompiledCodeTestServiceRegistrar
import org.jetbrains.kotlin.analysis.api.impl.base.test.configurators.AnalysisApiLibraryBaseTestServiceRegistrar import org.jetbrains.kotlin.analysis.api.impl.base.test.configurators.AnalysisApiLibraryBaseTestServiceRegistrar
import org.jetbrains.kotlin.analysis.api.impl.base.util.LibraryUtils
import org.jetbrains.kotlin.analysis.api.standalone.base.project.structure.KtModuleProjectStructure import org.jetbrains.kotlin.analysis.api.standalone.base.project.structure.KtModuleProjectStructure
import org.jetbrains.kotlin.analysis.api.standalone.base.project.structure.KtModuleWithFiles
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.AnalysisApiFirTestServiceRegistrar import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.AnalysisApiFirTestServiceRegistrar
import org.jetbrains.kotlin.analysis.test.framework.project.structure.KtLibraryModuleImpl import org.jetbrains.kotlin.analysis.test.framework.project.structure.KtLibraryBinaryModuleFactory
import org.jetbrains.kotlin.analysis.test.framework.project.structure.KtModuleFactory import org.jetbrains.kotlin.analysis.test.framework.project.structure.KtModuleFactory
import org.jetbrains.kotlin.analysis.test.framework.project.structure.TestModuleStructureFactory import org.jetbrains.kotlin.analysis.test.framework.project.structure.TestModuleStructureFactory
import org.jetbrains.kotlin.analysis.test.framework.services.libraries.* import org.jetbrains.kotlin.analysis.test.framework.services.libraries.*
@@ -23,7 +20,6 @@ import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisA
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiTestServiceRegistrar import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiTestServiceRegistrar
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.FrontendKind import org.jetbrains.kotlin.analysis.test.framework.test.configurators.FrontendKind
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.services.TestModuleStructure import org.jetbrains.kotlin.test.services.TestModuleStructure
import org.jetbrains.kotlin.test.services.TestServices import org.jetbrains.kotlin.test.services.TestServices
@@ -33,7 +29,7 @@ object AnalysisApiFirLibraryBinaryTestConfigurator : AnalysisApiTestConfigurator
override fun configureTest(builder: TestConfigurationBuilder, disposable: Disposable) { override fun configureTest(builder: TestConfigurationBuilder, disposable: Disposable) {
builder.apply { builder.apply {
useAdditionalService<KtModuleFactory> { KtLibraryBinaryModuleFactory() } useAdditionalService<KtModuleFactory> { KtLibraryBinaryModuleFactory }
useAdditionalService<TestModuleCompiler> { DispatchingTestModuleCompiler() } useAdditionalService<TestModuleCompiler> { DispatchingTestModuleCompiler() }
useAdditionalService<TestModuleDecompiler> { TestModuleDecompilerJar() } useAdditionalService<TestModuleDecompiler> { TestModuleDecompilerJar() }
} }
@@ -55,22 +51,3 @@ object AnalysisApiFirLibraryBinaryTestConfigurator : AnalysisApiTestConfigurator
AnalysisApiLibraryBaseTestServiceRegistrar, AnalysisApiLibraryBaseTestServiceRegistrar,
) )
} }
class KtLibraryBinaryModuleFactory : KtModuleFactory {
override fun createModule(testModule: TestModule, testServices: TestServices, project: Project): KtModuleWithFiles {
val library = testServices.compiledLibraryProvider.compileToLibrary(testModule).artifact
val decompiledFiles = testServices.testModuleDecompiler.getAllPsiFilesFromLibrary(library, project)
return KtModuleWithFiles(
KtLibraryModuleImpl(
testModule.name,
testModule.targetPlatform,
GlobalSearchScope.filesScope(project, decompiledFiles.mapTo(mutableSetOf()) { it.virtualFile }),
project,
binaryRoots = listOf(library),
librarySources = null,
),
decompiledFiles
)
}
}
@@ -11,19 +11,17 @@ import org.jetbrains.kotlin.analysis.api.impl.base.test.configurators.AnalysisAp
import org.jetbrains.kotlin.analysis.api.impl.base.test.configurators.AnalysisApiDecompiledCodeTestServiceRegistrar import org.jetbrains.kotlin.analysis.api.impl.base.test.configurators.AnalysisApiDecompiledCodeTestServiceRegistrar
import org.jetbrains.kotlin.analysis.api.impl.base.test.configurators.AnalysisApiLibraryBaseTestServiceRegistrar import org.jetbrains.kotlin.analysis.api.impl.base.test.configurators.AnalysisApiLibraryBaseTestServiceRegistrar
import org.jetbrains.kotlin.analysis.api.standalone.base.project.structure.KtModuleProjectStructure import org.jetbrains.kotlin.analysis.api.standalone.base.project.structure.KtModuleProjectStructure
import org.jetbrains.kotlin.analysis.api.standalone.base.project.structure.KtModuleWithFiles
import org.jetbrains.kotlin.analysis.low.level.api.fir.compiler.based.SealedClassesInheritorsCaclulatorPreAnalysisHandler import org.jetbrains.kotlin.analysis.low.level.api.fir.compiler.based.SealedClassesInheritorsCaclulatorPreAnalysisHandler
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.AnalysisApiFirTestServiceRegistrar import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.AnalysisApiFirTestServiceRegistrar
import org.jetbrains.kotlin.analysis.test.framework.project.structure.KtLibrarySourceModuleFactory
import org.jetbrains.kotlin.analysis.test.framework.project.structure.KtModuleFactory import org.jetbrains.kotlin.analysis.test.framework.project.structure.KtModuleFactory
import org.jetbrains.kotlin.analysis.test.framework.project.structure.TestModuleStructureFactory import org.jetbrains.kotlin.analysis.test.framework.project.structure.TestModuleStructureFactory
import org.jetbrains.kotlin.analysis.test.framework.services.libraries.*
import org.jetbrains.kotlin.analysis.test.framework.services.configuration.AnalysisApiJvmEnvironmentConfigurator import org.jetbrains.kotlin.analysis.test.framework.services.configuration.AnalysisApiJvmEnvironmentConfigurator
import org.jetbrains.kotlin.analysis.test.framework.services.libraries.compiledLibraryProvider import org.jetbrains.kotlin.analysis.test.framework.services.libraries.*
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiTestConfigurator import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiTestConfigurator
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiTestServiceRegistrar import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiTestServiceRegistrar
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.FrontendKind import org.jetbrains.kotlin.analysis.test.framework.test.configurators.FrontendKind
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.services.TestModuleStructure import org.jetbrains.kotlin.test.services.TestModuleStructure
import org.jetbrains.kotlin.test.services.TestServices import org.jetbrains.kotlin.test.services.TestServices
@@ -36,7 +34,7 @@ object AnalysisApiFirLibrarySourceTestConfigurator : AnalysisApiTestConfigurator
disposable: Disposable disposable: Disposable
) { ) {
builder.apply { builder.apply {
useAdditionalService<KtModuleFactory> { KtLibrarySourceModuleFactory() } useAdditionalService<KtModuleFactory> { KtLibrarySourceModuleFactory }
useAdditionalService<TestModuleCompiler> { DispatchingTestModuleCompiler() } useAdditionalService<TestModuleCompiler> { DispatchingTestModuleCompiler() }
useDirectives(SealedClassesInheritorsCaclulatorPreAnalysisHandler.Directives) useDirectives(SealedClassesInheritorsCaclulatorPreAnalysisHandler.Directives)
usePreAnalysisHandlers(::SealedClassesInheritorsCaclulatorPreAnalysisHandler) usePreAnalysisHandlers(::SealedClassesInheritorsCaclulatorPreAnalysisHandler)
@@ -60,18 +58,3 @@ object AnalysisApiFirLibrarySourceTestConfigurator : AnalysisApiTestConfigurator
AnalysisApiLibraryBaseTestServiceRegistrar, AnalysisApiLibraryBaseTestServiceRegistrar,
) )
} }
private class KtLibrarySourceModuleFactory : KtModuleFactory {
override fun createModule(testModule: TestModule, testServices: TestServices, project: Project): KtModuleWithFiles {
val (libraryJar, librarySourcesJar) = testServices.compiledLibraryProvider.compileToLibrary(testModule)
require(librarySourcesJar != null)
return createKtLibrarySourceModule(
libraryJar = libraryJar,
librarySourcesJar = librarySourcesJar,
testModule = testModule,
project = project,
)
}
}
@@ -34,7 +34,7 @@ object AnalysisApiFirOutOfContentRootTestConfigurator : AnalysisApiFirSourceLike
builder.apply { builder.apply {
useDirectives(Directives) useDirectives(Directives)
useAdditionalService<KtModuleFactory> { KtOutOfContentRootModuleFactory() } useAdditionalService<KtModuleFactory> { KtOutOfContentRootModuleFactory }
} }
} }
@@ -56,7 +56,7 @@ object AnalysisApiFirOutOfContentRootTestConfigurator : AnalysisApiFirSourceLike
private class SkipWhenOutOfContentRootException : SkipTestException() private class SkipWhenOutOfContentRootException : SkipTestException()
private class KtOutOfContentRootModuleFactory : KtModuleFactory { private object KtOutOfContentRootModuleFactory : KtModuleFactory {
override fun createModule(testModule: TestModule, testServices: TestServices, project: Project): KtModuleWithFiles { override fun createModule(testModule: TestModule, testServices: TestServices, project: Project): KtModuleWithFiles {
val psiFiles = TestModuleStructureFactory.createSourcePsiFiles(testModule, testServices, project) val psiFiles = TestModuleStructureFactory.createSourcePsiFiles(testModule, testServices, project)
val platform = testModule.targetPlatform val platform = testModule.targetPlatform
@@ -94,4 +94,4 @@ private class KtNotUnderContentRootModuleForTest(
override val moduleDescription: String override val moduleDescription: String
get() = "Not under content root \"${name}\" for ${file.virtualFile.path}" get() = "Not under content root \"${name}\" for ${file.virtualFile.path}"
} }
@@ -18,7 +18,7 @@ class AnalysisApiFirScriptTestConfigurator(analyseInDependentSession: Boolean) :
super.configureTest(builder, disposable) super.configureTest(builder, disposable)
builder.apply { builder.apply {
useAdditionalService<KtModuleFactory> { KtScriptModuleFactory() } useAdditionalService<KtModuleFactory> { KtScriptModuleFactory }
} }
} }
@@ -17,7 +17,7 @@ open class AnalysisApiFirSourceTestConfigurator(
super.configureTest(builder, disposable) super.configureTest(builder, disposable)
builder.apply { builder.apply {
useAdditionalService<KtModuleFactory> { KtSourceModuleFactory() } useAdditionalService<KtModuleFactory> { KtSourceModuleFactory }
} }
} }
} }
@@ -7,13 +7,9 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.test.configurators
import com.intellij.openapi.Disposable import com.intellij.openapi.Disposable
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.psi.search.GlobalSearchScope
import java.nio.file.Path
import org.jetbrains.kotlin.analysis.api.impl.base.util.LibraryUtils
import org.jetbrains.kotlin.analysis.api.standalone.base.project.structure.KtModuleWithFiles import org.jetbrains.kotlin.analysis.api.standalone.base.project.structure.KtModuleWithFiles
import org.jetbrains.kotlin.analysis.test.framework.project.structure.KtLibraryModuleImpl
import org.jetbrains.kotlin.analysis.test.framework.project.structure.KtLibrarySourceModuleImpl
import org.jetbrains.kotlin.analysis.test.framework.project.structure.KtModuleFactory import org.jetbrains.kotlin.analysis.test.framework.project.structure.KtModuleFactory
import org.jetbrains.kotlin.analysis.test.framework.project.structure.createKtLibrarySourceModule
import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
import org.jetbrains.kotlin.test.model.TestModule import org.jetbrains.kotlin.test.model.TestModule
@@ -23,35 +19,12 @@ object AnalysisApiFirStdlibSourceTestConfigurator : AnalysisApiFirSourceLikeTest
override fun configureTest(builder: TestConfigurationBuilder, disposable: Disposable) { override fun configureTest(builder: TestConfigurationBuilder, disposable: Disposable) {
super.configureTest(builder, disposable) super.configureTest(builder, disposable)
builder.apply { builder.apply {
useAdditionalService<KtModuleFactory> { KtStdlibSourceModuleFactory() } useAdditionalService<KtModuleFactory> { KtStdlibSourceModuleFactory }
} }
} }
} }
fun createKtLibrarySourceModule(libraryJar: Path, librarySourcesJar: Path, testModule: TestModule, project: Project): KtModuleWithFiles { private object KtStdlibSourceModuleFactory : KtModuleFactory {
val libraryKtModule = KtLibraryModuleImpl(
testModule.name,
testModule.targetPlatform,
GlobalSearchScope.filesScope(project, LibraryUtils.getAllVirtualFilesFromJar(libraryJar)),
project,
binaryRoots = listOf(libraryJar),
librarySources = null,
)
val decompiledPsiFilesFromSourceJar = LibraryUtils.getAllPsiFilesFromJar(librarySourcesJar, project)
val librarySourceKtModule = KtLibrarySourceModuleImpl(
testModule.name,
testModule.targetPlatform,
GlobalSearchScope.filesScope(project, decompiledPsiFilesFromSourceJar.map { it.virtualFile }),
project,
binaryLibrary = libraryKtModule,
)
libraryKtModule.librarySources = librarySourceKtModule
return KtModuleWithFiles(librarySourceKtModule, decompiledPsiFilesFromSourceJar)
}
private class KtStdlibSourceModuleFactory : KtModuleFactory {
override fun createModule(testModule: TestModule, testServices: TestServices, project: Project): KtModuleWithFiles { override fun createModule(testModule: TestModule, testServices: TestServices, project: Project): KtModuleWithFiles {
val libraryJar = ForTestCompileRuntime.runtimeJarForTests().toPath() val libraryJar = ForTestCompileRuntime.runtimeJarForTests().toPath()
val librarySourcesJar = ForTestCompileRuntime.runtimeSourcesJarForTests().toPath() val librarySourcesJar = ForTestCompileRuntime.runtimeSourcesJarForTests().toPath()
@@ -62,5 +35,4 @@ private class KtStdlibSourceModuleFactory : KtModuleFactory {
project = project, project = project,
) )
} }
}
}