[analysis api, test] rework test infrastructure, add multimodule tests

This commit is contained in:
Ilya Kirillov
2022-03-24 22:34:31 +01:00
parent 1e5cf80278
commit 4bd7fed1ea
79 changed files with 1786 additions and 510 deletions
@@ -3,11 +3,12 @@
* 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.api.fir
package org.jetbrains.kotlin.analysis.api.fir.test.configurators
import org.jetbrains.kotlin.analysis.api.fir.utils.libraries.binary.LibraryAnalysisApiTestConfigurator
import org.jetbrains.kotlin.analysis.api.fir.utils.libraries.source.LibrarySourceAnalysisApiTestConfigurator
import org.jetbrains.kotlin.analysis.test.framework.*
import org.jetbrains.kotlin.analysis.api.fir.test.configurators.library.AnalysisApiFirLibraryBinaryTestConfigurator
import org.jetbrains.kotlin.analysis.api.fir.test.configurators.source.AnalysisApiFirSourceTestConfigurator
import org.jetbrains.kotlin.analysis.api.fir.test.configurators.library.AnalysisApiFirLibrarySourceTestConfigurator
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.*
object AnalysisApiFirTestConfiguratorFactory : AnalysisApiTestConfiguratorFactory() {
override fun createConfigurator(data: AnalysisApiTestConfiguratorFactoryData): AnalysisApiTestConfigurator {
@@ -15,18 +16,18 @@ object AnalysisApiFirTestConfiguratorFactory : AnalysisApiTestConfiguratorFactor
return when (data.moduleKind) {
TestModuleKind.Source -> when (data.analysisSessionMode) {
AnalysisSessionMode.Normal -> AnalysisApiFirTestConfigurator(analyseInDependentSession = false)
AnalysisSessionMode.Dependent -> AnalysisApiFirTestConfigurator(analyseInDependentSession = true)
AnalysisSessionMode.Normal -> AnalysisApiFirSourceTestConfigurator(analyseInDependentSession = false)
AnalysisSessionMode.Dependent -> AnalysisApiFirSourceTestConfigurator(analyseInDependentSession = true)
}
TestModuleKind.LibraryBinary -> {
require(data.analysisSessionMode == AnalysisSessionMode.Normal)
LibraryAnalysisApiTestConfigurator
AnalysisApiFirLibraryBinaryTestConfigurator
}
TestModuleKind.LibrarySource -> {
require(data.analysisSessionMode == AnalysisSessionMode.Normal)
LibrarySourceAnalysisApiTestConfigurator
AnalysisApiFirLibrarySourceTestConfigurator
}
}
}
@@ -0,0 +1,66 @@
/*
* 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.analysis.api.fir.test.configurators.library
import com.intellij.openapi.Disposable
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiManager
import org.jetbrains.kotlin.analysis.api.fir.test.configurators.source.AnalysisApiFirSourceTestConfigurator
import org.jetbrains.kotlin.analysis.api.impl.base.test.configurators.AnalysisApiBaseTestServiceRegistrar
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.KtModuleWithFiles
import org.jetbrains.kotlin.analysis.decompiler.psi.file.KtClsFile
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.AnalysisApiFirTestServiceRegistrar
import org.jetbrains.kotlin.analysis.test.framework.project.structure.TestKtLibraryModule
import org.jetbrains.kotlin.analysis.test.framework.services.libraries.compiledLibraryProvider
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiTestConfigurator
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiTestServiceRegistrar
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
import org.jetbrains.kotlin.test.services.TestModuleStructure
import org.jetbrains.kotlin.test.services.TestServices
import java.nio.file.Path
object AnalysisApiFirLibraryBinaryTestConfigurator : AnalysisApiTestConfigurator() {
override val analyseInDependentSession: Boolean get() = false
override fun configureTest(
builder: TestConfigurationBuilder,
disposable: Disposable
) {
}
override fun createModules(
moduleStructure: TestModuleStructure,
testServices: TestServices,
project: Project
): List<KtModuleWithFiles> {
val testModule = moduleStructure.modules.single()
val library = testServices.compiledLibraryProvider.compileToLibrary(testModule).jar
val decompiledFiles = LibraryUtils.getAllPsiFilesFromTheJar(library, project)
return listOf(
KtModuleWithFiles(
TestKtLibraryModule(project, testModule, decompiledFiles, listOf(library), testServices),
decompiledFiles,
)
)
}
override val serviceRegistrars: List<AnalysisApiTestServiceRegistrar> =
listOf(
AnalysisApiBaseTestServiceRegistrar,
AnalysisApiFirTestServiceRegistrar,
AnalysisApiLibraryBaseTestServiceRegistrar,
)
override fun doOutOfBlockModification(file: KtFile) {
AnalysisApiFirSourceTestConfigurator(analyseInDependentSession = false).doOutOfBlockModification(file)
}
}
@@ -3,55 +3,83 @@
* 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.api.fir.utils.libraries.source
package org.jetbrains.kotlin.analysis.api.fir.test.configurators.library
import com.intellij.openapi.Disposable
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiManager
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.analysis.api.fir.test.configurators.source.AnalysisApiFirSourceTestConfigurator
import org.jetbrains.kotlin.analysis.api.impl.base.test.configurators.AnalysisApiBaseTestServiceRegistrar
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.KtModuleWithFiles
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.AnalysisApiFirTestServiceRegistrar
import org.jetbrains.kotlin.analysis.project.structure.KtLibraryModule
import org.jetbrains.kotlin.analysis.project.structure.KtLibrarySourceModule
import org.jetbrains.kotlin.analysis.project.structure.KtModule
import org.jetbrains.kotlin.analysis.test.framework.project.structure.TestKtLibrarySourceModule
import org.jetbrains.kotlin.analysis.test.framework.project.structure.projectModuleProvider
import org.jetbrains.kotlin.analysis.test.framework.services.libraries.CompiledLibraryProvider
import org.jetbrains.kotlin.analysis.test.framework.services.libraries.compiledLibraryProvider
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiTestConfigurator
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiTestServiceRegistrar
import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
import org.jetbrains.kotlin.test.frontend.fir.getAnalyzerServices
import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.services.PreAnalysisHandler
import org.jetbrains.kotlin.test.services.ServiceRegistrationData
import org.jetbrains.kotlin.test.services.TestModuleStructure
import org.jetbrains.kotlin.test.services.TestServices
import org.jetbrains.kotlin.test.services.compilerConfigurationProvider
import java.nio.file.Path
class LibrarySourceModuleRegistrarPreAnalysisHandler(
testServices: TestServices
) : PreAnalysisHandler(testServices) {
private val moduleInfoProvider = testServices.projectModuleProvider
object AnalysisApiFirLibrarySourceTestConfigurator : AnalysisApiTestConfigurator() {
override val analyseInDependentSession: Boolean get() = false
override fun preprocessModuleStructure(moduleStructure: TestModuleStructure) {
override fun configureTest(
builder: TestConfigurationBuilder,
disposable: Disposable
) {
builder.useAdditionalServices(ServiceRegistrationData(CompiledLibraryProvider::class, ::CompiledLibraryProvider))
}
override fun createModules(
moduleStructure: TestModuleStructure,
testServices: TestServices,
project: Project
): List<KtModuleWithFiles> {
val testModule = moduleStructure.modules.single()
val project = testServices.compilerConfigurationProvider.getProject(testModule)
val (libraryJar, librarySourcesJar) = testServices.compiledLibraryProvider.getCompiledLibrary(testModule)
val (libraryJar, librarySourcesJar) = testServices.compiledLibraryProvider.compileToLibrary(testModule)
val libraryKtModule = KtTestLibraryModule(project, testModule, libraryJar)
val librarySourceKtFiles = LibraryUtils
.getAllVirtualFilesFromJar(librarySourcesJar)
.mapNotNull { PsiManager.getInstance(project).findFile(it) as? KtFile }
val librarySourceFiles = LibraryUtils
.getAllPsiFilesFromTheJar(librarySourcesJar, project)
val sourcesKtModule = TestKtLibrarySourceModule(
project,
testModule,
librarySourceKtFiles.toSet(),
librarySourceFiles,
testServices,
libraryKtModule
)
libraryKtModule.librarySources = sourcesKtModule
moduleInfoProvider.registerModuleInfo(testModule, sourcesKtModule)
return listOf(
KtModuleWithFiles(sourcesKtModule, librarySourceFiles),
)
}
override val serviceRegistrars: List<AnalysisApiTestServiceRegistrar> =
listOf(
AnalysisApiBaseTestServiceRegistrar,
AnalysisApiFirTestServiceRegistrar,
AnalysisApiLibraryBaseTestServiceRegistrar,
)
override fun doOutOfBlockModification(file: KtFile) {
AnalysisApiFirSourceTestConfigurator(analyseInDependentSession = false).doOutOfBlockModification(file)
}
}
@@ -76,3 +104,4 @@ private class KtTestLibraryModule(
override val platform: TargetPlatform get() = testModule.targetPlatform
override val analyzerServices: PlatformDependentAnalyzerServices get() = testModule.targetPlatform.getAnalyzerServices()
}
@@ -0,0 +1,43 @@
/*
* 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.analysis.api.fir.test.configurators.source
import com.intellij.openapi.Disposable
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.analysis.api.fir.utils.configureOptionalTestCompilerPlugin
import org.jetbrains.kotlin.analysis.api.impl.base.test.configurators.AnalysisApiBaseTestServiceRegistrar
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.FirLowLevelAnalysisApiTestConfigurator
import org.jetbrains.kotlin.analysis.test.framework.project.structure.toKtSourceModules
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiTestConfigurator
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiTestServiceRegistrar
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
import org.jetbrains.kotlin.test.services.TestModuleStructure
import org.jetbrains.kotlin.test.services.TestServices
class AnalysisApiFirSourceTestConfigurator(override val analyseInDependentSession: Boolean) : AnalysisApiTestConfigurator() {
override fun configureTest(builder: TestConfigurationBuilder, disposable: Disposable) {
FirLowLevelAnalysisApiTestConfigurator.configureTest(builder, disposable)
builder.apply {
configureOptionalTestCompilerPlugin()
}
}
override val serviceRegistrars: List<AnalysisApiTestServiceRegistrar> = listOf(
AnalysisApiBaseTestServiceRegistrar,
AnalysisApiFirTestServiceRegistrar,
)
override fun createModules(moduleStructure: TestModuleStructure, testServices: TestServices, project: Project): List<KtModuleWithFiles> {
return moduleStructure.toKtSourceModules(testServices, project)
}
override fun doOutOfBlockModification(file: KtFile) {
FirLowLevelAnalysisApiTestConfigurator.doOutOfBlockModification(file)
}
}
@@ -1,42 +0,0 @@
/*
* 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.analysis.api.fir.utils.libraries.binary
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiManager
import org.jetbrains.kotlin.analysis.api.impl.base.util.LibraryUtils
import org.jetbrains.kotlin.analysis.decompiler.psi.file.KtClsFile
import org.jetbrains.kotlin.analysis.test.framework.project.structure.TestKtLibraryModule
import org.jetbrains.kotlin.analysis.test.framework.project.structure.projectModuleProvider
import org.jetbrains.kotlin.analysis.test.framework.services.libraries.compiledLibraryProvider
import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.services.PreAnalysisHandler
import org.jetbrains.kotlin.test.services.TestModuleStructure
import org.jetbrains.kotlin.test.services.TestServices
import org.jetbrains.kotlin.test.services.compilerConfigurationProvider
class LibraryModuleRegistrarPreAnalysisHandler(
testServices: TestServices
) : PreAnalysisHandler(testServices) {
private val moduleInfoProvider = testServices.projectModuleProvider
override fun preprocessModuleStructure(moduleStructure: TestModuleStructure) {
val testModule = moduleStructure.modules.single()
val project = testServices.compilerConfigurationProvider.getProject(testModule)
val decompiledKtFiles = getDecompiledVirtualFilesFromLibrary(testModule, project)
moduleInfoProvider.registerModuleInfo(testModule, TestKtLibraryModule(project, testModule, decompiledKtFiles, testServices))
}
private fun getDecompiledVirtualFilesFromLibrary(module: TestModule, project: Project): List<KtClsFile> {
val library = testServices.compiledLibraryProvider.getCompiledLibrary(module).jar
val virtualFiles = LibraryUtils.getAllVirtualFilesFromJar(library)
return virtualFiles.mapNotNull { virtualFile ->
PsiManager.getInstance(project).findFile(virtualFile) as? KtClsFile
}
}
}