[analysis api fir] put every library into a separate KtModule in tests

This commit is contained in:
Ilya Kirillov
2022-04-07 08:09:00 +02:00
parent 252d8e283b
commit 2649788b87
43 changed files with 778 additions and 399 deletions
@@ -9,8 +9,7 @@ import com.intellij.openapi.Disposable
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiFile
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.test.framework.project.structure.toKtSourceModules
import org.jetbrains.kotlin.analysis.api.standalone.base.project.structure.KtModuleProjectStructure
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
@@ -42,7 +41,7 @@ object AnalysisApiFe10TestConfigurator : AnalysisApiTestConfigurator() {
moduleStructure: TestModuleStructure,
testServices: TestServices,
project: Project,
): List<KtModuleWithFiles> {
): KtModuleProjectStructure {
return moduleStructure.toKtSourceModules(testServices, project)
}
@@ -39,9 +39,6 @@ dependencies {
testApiJUnit5()
testApi(project(":analysis:symbol-light-classes"))
// We use 'api' instead of 'implementation' because other modules might be using these jars indirectly
testApi(project(":plugins:fir-plugin-prototype"))
testApi(projectTests(":plugins:fir-plugin-prototype"))
}
sourceSets {
@@ -6,8 +6,8 @@
package org.jetbrains.kotlin.analysis.api.fir.test.configurators
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.low.level.api.fir.test.configurators.AnalysisApiFirSourceTestConfigurator
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.*
object AnalysisApiFirTestConfiguratorFactory : AnalysisApiTestConfiguratorFactory() {
@@ -7,23 +7,24 @@ 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 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.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.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.low.level.api.fir.test.configurators.AnalysisApiFirSourceTestConfigurator
import org.jetbrains.kotlin.analysis.test.framework.project.structure.KtLibraryModuleImpl
import org.jetbrains.kotlin.analysis.test.framework.project.structure.TestModuleStructureFactory
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.model.TestModule
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
@@ -38,17 +39,28 @@ object AnalysisApiFirLibraryBinaryTestConfigurator : AnalysisApiTestConfigurator
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)
): KtModuleProjectStructure {
return TestModuleStructureFactory.createProjectStructureByTestStructure(
moduleStructure,
testServices,
project
) { testModule: TestModule, _, _ ->
val library = testServices.compiledLibraryProvider.compileToLibrary(testModule).jar
val decompiledFiles = LibraryUtils.getAllPsiFilesFromTheJar(library, project)
return listOf(
KtModuleWithFiles(
TestKtLibraryModule(project, testModule, decompiledFiles, listOf(library), testServices),
decompiledFiles,
KtLibraryModuleImpl(
testModule.name,
testModule.targetPlatform,
GlobalSearchScope.filesScope(project, decompiledFiles.mapTo(mutableSetOf()) { it.virtualFile }),
project,
binaryRoots = listOf(library),
librarySources = null,
isBuitinsContainingStdlib = false,
),
decompiledFiles
)
)
}
}
@@ -8,30 +8,27 @@ 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.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.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.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.low.level.api.fir.test.configurators.AnalysisApiFirSourceTestConfigurator
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.TestModuleStructureFactory
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.ServiceRegistrationData
import org.jetbrains.kotlin.test.services.TestModuleStructure
import org.jetbrains.kotlin.test.services.TestServices
import java.nio.file.Path
object AnalysisApiFirLibrarySourceTestConfigurator : AnalysisApiTestConfigurator() {
override val analyseInDependentSession: Boolean get() = false
@@ -40,34 +37,49 @@ object AnalysisApiFirLibrarySourceTestConfigurator : AnalysisApiTestConfigurator
builder: TestConfigurationBuilder,
disposable: Disposable
) {
builder.useAdditionalServices(ServiceRegistrationData(CompiledLibraryProvider::class, ::CompiledLibraryProvider))
builder.apply {
useAdditionalServices(ServiceRegistrationData(CompiledLibraryProvider::class, ::CompiledLibraryProvider))
usePreAnalysisHandlers(::SealedClassesInheritorsCaclulatorPreAnalysisHandler)
}
}
override fun createModules(
moduleStructure: TestModuleStructure,
testServices: TestServices,
project: Project
): List<KtModuleWithFiles> {
val testModule = moduleStructure.modules.single()
val (libraryJar, librarySourcesJar) = testServices.compiledLibraryProvider.compileToLibrary(testModule)
val libraryKtModule = KtTestLibraryModule(project, testModule, libraryJar)
val librarySourceFiles = LibraryUtils
.getAllPsiFilesFromTheJar(librarySourcesJar, project)
val sourcesKtModule = TestKtLibrarySourceModule(
project,
testModule,
librarySourceFiles,
): KtModuleProjectStructure {
return TestModuleStructureFactory.createProjectStructureByTestStructure(
moduleStructure,
testServices,
libraryKtModule
)
libraryKtModule.librarySources = sourcesKtModule
project
) { testModule: TestModule, _, _ ->
val (libraryJar, librarySourcesJar) = testServices.compiledLibraryProvider.compileToLibrary(testModule)
return listOf(
KtModuleWithFiles(sourcesKtModule, librarySourceFiles),
)
val libraryKtModule = KtLibraryModuleImpl(
testModule.name,
testModule.targetPlatform,
GlobalSearchScope.filesScope(project, LibraryUtils.getAllVirtualFilesFromJar(libraryJar)),
project,
binaryRoots = listOf(libraryJar),
librarySources = null,
isBuitinsContainingStdlib = false,
)
val decompiledPsiFilesFromSourceJar = LibraryUtils.getAllPsiFilesFromTheJar(librarySourcesJar, project)
val librarySourceKtModule = KtLibrarySourceModuleImpl(
testModule.name,
testModule.targetPlatform,
GlobalSearchScope.filesScope(project, decompiledPsiFilesFromSourceJar.map { it.virtualFile }),
project,
binaryLibrary = libraryKtModule,
)
libraryKtModule.librarySources = librarySourceKtModule
KtModuleWithFiles(
librarySourceKtModule,
decompiledPsiFilesFromSourceJar
)
}
}
override val serviceRegistrars: List<AnalysisApiTestServiceRegistrar> =
@@ -81,27 +93,4 @@ object AnalysisApiFirLibrarySourceTestConfigurator : AnalysisApiTestConfigurator
override fun doOutOfBlockModification(file: KtFile) {
AnalysisApiFirSourceTestConfigurator(analyseInDependentSession = false).doOutOfBlockModification(file)
}
}
private class KtTestLibraryModule(
override val project: Project,
private val testModule: TestModule,
private val jar: Path
) : KtLibraryModule {
override val directRegularDependencies: List<KtModule> get() = emptyList()
override val directRefinementDependencies: List<KtModule> get() = emptyList()
override val directFriendDependencies: List<KtModule> get() = emptyList()
override val contentScope: GlobalSearchScope by lazy {
GlobalSearchScope.filesScope(project, LibraryUtils.getAllVirtualFilesFromJar(jar))
}
override fun getBinaryRoots(): Collection<Path> = listOf(jar)
override val libraryName: String get() = testModule.name
override lateinit var librarySources: KtLibrarySourceModule
override val platform: TargetPlatform get() = testModule.targetPlatform
override val analyzerServices: PlatformDependentAnalyzerServices get() = testModule.targetPlatform.getAnalyzerServices()
}
}
@@ -1,108 +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.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.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.ServiceRegistrationData
import org.jetbrains.kotlin.test.services.TestModuleStructure
import org.jetbrains.kotlin.test.services.TestServices
import java.nio.file.Path
object AnalysisApiLibrarySourceTestConfigurator : AnalysisApiTestConfigurator() {
override val analyseInDependentSession: Boolean get() = false
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 (libraryJar, librarySourcesJar) = testServices.compiledLibraryProvider.compileToLibrary(testModule)
val libraryKtModule = KtTestLibraryModule(project, testModule, libraryJar)
val librarySourceFiles = LibraryUtils
.getAllPsiFilesFromTheJar(librarySourcesJar, project)
val sourcesKtModule = TestKtLibrarySourceModule(
project,
testModule,
librarySourceFiles,
testServices,
libraryKtModule
)
libraryKtModule.librarySources = 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)
}
}
private class KtTestLibraryModule(
override val project: Project,
private val testModule: TestModule,
private val jar: Path
) : KtLibraryModule {
override val directRegularDependencies: List<KtModule> get() = emptyList()
override val directRefinementDependencies: List<KtModule> get() = emptyList()
override val directFriendDependencies: List<KtModule> get() = emptyList()
override val contentScope: GlobalSearchScope by lazy {
GlobalSearchScope.filesScope(project, LibraryUtils.getAllVirtualFilesFromJar(jar))
}
override fun getBinaryRoots(): Collection<Path> = listOf(jar)
override val libraryName: String get() = testModule.name
override lateinit var librarySources: KtLibrarySourceModule
override val platform: TargetPlatform get() = testModule.targetPlatform
override val analyzerServices: PlatformDependentAnalyzerServices get() = testModule.targetPlatform.getAnalyzerServices()
}
@@ -1,43 +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.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)
}
}
@@ -29,7 +29,7 @@ object AnalysisApiBaseTestServiceRegistrar: AnalysisApiTestServiceRegistrar() {
}
override fun registerProjectServices(project: MockProject, testServices: TestServices) {
val allKtFiles = testServices.ktModuleProvider.getAllModules().flatMap { it.files.filterIsInstance<KtFile>() }
val allKtFiles = testServices.ktModuleProvider.getModuleStructure().mainModules.flatMap { it.files.filterIsInstance<KtFile>() }
project.apply {
registerService(KotlinModificationTrackerFactory::class.java, KotlinStaticModificationTrackerFactory::class.java)
@@ -6,8 +6,22 @@
package org.jetbrains.kotlin.analysis.api.standalone.base.project.structure
import com.intellij.psi.PsiFile
import org.jetbrains.kotlin.analysis.project.structure.KtBinaryModule
import org.jetbrains.kotlin.analysis.project.structure.KtLibraryModule
import org.jetbrains.kotlin.analysis.project.structure.KtModule
data class KtModuleProjectStructure(
val mainModules: List<KtModuleWithFiles>,
val binaryModules: Iterable<KtBinaryModule>,
val stdlibFor: (KtModule) -> KtLibraryModule,
) {
fun allKtModules(): List<KtModule> = buildList {
mainModules.mapTo(this) { it.ktModule }
addAll(binaryModules)
}
}
data class KtModuleWithFiles(
val ktModule: KtModule,
val files: List<PsiFile>
@@ -10,20 +10,20 @@ import org.jetbrains.kotlin.analysis.project.structure.*
import org.jetbrains.kotlin.psi.psiUtil.contains
class KtStaticModuleProvider(
private val modules: List<KtModule>,
private val stdlibs: Set<KtModule>
private val testProjectStructure: KtModuleProjectStructure,
) : ProjectStructureProvider() {
override fun getKtModuleForKtElement(element: PsiElement): KtModule {
return modules.first { module ->
module.contentScope.contains(element)
}
return testProjectStructure.mainModules
.first { module ->
module.ktModule.contentScope.contains(element)
}.ktModule
}
override fun getKtLibraryModules(): Collection<KtLibraryModule> {
return modules.filterIsInstance<KtLibraryModule>()
return testProjectStructure.allKtModules().filterIsInstance<KtLibraryModule>()
}
override fun getStdlibModule(module: KtModule): KtLibraryModule? {
return module.allDirectDependenciesOfType<KtLibraryModule>().firstOrNull { it in stdlibs }
override fun getStdlibWithBuiltinsModule(module: KtModule): KtLibraryModule {
return testProjectStructure.stdlibFor(module)
}
}
}
@@ -46,7 +46,7 @@ object StandaloneProjectFactory {
fun registerServicesForProjectEnvironment(
environment: KotlinCoreProjectEnvironment,
modules: List<KtModuleWithFiles>,
modules: KtModuleProjectStructure,
languageVersionSettings: LanguageVersionSettings,
jdkHome: Path?,
) {
@@ -55,7 +55,7 @@ object StandaloneProjectFactory {
KotlinCoreEnvironment.registerProjectExtensionPoints(project.extensionArea)
KotlinCoreEnvironment.registerProjectServices(project)
project.registerService(ProjectStructureProvider::class.java, KtStaticModuleProvider(modules.map { it.ktModule }, emptySet()))
project.registerService(ProjectStructureProvider::class.java, KtStaticModuleProvider(modules))
initialiseVirtualFinderFinderServices(modules, environment, jdkHome, languageVersionSettings)
initialiseAnnotationServices(project)
@@ -68,7 +68,7 @@ object StandaloneProjectFactory {
}
private fun initialiseVirtualFinderFinderServices(
modules: List<KtModuleWithFiles>,
modules: KtModuleProjectStructure,
environment: KotlinCoreProjectEnvironment,
jdkHome: Path?,
languageVersionSettings: LanguageVersionSettings
@@ -76,12 +76,12 @@ object StandaloneProjectFactory {
val project = environment.project
val allSourceFiles = buildList {
val files = modules.flatMap { it.files }
val files = modules.mainModules.flatMap { it.files }
addAll(files)
addAll(findJvmRootsForJavaFiles(files.filterIsInstance<PsiJavaFile>()))
}
val allSourceFileRoots = allSourceFiles.map { JavaRoot(it.virtualFile, JavaRoot.RootType.SOURCE) }
val libraryRoots = getAllBinaryRoots(modules.map { it.ktModule }, environment)
val libraryRoots = getAllBinaryRoots(modules.allKtModules(), environment)
libraryRoots.forEach { environment.addSourcesToClasspath(it.file) }
val sourceAndLibraryRoots = buildList {
@@ -133,7 +133,7 @@ object StandaloneProjectFactory {
modules: List<KtModule>,
environment: KotlinCoreProjectEnvironment
): List<JavaRoot> = withAllTransitiveDependencies(modules)
.filterIsInstance<KtLibraryModule>()
.filterIsInstance<KtBinaryModule>()
.flatMap { it.getBinaryRoots() }
.map {
val jar = environment.environment.jarFileSystem.findFileByPath(it.toAbsolutePath().toString() + "!/")!!
@@ -39,4 +39,8 @@ internal class KtModuleProviderByCompilerConfiguration(
override fun getKtLibraryModules(): Collection<KtLibraryModule> {
return libraryModules
}
override fun getStdlibWithBuiltinsModule(module: KtModule): KtLibraryModule? {
TODO("Not yet implemented")
}
}
@@ -7,8 +7,8 @@ package org.jetbrains.kotlin.analysis.api.standalone.fir.test
import com.intellij.openapi.Disposable
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.analysis.api.fir.test.configurators.source.AnalysisApiFirSourceTestConfigurator
import org.jetbrains.kotlin.analysis.api.standalone.base.project.structure.KtModuleWithFiles
import org.jetbrains.kotlin.analysis.api.standalone.base.project.structure.KtModuleProjectStructure
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.configurators.AnalysisApiFirSourceTestConfigurator
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
@@ -0,0 +1,25 @@
/*
* 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.utils.errors
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract
@OptIn(ExperimentalContracts::class)
public inline fun <reified T> requireIsInstance(obj: Any) {
contract {
returns() implies (obj is T)
}
require(obj is T) { "Expected ${T::class} instead of ${obj::class} for $obj" }
}
@OptIn(ExperimentalContracts::class)
public inline fun <reified T> checkIsInstance(obj: Any) {
contract {
returns() implies (obj is T)
}
check(obj is T) { "Expected ${T::class} instead of ${obj::class} for $obj" }
}
@@ -9,6 +9,7 @@ dependencies {
testApiJUnit5()
testApi(project(":kotlin-test:kotlin-test-junit"))
testImplementation(project(":analysis:analysis-internal-utils"))
testApi(project(":compiler:psi"))
testApi(project(":analysis:kt-references"))
testApi(projectTests(":compiler:tests-common-new"))
@@ -104,10 +104,7 @@ abstract class AbstractAnalysisApiBasedTest : TestWithDisposable() {
targetPlatform = JvmPlatforms.defaultJvmPlatform
dependencyKind = DependencyKind.Source
}
useConfigurators(
::CommonEnvironmentConfigurator,
::JvmEnvironmentConfigurator,
)
assertions = JUnit5Assertions
useAdditionalService<TemporaryDirectoryManager>(::TemporaryDirectoryManagerImpl)
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.analysis.test.framework.project.structure
import com.intellij.psi.PsiFile
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.project.structure.*
import org.jetbrains.kotlin.test.model.TestModule
@@ -18,17 +19,17 @@ abstract class AnalysisApiKtModuleProvider : TestService {
abstract fun getModuleFiles(module: TestModule): List<PsiFile>
abstract fun registerProjectStructure(modules: List<KtModuleWithFiles>)
abstract fun registerProjectStructure(modules: KtModuleProjectStructure)
protected abstract fun getModuleName(ktModule: KtModule): String
abstract fun getAllModules(): List<KtModuleWithFiles>
abstract fun getModuleStructure(): KtModuleProjectStructure
}
class AnalysisApiKtModuleProviderImpl(
override val testServices: TestServices,
) : AnalysisApiKtModuleProvider() {
private lateinit var modules: List<KtModuleWithFiles>
private lateinit var modulesStructure: KtModuleProjectStructure
private lateinit var modulesByName: Map<String, KtModuleWithFiles>
override fun getModule(moduleName: String): KtModule {
@@ -37,12 +38,12 @@ class AnalysisApiKtModuleProviderImpl(
override fun getModuleFiles(module: TestModule): List<PsiFile> = modulesByName.getValue(module.name).files
override fun registerProjectStructure(modules: List<KtModuleWithFiles>) {
require(!this::modules.isInitialized)
override fun registerProjectStructure(modules: KtModuleProjectStructure) {
require(!this::modulesStructure.isInitialized)
require(!this::modulesByName.isInitialized)
this.modules = modules
this.modulesByName = modules.associateBy { getModuleName(it.ktModule) }
this.modulesStructure = modules
this.modulesByName = modulesStructure.mainModules.associateBy { getModuleName(it.ktModule) }
}
override fun getModuleName(ktModule: KtModule): String = when (ktModule) {
@@ -54,7 +55,7 @@ class AnalysisApiKtModuleProviderImpl(
}
override fun getAllModules(): List<KtModuleWithFiles> = modules
override fun getModuleStructure(): KtModuleProjectStructure = modulesStructure
}
val TestServices.ktModuleProvider: AnalysisApiKtModuleProvider by TestServices.testServiceAccessor()
@@ -31,7 +31,7 @@ import java.nio.file.Path
import java.nio.file.Paths
@OptIn(ExperimentalStdlibApi::class)
abstract class TestKtModule(
abstract class KtModuleByCompilerConfiguration(
val project: Project,
val testModule: TestModule,
val psiFiles: List<PsiFile>,
@@ -91,25 +91,25 @@ abstract class TestKtModule(
get() = testModule.targetPlatform.getAnalyzerServices()
}
class TestKtSourceModule(
class KtSourceModuleByCompilerConfiguration(
project: Project,
testModule: TestModule,
psiFiles: List<PsiFile>,
testServices: TestServices
) : TestKtModule(project, testModule, psiFiles, testServices), KtSourceModule {
) : KtModuleByCompilerConfiguration(project, testModule, psiFiles, testServices), KtSourceModule {
override val ktModule: KtModule get() = this
override val contentScope: GlobalSearchScope =
TopDownAnalyzerFacadeForJVM.newModuleSearchScope(project, psiFiles.filterIsInstance<KtFile>())
}
class TestKtLibraryModule(
class KtLibraryModuleByCompilerConfiguration(
project: Project,
testModule: TestModule,
psiFiles: List<PsiFile>,
private val binaryRoots: List<Path>,
testServices: TestServices
) : TestKtModule(project, testModule, psiFiles, testServices), KtLibraryModule {
) : KtModuleByCompilerConfiguration(project, testModule, psiFiles, testServices), KtLibraryModule {
override val ktModule: KtModule get() = this
override val libraryName: String get() = testModule.name
override val librarySources: KtLibrarySourceModule? get() = null
@@ -120,13 +120,13 @@ class TestKtLibraryModule(
GlobalSearchScope.filesScope(project, psiFiles.map { it.virtualFile })
}
class TestKtLibrarySourceModule(
class KtLibrarySourceModuleByCompilerConfiguration(
project: Project,
testModule: TestModule,
psiFiles: List<PsiFile>,
testServices: TestServices,
override val binaryLibrary: KtLibraryModule,
) : TestKtModule(project, testModule, psiFiles, testServices), KtLibrarySourceModule {
) : KtModuleByCompilerConfiguration(project, testModule, psiFiles, testServices), KtLibrarySourceModule {
override val ktModule: KtModule get() = this
override val contentScope: GlobalSearchScope get() = GlobalSearchScope.filesScope(project, psiFiles.map { it.virtualFile })
@@ -0,0 +1,83 @@
/*
* 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.test.framework.project.structure
import com.intellij.openapi.project.Project
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.analysis.project.structure.*
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices
import org.jetbrains.kotlin.test.frontend.fir.getAnalyzerServices
import java.nio.file.Path
interface KtModuleWithModifiableDependencies {
val directRegularDependencies: MutableList<KtModule>
val directRefinementDependencies: MutableList<KtModule>
val directFriendDependencies: MutableList<KtModule>
}
class KtSourceModuleImpl(
override val moduleName: String,
override val platform: TargetPlatform,
override val languageVersionSettings: LanguageVersionSettings,
override val project: Project,
override val contentScope: GlobalSearchScope,
) : KtSourceModule, KtModuleWithModifiableDependencies {
override val analyzerServices: PlatformDependentAnalyzerServices get() = platform.getAnalyzerServices()
override val directRegularDependencies: MutableList<KtModule> = mutableListOf()
override val directRefinementDependencies: MutableList<KtModule> = mutableListOf()
override val directFriendDependencies: MutableList<KtModule> = mutableListOf()
}
class KtJdkModuleImpl(
override val sdkName: String,
override val platform: TargetPlatform,
override val contentScope: GlobalSearchScope,
override val project: Project,
private val binaryRoots: Collection<Path>,
) : KtSdkModule, KtModuleWithModifiableDependencies {
override val analyzerServices: PlatformDependentAnalyzerServices
get() = platform.getAnalyzerServices()
override fun getBinaryRoots(): Collection<Path> = binaryRoots
override val directRegularDependencies: MutableList<KtModule> = mutableListOf()
override val directRefinementDependencies: MutableList<KtModule> = mutableListOf()
override val directFriendDependencies: MutableList<KtModule> = mutableListOf()
}
class KtLibraryModuleImpl(
override val libraryName: String,
override val platform: TargetPlatform,
override val contentScope: GlobalSearchScope,
override val project: Project,
private val binaryRoots: Collection<Path>,
override var librarySources: KtLibrarySourceModule?,
val isBuitinsContainingStdlib: Boolean,
) : KtLibraryModule, KtModuleWithModifiableDependencies {
override val analyzerServices: PlatformDependentAnalyzerServices get() = platform.getAnalyzerServices()
override fun getBinaryRoots(): Collection<Path> = binaryRoots
override val directRegularDependencies: MutableList<KtModule> = mutableListOf()
override val directRefinementDependencies: MutableList<KtModule> = mutableListOf()
override val directFriendDependencies: MutableList<KtModule> = mutableListOf()
}
class KtLibrarySourceModuleImpl(
override val libraryName: String,
override val platform: TargetPlatform,
override val contentScope: GlobalSearchScope,
override val project: Project,
override val binaryLibrary: KtLibraryModule,
) : KtLibrarySourceModule, KtModuleWithModifiableDependencies {
override val analyzerServices: PlatformDependentAnalyzerServices get() = platform.getAnalyzerServices()
override val directRegularDependencies: MutableList<KtModule> = mutableListOf()
override val directRefinementDependencies: MutableList<KtModule> = mutableListOf()
override val directFriendDependencies: MutableList<KtModule> = mutableListOf()
}
@@ -0,0 +1,249 @@
/*
* 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.test.framework.project.structure
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiFile
import com.intellij.psi.PsiManager
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.search.ProjectScope
import org.jetbrains.kotlin.analysis.api.standalone.base.project.structure.KtModuleWithFiles
import org.jetbrains.kotlin.analysis.api.standalone.base.project.structure.KtModuleProjectStructure
import org.jetbrains.kotlin.analysis.project.structure.KtBinaryModule
import org.jetbrains.kotlin.analysis.project.structure.KtLibraryModule
import org.jetbrains.kotlin.analysis.project.structure.KtModule
import org.jetbrains.kotlin.analysis.project.structure.allDirectDependenciesOfType
import org.jetbrains.kotlin.analysis.test.framework.services.environmentManager
import org.jetbrains.kotlin.analysis.utils.errors.checkIsInstance
import org.jetbrains.kotlin.analysis.utils.errors.requireIsInstance
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.jvm.config.JvmClasspathRoot
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
import org.jetbrains.kotlin.test.TestInfrastructureInternals
import org.jetbrains.kotlin.test.model.DependencyRelation
import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.services.*
import org.jetbrains.kotlin.test.services.configuration.JvmEnvironmentConfigurator
import org.jetbrains.kotlin.test.util.KtTestUtil
import org.jetbrains.kotlin.utils.KotlinPaths
import org.jetbrains.kotlin.utils.PathUtil
import org.jetbrains.kotlin.utils.addIfNotNull
import java.nio.file.Path
import kotlin.io.path.exists
import kotlin.io.path.extension
import kotlin.io.path.nameWithoutExtension
fun interface KtMainModuleFactory {
fun createMainModule(
testModule: TestModule,
testServices: TestServices,
project: Project,
): KtModuleWithFiles
}
object KtMainModuleFactoryForSourceModules : KtMainModuleFactory {
override fun createMainModule(
testModule: TestModule,
testServices: TestServices,
project: Project,
): KtModuleWithFiles {
val psiFiles = TestModuleStructureFactory.createSourcePsiFiles(testModule, testServices, project)
return KtModuleWithFiles(
KtSourceModuleImpl(
testModule.name,
testModule.targetPlatform,
testModule.languageVersionSettings,
project,
GlobalSearchScope.filesScope(project, psiFiles.mapTo(mutableSetOf()) { it.virtualFile }),
),
psiFiles
)
}
}
object TestModuleStructureFactory {
@OptIn(TestInfrastructureInternals::class)
fun createProjectStructureByTestStructure(
moduleStructure: TestModuleStructure,
testServices: TestServices,
project: Project,
mainModuleFactory: KtMainModuleFactory
): KtModuleProjectStructure {
val modulesFromTestServices = moduleStructure.modules.map { testModule ->
testModule.toKtModule(testServices, project, mainModuleFactory)
}
val moduleByName = modulesFromTestServices.associateBy { getModuleName(it.ktModule) }
val binaryModulesBySourceRoots = mutableMapOf<Set<Path>, KtBinaryModule>()
moduleStructure.modules.forEach { testModule ->
val ktModule = moduleByName.getValue(testModule.name).ktModule
checkIsInstance<KtModuleWithModifiableDependencies>(ktModule)
addModuleDependencies(testModule, moduleByName, ktModule)
buildList {
addIfNotNull(getJdkModule(testModule, project))
addAll(getStdlibModules(testModule, project))
addAll(getLibraryModules(testServices, testModule, project))
addAll(createLibrariesByCompilerConfigurators(testModule, testServices, project))
}.forEach { library ->
val cachedLibrary = binaryModulesBySourceRoots.getOrPut(library.getBinaryRoots().toSet()) { library }
ktModule.directRegularDependencies.add(cachedLibrary)
}
}
return KtModuleProjectStructure(modulesFromTestServices, binaryModulesBySourceRoots.values) { module ->
module.allDirectDependenciesOfType<KtLibraryModuleImpl>().first { it.isBuitinsContainingStdlib }
}
}
@OptIn(TestInfrastructureInternals::class)
private fun createLibrariesByCompilerConfigurators(
testModule: TestModule,
testServices: TestServices,
project: Project
): List<KtLibraryModuleImpl> {
val compilerConfiguration = createCompilerConfiguration(testModule, testServices.environmentConfigurators)
val contentRoots = compilerConfiguration[CLIConfigurationKeys.CONTENT_ROOTS, emptyList()]
return contentRoots
.filterIsInstance<JvmClasspathRoot>()
.map { root -> createKtLibraryModuleByJar(root.file.toPath(), project, isBuitinsContainingStdlib = false) }
}
private fun getModuleName(ktModule: KtModule) = when (ktModule) {
is KtSourceModuleImpl -> ktModule.moduleName
is KtLibraryModuleImpl -> ktModule.libraryName
is KtLibrarySourceModuleImpl -> ktModule.libraryName
else -> error("Unknown module ${ktModule::class}")
}
private fun addModuleDependencies(
testModule: TestModule,
moduleByName: Map<String, KtModuleWithFiles>,
ktModule: KtModule
) {
requireIsInstance<KtModuleWithModifiableDependencies>(ktModule)
testModule.allDependencies.forEach { dependency ->
val dependencyKtModule = moduleByName.getValue(dependency.moduleName).ktModule
when (dependency.relation) {
DependencyRelation.RegularDependency -> ktModule.directRegularDependencies.add(dependencyKtModule)
DependencyRelation.FriendDependency -> ktModule.directFriendDependencies.add(dependencyKtModule)
DependencyRelation.DependsOnDependency -> ktModule.directRefinementDependencies.add(dependencyKtModule)
}
}
}
private fun getLibraryModules(
testServices: TestServices,
testModule: TestModule,
project: Project
): List<KtLibraryModuleImpl> {
val configurationKind = JvmEnvironmentConfigurator.extractConfigurationKind(testModule.directives)
return JvmEnvironmentConfigurator
.getLibraryFilesExceptRealRuntime( testServices, configurationKind, testModule.directives)
.map { it.toPath().toAbsolutePath() }
.map { jar ->
createKtLibraryModuleByJar(
jar,
project,
isBuitinsContainingStdlib = jar.nameWithoutExtension == "kotlin-stdlib-jvm-minimal-for-test"
)
}
}
private fun createKtLibraryModuleByJar(
jar: Path,
project: Project,
libraryName: String = jar.nameWithoutExtension,
isBuitinsContainingStdlib: Boolean = false,
): KtLibraryModuleImpl {
check(jar.extension == "jar")
check(jar.exists())
return KtLibraryModuleImpl(
libraryName,
JvmPlatforms.defaultJvmPlatform,
ProjectScope.getLibrariesScope(project),
project,
listOf(jar),
librarySources = null,
isBuitinsContainingStdlib,
)
}
private fun getStdlibModules(
testModule: TestModule,
project: Project
): List<KtLibraryModule> {
val configurationKind = JvmEnvironmentConfigurator.extractConfigurationKind(testModule.directives)
if (!configurationKind.withRuntime) return emptyList()
return listOf(
KotlinPaths.Jar.StdLib to PathUtil.KOTLIN_JAVA_STDLIB_NAME,
).map { (jar, name) ->
val lib = PathUtil.kotlinPathsForDistDirectory.jar(jar).toPath().toAbsolutePath()
createKtLibraryModuleByJar(lib, project, name, isBuitinsContainingStdlib = jar == KotlinPaths.Jar.StdLib)
}
}
private fun getJdkModule(
testModule: TestModule,
project: Project
): KtJdkModuleImpl? {
val jdkKind = JvmEnvironmentConfigurator.extractJdkKind(testModule.directives)
val jdkSourceRoots = buildList {
JvmEnvironmentConfigurator.getJdkHome(jdkKind)?.let { add(it.toPath()) }
JvmEnvironmentConfigurator.getJdkClasspathRoot(jdkKind)?.let { add(it.toPath()) }
}.mapTo(mutableListOf()) { it.toAbsolutePath() }
if (jdkSourceRoots.isEmpty()) return null
return KtJdkModuleImpl(
"jdk",
JvmPlatforms.defaultJvmPlatform,
ProjectScope.getLibrariesScope(project),
project,
jdkSourceRoots
)
}
private fun TestModule.toKtModule(
testServices: TestServices,
project: Project,
mainModuleFactory: KtMainModuleFactory,
): KtModuleWithFiles {
return mainModuleFactory.createMainModule(this, testServices, project)
}
fun createSourcePsiFiles(
testModule: TestModule,
testServices: TestServices,
project: Project
): List<PsiFile> {
return testModule.files.map { testFile ->
when {
testFile.isKtFile -> {
val fileText = testServices.sourceFileProvider.getContentOfSourceFile(testFile)
KtTestUtil.createFile(testFile.name, fileText, project)
}
testFile.isJavaFile -> {
val filePath = testServices.sourceFileProvider.getRealFileForSourceFile(testFile)
val virtualFile =
testServices.environmentManager.getApplicationEnvironment().localFileSystem.findFileByIoFile(filePath)
?: error("Virtual file not found for $filePath")
PsiManager.getInstance(project).findFile(virtualFile)
?: error("PsiFile file not found for $filePath")
}
else -> error("Unexpected file ${testFile.name}")
}
}
}
}
@@ -1,56 +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.test.framework.project.structure
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiManager
import org.jetbrains.kotlin.analysis.api.standalone.base.project.structure.KtModuleWithFiles
import org.jetbrains.kotlin.analysis.test.framework.services.environmentManager
import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.services.*
import org.jetbrains.kotlin.test.util.KtTestUtil
fun getKtFilesFromModule(testServices: TestServices, testModule: TestModule): List<KtFile> {
val moduleInfoProvider = testServices.ktModuleProvider
return when (val moduleInfo = moduleInfoProvider.getModule(testModule.name)) {
is TestKtSourceModule -> moduleInfo.psiFiles.filterIsInstance<KtFile>()
is TestKtLibraryModule -> moduleInfo.psiFiles.filterIsInstance<KtFile>()
is TestKtLibrarySourceModule -> moduleInfo.psiFiles.filterIsInstance<KtFile>()
else -> error("Unexpected $moduleInfo")
}
}
fun TestModuleStructure.toKtSourceModules(testServices: TestServices, project: Project) =
modules.map { testModule -> testModule.toKtSourceModule(testServices, project) }
fun TestModule.toKtSourceModule(testServices: TestServices, project: Project): KtModuleWithFiles {
val files = files.map { testFile ->
when {
testFile.isKtFile -> {
val fileText = testServices.sourceFileProvider.getContentOfSourceFile(testFile)
KtTestUtil.createFile(testFile.name, fileText, project)
}
testFile.isJavaFile -> {
val filePath = testServices.sourceFileProvider.getRealFileForSourceFile(testFile)
val virtualFile =
testServices.environmentManager.getApplicationEnvironment().localFileSystem.findFileByIoFile(filePath)
?: error("Virtual file not found for $filePath")
PsiManager.getInstance(project).findFile(virtualFile)
?: error("PsiFile file not found for $filePath")
}
else -> error("Unexpected file ${testFile.name}")
}
}
return KtModuleWithFiles(
TestKtSourceModule(project, this, files, testServices),
files
)
}
@@ -52,7 +52,7 @@ class AnalysisApiEnvironmentManagerImpl(
}
override fun initializeProjectStructure() {
val ktModules = testServices.ktModuleProvider.getAllModules()
val ktModules = testServices.ktModuleProvider.getModuleStructure()
val useSiteModule = testServices.moduleStructure.modules.first()
val useSiteCompilerConfiguration = testServices.compilerConfigurationProvider.getCompilerConfiguration(useSiteModule)
@@ -29,7 +29,7 @@ class AnalysisApiTestCompilerConfiguratorProvider(
private val allProjectBinaryRoots by lazy {
StandaloneProjectFactory.getAllBinaryRoots(
testServices.ktModuleProvider.getAllModules().map { it.ktModule },
testServices.ktModuleProvider.getModuleStructure().allKtModules(),
testServices.environmentManager.getProjectEnvironment()
)
}
@@ -12,7 +12,7 @@ import com.intellij.openapi.application.Application
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Key
import com.intellij.psi.PsiFile
import org.jetbrains.kotlin.analysis.api.standalone.base.project.structure.KtModuleWithFiles
import org.jetbrains.kotlin.analysis.api.standalone.base.project.structure.KtModuleProjectStructure
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.NotNullableUserDataProperty
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
@@ -40,7 +40,7 @@ abstract class AnalysisApiTestConfigurator {
open fun preprocessTestDataPath(path: Path): Path = path
abstract fun createModules(moduleStructure: TestModuleStructure, testServices: TestServices, project: Project): List<KtModuleWithFiles>
abstract fun createModules(moduleStructure: TestModuleStructure, testServices: TestServices, project: Project): KtModuleProjectStructure
fun registerProjectExtensionPoints(project: MockProject, testServices: TestServices) {
serviceRegistrars.forEach { it.registerProjectExtensionPoints(project, testServices) }
@@ -43,6 +43,11 @@ dependencies {
testImplementation(project(":analysis:symbol-light-classes"))
testRuntimeOnly(project(":core:descriptors.runtime"))
// We use 'api' instead of 'implementation' because other modules might be using these jars indirectly
testApi(project(":plugins:fir-plugin-prototype"))
testApi(projectTests(":plugins:fir-plugin-prototype"))
}
sourceSets {
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.fir.checkers.registerExtendedCommonCheckers
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.declarations.SealedClassInheritorsProvider
import org.jetbrains.kotlin.fir.deserialization.EmptyModuleDataProvider
import org.jetbrains.kotlin.fir.deserialization.LibraryPathFilter
import org.jetbrains.kotlin.fir.deserialization.ModuleDataProvider
import org.jetbrains.kotlin.fir.deserialization.MultipleModuleDataProvider
@@ -261,11 +262,17 @@ internal object LLFirSessionFactory {
addAll(dependsOnDependenciesOnLibs)
}
if (allDependencies.isEmpty()) {
return EmptyModuleDataProvider(sourceModule.platform, sourceModule.analyzerServices)
}
allDependencies.forEach { it.bindSession(session) }
val moduleDataWithFilters: Map<FirModuleData, LibraryPathFilter.LibraryList> =
allDependencies.associateWith { moduleData ->
LibraryPathFilter.LibraryList((moduleData.module as KtBinaryModule).getBinaryRoots().toSet())
val ktBinaryModule = moduleData.module as KtBinaryModule
val moduleBinaryRoots = ktBinaryModule.getBinaryRoots().mapTo(mutableSetOf()) { it.toAbsolutePath() }
LibraryPathFilter.LibraryList(moduleBinaryRoots)
}
return MultipleModuleDataProvider(moduleDataWithFilters)
@@ -13,10 +13,7 @@ import kotlinx.collections.immutable.toPersistentMap
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirPhaseRunner
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.addValueFor
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.executeWithoutPCE
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.project.structure.KtSourceModule
import org.jetbrains.kotlin.analysis.project.structure.*
import org.jetbrains.kotlin.analysis.providers.createLibrariesModificationTracker
import org.jetbrains.kotlin.analysis.providers.createModuleWithoutDependenciesOutOfBlockModificationTracker
import org.jetbrains.kotlin.analysis.utils.caches.getValue
@@ -38,7 +35,9 @@ class LLFirSessionProviderStorage(val project: Project) {
val firPhaseRunner = LLFirPhaseRunner()
val builtinTypes = BuiltinTypes()
val builtinsAndCloneableSession = LLFirSessionFactory.createBuiltinsAndCloneableSession(project, builtinTypes)
val stdlibModule = project.getService(ProjectStructureProvider::class.java).getStdlibWithBuiltinsModule(rootModule)
?: error("Stdlib was not found for ${rootModule.moduleDescription}")
val builtinsAndCloneableSession = LLFirSessionFactory.createBuiltinsAndCloneableSession(project, builtinTypes, stdlibModule)
val cache = sessionsCache.getOrPut(rootModule) { FromModuleViewSessionCache() }
val (sessions, session) = cache.withMappings(project) { mappings ->
val sessions = mutableMapOf<KtModule, LLFirResolvableModuleSession>().apply { putAll(mappings) }
@@ -9,11 +9,10 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.compiler.based
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.DiagnosticCheckerFilter
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirFile
import org.jetbrains.kotlin.analysis.low.level.api.fir.createResolveStateForNoCaching
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.FirLowLevelAnalysisApiTestConfigurator
import org.jetbrains.kotlin.analysis.low.level.api.fir.transformers.LLFirLazyTransformer
import org.jetbrains.kotlin.analysis.test.framework.AbstractCompilerBasedTest
import org.jetbrains.kotlin.analysis.test.framework.base.registerAnalysisApiBaseTestServices
import org.jetbrains.kotlin.analysis.test.framework.project.structure.TestKtSourceModule
import org.jetbrains.kotlin.analysis.test.framework.project.structure.KtSourceModuleByCompilerConfiguration
import org.jetbrains.kotlin.analysis.test.framework.project.structure.ktModuleProvider
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
import org.jetbrains.kotlin.psi.KtFile
@@ -34,6 +33,7 @@ import org.jetbrains.kotlin.test.services.TestServices
import org.jetbrains.kotlin.test.services.compilerConfigurationProvider
import org.jetbrains.kotlin.test.services.isKtFile
import org.jetbrains.kotlin.test.services.*
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.FirLowLevelCompilerBasedTestConfigurator
abstract class AbstractCompilerBasedTestForFir : AbstractCompilerBasedTest() {
@OptIn(TestInfrastructureInternals::class)
@@ -64,14 +64,14 @@ abstract class AbstractCompilerBasedTestForFir : AbstractCompilerBasedTest() {
override fun analyze(module: TestModule): FirOutputArtifact {
val moduleInfoProvider = testServices.ktModuleProvider
val moduleInfo = moduleInfoProvider.getModule(module.name) as TestKtSourceModule
val ktModule = moduleInfoProvider.getModule(module.name) as KtSourceModuleByCompilerConfiguration
val project = testServices.compilerConfigurationProvider.getProject(module)
val resolveState = createResolveStateForNoCaching(moduleInfo, project)
val resolveState = createResolveStateForNoCaching(ktModule, project)
val allFirFiles =
module.files.filter { it.isKtFile }.zip(
moduleInfo.psiFiles
ktModule.psiFiles
.filterIsInstance<KtFile>()
.map { psiFile -> psiFile.getOrBuildFirFile(resolveState) }
)
@@ -87,6 +87,7 @@ abstract class AbstractCompilerBasedTestForFir : AbstractCompilerBasedTest() {
override fun runTest(filePath: String) {
val configuration = testConfiguration(filePath, configuration)
if (ignoreTest(filePath, configuration)) {
return
}
@@ -8,12 +8,13 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.compiler.based
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirFile
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getResolveState
import org.jetbrains.kotlin.analysis.project.structure.ProjectStructureProvider
import org.jetbrains.kotlin.analysis.test.framework.project.structure.getKtFilesFromModule
import org.jetbrains.kotlin.analysis.test.framework.project.structure.ktModuleProvider
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.transformers.FirSealedClassInheritorsProcessor
import org.jetbrains.kotlin.fir.symbols.ensureResolved
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.services.PreAnalysisHandler
import org.jetbrains.kotlin.test.services.TestModuleStructure
import org.jetbrains.kotlin.test.services.TestServices
@@ -28,7 +29,7 @@ class SealedClassesInheritorsCaclulatorPreAnalysisHandler(
override fun prepareSealedClassInheritors(moduleStructure: TestModuleStructure) {
val ktFilesByModule = moduleStructure.modules.associateWith { testModule ->
getKtFilesFromModule(testServices, testModule)
testServices.ktModuleProvider.getModuleFiles(testModule).filterIsInstance<KtFile>()
}
ktFilesByModule.forEach { (testModule, ktFiles) ->
@@ -5,10 +5,11 @@
package org.jetbrains.kotlin.analysis.low.level.api.fir.test.base
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.configurators.AnalysisApiFirSourceTestConfigurator
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiTestConfigurator
import org.jetbrains.kotlin.analysis.test.framework.base.AbstractAnalysisApiBasedTest
abstract class AbstractLowLevelApiSingleModuleTest : AbstractAnalysisApiBasedTest() {
override val configurator: AnalysisApiTestConfigurator get() = FirLowLevelAnalysisApiTestConfigurator
override val configurator: AnalysisApiTestConfigurator = AnalysisApiFirSourceTestConfigurator(analyseInDependentSession = false)
}
@@ -0,0 +1,83 @@
/*
* Copyright 2010-2021 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.low.level.api.fir.test.base
import com.intellij.openapi.Disposable
import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.project.Project
import com.intellij.psi.search.ProjectScope
import org.jetbrains.kotlin.analysis.low.level.api.fir.compiler.based.SealedClassesInheritorsCaclulatorPreAnalysisHandler
import org.jetbrains.kotlin.analysis.providers.KotlinModificationTrackerFactory
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 org.jetbrains.kotlin.analysis.api.impl.base.test.configurators.AnalysisApiBaseTestServiceRegistrar
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.project.structure.KtLibraryModule
import org.jetbrains.kotlin.analysis.project.structure.KtModule
import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule
import org.jetbrains.kotlin.analysis.project.structure.allDirectDependenciesOfType
import org.jetbrains.kotlin.analysis.test.framework.base.registerAnalysisApiBaseTestServices
import org.jetbrains.kotlin.analysis.test.framework.project.structure.KtLibraryModuleImpl
import org.jetbrains.kotlin.analysis.test.framework.project.structure.KtSourceModuleByCompilerConfiguration
import org.jetbrains.kotlin.analysis.test.framework.project.structure.TestModuleStructureFactory
import org.jetbrains.kotlin.platform.TargetPlatform
object FirLowLevelCompilerBasedTestConfigurator : AnalysisApiTestConfigurator() {
override val analyseInDependentSession: Boolean get() = false
override fun configureTest(builder: TestConfigurationBuilder, disposable: Disposable) {
builder.apply {
}
}
override val serviceRegistrars: List<AnalysisApiTestServiceRegistrar> = listOf(
AnalysisApiBaseTestServiceRegistrar,
AnalysisApiFirTestServiceRegistrar,
)
override fun createModules(
moduleStructure: TestModuleStructure,
testServices: TestServices,
project: Project
): KtModuleProjectStructure {
val mainModules = moduleStructure.modules.map { testModule ->
val files = TestModuleStructureFactory.createSourcePsiFiles(testModule, testServices, project)
KtModuleWithFiles(
KtSourceModuleByCompilerConfiguration(project, testModule, files, testServices),
files
)
}
return KtModuleProjectStructure(
mainModules = mainModules,
binaryModules = mainModules.asSequence().flatMap { it.ktModule.allDirectDependenciesOfType<KtLibraryModule>() }.asIterable(),
stdlibFor = { module ->
createFakeStdlibModule(module, project)
}
)
}
private fun createFakeStdlibModule(
module: KtModule,
project: Project
): KtLibraryModule = KtLibraryModuleImpl(
libraryName = "fake-std-lib",
platform = module.platform,
contentScope = ProjectScope.getLibrariesScope(project),
project = project,
binaryRoots = emptyList(),
librarySources = null,
isBuitinsContainingStdlib = true
)
override fun doOutOfBlockModification(file: KtFile) {
error("Should not be called for compiler based tests")
}
}
@@ -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.low.level.api.fir.test.base
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.config.AnalysisFlag
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.LanguageVersion
import org.jetbrains.kotlin.fir.plugin.services.ExtensionRegistrarConfigurator
import org.jetbrains.kotlin.fir.plugin.services.PluginAnnotationsProvider
import org.jetbrains.kotlin.test.Constructor
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
import org.jetbrains.kotlin.test.directives.model.Directive
import org.jetbrains.kotlin.test.directives.model.DirectiveApplicability
import org.jetbrains.kotlin.test.directives.model.RegisteredDirectives
import org.jetbrains.kotlin.test.directives.model.SimpleDirectivesContainer
import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.services.AbstractEnvironmentConfigurator
private object CompilerPluginsDirectives : SimpleDirectivesContainer() {
val WITH_FIR_TEST_COMPILER_PLUGIN by directive(
description = "Configure test compiler plugin from :plugins:fir-plugin-prototype module",
applicability = DirectiveApplicability.Global
)
}
internal fun TestConfigurationBuilder.configureOptionalTestCompilerPlugin() {
useDirectives(CompilerPluginsDirectives)
useConfigurators(
::PluginAnnotationsProvider.enabledByDirective(CompilerPluginsDirectives.WITH_FIR_TEST_COMPILER_PLUGIN),
::ExtensionRegistrarConfigurator.enabledByDirective(CompilerPluginsDirectives.WITH_FIR_TEST_COMPILER_PLUGIN),
)
}
private fun Constructor<AbstractEnvironmentConfigurator>.enabledByDirective(
directive: Directive
): Constructor<AbstractEnvironmentConfigurator> {
val originalConstructor = this
return { testServices -> EnabledByDirectiveConfiguratorDecorator(originalConstructor(testServices), directive) }
}
private class EnabledByDirectiveConfiguratorDecorator(
private val original: AbstractEnvironmentConfigurator,
private val directive: Directive
) : AbstractEnvironmentConfigurator() {
override fun configureCompileConfigurationWithAdditionalConfigurationKeys(configuration: CompilerConfiguration, module: TestModule) {
if (directive !in module.directives) return
original.configureCompileConfigurationWithAdditionalConfigurationKeys(configuration, module)
}
override fun provideAdditionalAnalysisFlags(
directives: RegisteredDirectives,
languageVersion: LanguageVersion
): Map<AnalysisFlag<*>, Any?> = original.provideAdditionalAnalysisFlags(directives, languageVersion)
override fun registerCompilerExtensions(project: Project, module: TestModule, configuration: CompilerConfiguration) {
if (directive !in module.directives) return
original.registerCompilerExtensions(project, module, configuration)
}
}
@@ -1,31 +1,33 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.low.level.api.fir.test.base
package org.jetbrains.kotlin.analysis.low.level.api.fir.test.configurators
import com.intellij.openapi.Disposable
import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.analysis.api.standalone.base.project.structure.KtModuleWithFiles
import org.jetbrains.kotlin.analysis.api.impl.base.test.configurators.AnalysisApiBaseTestServiceRegistrar
import org.jetbrains.kotlin.analysis.api.standalone.base.project.structure.KtModuleProjectStructure
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.configureOptionalTestCompilerPlugin
import org.jetbrains.kotlin.analysis.providers.KotlinModificationTrackerFactory
import org.jetbrains.kotlin.analysis.test.framework.project.structure.toKtSourceModules
import org.jetbrains.kotlin.analysis.test.framework.project.structure.KtMainModuleFactoryForSourceModules
import org.jetbrains.kotlin.analysis.test.framework.project.structure.TestModuleStructureFactory
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 org.jetbrains.kotlin.analysis.api.impl.base.test.configurators.AnalysisApiBaseTestServiceRegistrar
object FirLowLevelAnalysisApiTestConfigurator : AnalysisApiTestConfigurator() {
override val analyseInDependentSession: Boolean get() = false
class AnalysisApiFirSourceTestConfigurator(override val analyseInDependentSession: Boolean) : AnalysisApiTestConfigurator() {
override fun configureTest(builder: TestConfigurationBuilder, disposable: Disposable) {
builder.apply {
usePreAnalysisHandlers(::SealedClassesInheritorsCaclulatorPreAnalysisHandler)
configureOptionalTestCompilerPlugin()
}
}
@@ -38,12 +40,17 @@ object FirLowLevelAnalysisApiTestConfigurator : AnalysisApiTestConfigurator() {
moduleStructure: TestModuleStructure,
testServices: TestServices,
project: Project
): List<KtModuleWithFiles> {
return moduleStructure.toKtSourceModules(testServices, project)
): KtModuleProjectStructure {
return TestModuleStructureFactory.createProjectStructureByTestStructure(
moduleStructure,
testServices,
project,
KtMainModuleFactoryForSourceModules,
)
}
override fun doOutOfBlockModification(file: KtFile) {
ServiceManager.getService(file.project, KotlinModificationTrackerFactory::class.java)
.incrementModificationsCount()
}
}
}
@@ -20,7 +20,7 @@ public abstract class ProjectStructureProvider {
// TODO: We rather need a session or facade that maintains this information.
public abstract fun getKtLibraryModules(): Collection<KtLibraryModule>
public abstract fun getStdlibModule(module: KtModule): KtLibraryModule?
public abstract fun getStdlibWithBuiltinsModule(module: KtModule): KtLibraryModule?
}
/**
@@ -6,13 +6,31 @@
package org.jetbrains.kotlin.analysis.project.structure
/**
* A list of all modules current module can depend onwith regular dependency
* A list of all modules current module can depend on with regular dependency
*
* @see KtModule.directRegularDependencies
*/
public inline fun <reified M : KtModule> KtModule.directRegularDependenciesOfType(): Sequence<M> =
directRegularDependencies.asSequence().filterIsInstance<M>()
/**
* A list of all modules current module can depend on with friend dependency
*
* @see KtModule.directFriendDependencies
*/
public inline fun <reified M : KtModule> KtModule.directFriendDependenciesOfType(): Sequence<M> =
directFriendDependencies.asSequence().filterIsInstance<M>()
/**
* A list of all modules current module can depend on with refinement dependency
*
* @see KtModule.directRefinementDependencies
*/
public inline fun <reified M : KtModule> KtModule.directRefinementDependenciesOfType(): Sequence<M> =
directRefinementDependencies.asSequence().filterIsInstance<M>()
/**
* A list of all other modules current module can depend on.
*
@@ -8,7 +8,7 @@ package org.jetbrains.kotlin.light.classes.symbol.decompiled.test.configurators
import com.intellij.openapi.Disposable
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.analysis.api.fir.test.configurators.library.AnalysisApiFirLibraryBinaryTestConfigurator
import org.jetbrains.kotlin.analysis.api.standalone.base.project.structure.KtModuleWithFiles
import org.jetbrains.kotlin.analysis.api.standalone.base.project.structure.KtModuleProjectStructure
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
@@ -35,7 +35,7 @@ object AnalysisApiSymbolLightClassesDecompiledTestConfigurator : AnalysisApiTest
moduleStructure: TestModuleStructure,
testServices: TestServices,
project: Project
): List<KtModuleWithFiles> {
): KtModuleProjectStructure {
return AnalysisApiFirLibraryBinaryTestConfigurator.createModules(moduleStructure, testServices, project)
}
}
@@ -5,7 +5,7 @@
package org.jetbrains.kotlin.light.classes.symbol.source
import org.jetbrains.kotlin.analysis.api.fir.test.configurators.source.AnalysisApiFirSourceTestConfigurator
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.configurators.AnalysisApiFirSourceTestConfigurator
import org.jetbrains.kotlin.light.classes.symbol.base.AbstractSymbolLightClassesFacadeTest
abstract class AbstractSymbolLightClassesFacadeForSourceTest :
@@ -5,7 +5,7 @@
package org.jetbrains.kotlin.light.classes.symbol.source
import org.jetbrains.kotlin.analysis.api.fir.test.configurators.source.AnalysisApiFirSourceTestConfigurator
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.configurators.AnalysisApiFirSourceTestConfigurator
import org.jetbrains.kotlin.light.classes.symbol.base.AbstractSymbolLightClassesTest
abstract class AbstractSymbolLightClassesForSourceTest :
@@ -5,7 +5,7 @@
package org.jetbrains.kotlin.light.classes.symbol.source
import org.jetbrains.kotlin.analysis.api.fir.test.configurators.source.AnalysisApiFirSourceTestConfigurator
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.configurators.AnalysisApiFirSourceTestConfigurator
import org.jetbrains.kotlin.light.classes.symbol.base.AbstractSymbolLightClassesLoadingTest
abstract class AbstractSymbolLightClassesLoadingForSourceTest :
@@ -55,3 +55,12 @@ class MultipleModuleDataProvider(private val moduleDataWithFilters: Map<FirModul
return null
}
}
class EmptyModuleDataProvider(
override val platform: TargetPlatform,
override val analyzerServices: PlatformDependentAnalyzerServices
) : ModuleDataProvider() {
override val allModuleData: Collection<FirModuleData> get() = emptyList()
override fun getModuleData(path: Path?): FirModuleData? = null
}
@@ -25,6 +25,12 @@ abstract class AbstractEnvironmentConfigurator : ServicesAndDirectivesContainer
abstract fun registerCompilerExtensions(project: Project, module: TestModule, configuration: CompilerConfiguration)
}
class EnvironmentConfiguratorsProvider(internal val environmentConfigurators: List<AbstractEnvironmentConfigurator>) : TestService
internal val TestServices.environmentConfiguratorsProvider: EnvironmentConfiguratorsProvider by TestServices.testServiceAccessor()
val TestServices.environmentConfigurators: List<AbstractEnvironmentConfigurator>
get() = environmentConfiguratorsProvider.environmentConfigurators
abstract class EnvironmentConfigurator(protected val testServices: TestServices) : AbstractEnvironmentConfigurator() {
protected val moduleStructure: TestModuleStructure
get() = testServices.moduleStructure
@@ -97,6 +97,7 @@ class TestConfigurationImpl(
init {
testServices.apply {
register(EnvironmentConfiguratorsProvider::class, EnvironmentConfiguratorsProvider(this@TestConfigurationImpl.environmentConfigurators))
@OptIn(ExperimentalStdlibApi::class)
val sourceFilePreprocessors = sourcePreprocessors.map { it.invoke(this@apply) }
val sourceFileProvider = SourceFileProviderImpl(this, sourceFilePreprocessors)
@@ -103,6 +103,51 @@ class JvmEnvironmentConfigurator(testServices: TestServices) : EnvironmentConfig
else -> error("Too many jdk kinds passed: ${jdkKinds.joinToArrayString()}")
}
}
fun getLibraryFilesExceptRealRuntime(
testServices: TestServices,
configurationKind: ConfigurationKind,
directives: RegisteredDirectives
): List<File> {
val provider = testServices.standardLibrariesPathProvider
val files = mutableListOf<File>()
if (configurationKind.withRuntime) {
files.add(provider.kotlinTestJarForTests())
} else if (configurationKind.withMockRuntime) {
files.add(provider.minimalRuntimeJarForTests())
files.add(provider.scriptRuntimeJarForTests())
}
if (configurationKind.withReflection) {
files.add(provider.reflectJarForTests())
}
files.add(KtTestUtil.getAnnotationsJar())
if (JvmEnvironmentConfigurationDirectives.STDLIB_JDK8 in directives) {
files.add(provider.runtimeJarForTestsWithJdk8())
}
files.add(KtTestUtil.getAnnotationsJar())
return files
}
fun getJdkHome(jdkKindTestJdkKind: TestJdkKind): File? = when (jdkKindTestJdkKind) {
TestJdkKind.MOCK_JDK -> null
TestJdkKind.MODIFIED_MOCK_JDK -> null
TestJdkKind.FULL_JDK_6 -> File(System.getenv("JDK_16") ?: error("Environment variable JDK_16 is not set"))
TestJdkKind.FULL_JDK_11 -> KtTestUtil.getJdk11Home()
TestJdkKind.FULL_JDK_17 -> KtTestUtil.getJdk17Home()
TestJdkKind.FULL_JDK -> if (SystemInfo.IS_AT_LEAST_JAVA9) File(System.getProperty("java.home")) else null
TestJdkKind.ANDROID_API -> null
}
fun getJdkClasspathRoot(jdkKind: TestJdkKind): File? = when (jdkKind) {
TestJdkKind.MOCK_JDK -> KtTestUtil.findMockJdkRtJar()
TestJdkKind.MODIFIED_MOCK_JDK -> KtTestUtil.findMockJdkRtModified()
TestJdkKind.ANDROID_API -> KtTestUtil.findAndroidApiJar()
TestJdkKind.FULL_JDK_6 -> null
TestJdkKind.FULL_JDK_11 -> null
TestJdkKind.FULL_JDK_17 -> null
TestJdkKind.FULL_JDK -> null
}
}
override val directiveContainers: List<DirectivesContainer>
@@ -136,34 +181,19 @@ class JvmEnvironmentConfigurator(testServices: TestServices) : EnvironmentConfig
configureDefaultJvmTarget(configuration)
val registeredDirectives = module.directives
when (extractJdkKind(registeredDirectives)) {
TestJdkKind.MOCK_JDK -> {
configuration.addJvmClasspathRoot(KtTestUtil.findMockJdkRtJar())
configuration.put(JVMConfigurationKeys.NO_JDK, true)
}
TestJdkKind.MODIFIED_MOCK_JDK -> {
configuration.addJvmClasspathRoot(KtTestUtil.findMockJdkRtModified())
configuration.put(JVMConfigurationKeys.NO_JDK, true)
}
TestJdkKind.FULL_JDK_6 -> {
val jdk6 = System.getenv("JDK_16") ?: error("Environment variable JDK_16 is not set")
configuration.put(JVMConfigurationKeys.JDK_HOME, File(jdk6))
}
TestJdkKind.FULL_JDK_11 -> {
configuration.put(JVMConfigurationKeys.JDK_HOME, KtTestUtil.getJdk11Home())
}
TestJdkKind.FULL_JDK_17 -> {
configuration.put(JVMConfigurationKeys.JDK_HOME, KtTestUtil.getJdk17Home())
}
TestJdkKind.FULL_JDK -> {
if (SystemInfo.IS_AT_LEAST_JAVA9) {
configuration.put(JVMConfigurationKeys.JDK_HOME, File(System.getProperty("java.home")))
}
}
TestJdkKind.ANDROID_API -> {
configuration.addJvmClasspathRoot(KtTestUtil.findAndroidApiJar())
val jdkKind = extractJdkKind(registeredDirectives)
getJdkHome(jdkKind)?.let { configuration.put(JVMConfigurationKeys.JDK_HOME, it) }
getJdkClasspathRoot(jdkKind)?.let { configuration.addJvmClasspathRoot(it) }
when (jdkKind) {
TestJdkKind.MOCK_JDK, TestJdkKind.MODIFIED_MOCK_JDK, TestJdkKind.ANDROID_API -> {
configuration.put(JVMConfigurationKeys.NO_JDK, true)
}
TestJdkKind.FULL_JDK_6 -> {}
TestJdkKind.FULL_JDK_11 -> {}
TestJdkKind.FULL_JDK_17 -> {}
TestJdkKind.FULL_JDK -> {}
}
val configurationKind = extractConfigurationKind(registeredDirectives).also {
@@ -180,7 +210,7 @@ class JvmEnvironmentConfigurator(testServices: TestServices) : EnvironmentConfig
if (configurationKind.withRuntime) {
configuration.configureStandardLibs(PathUtil.kotlinPathsForDistDirectory, K2JVMCompilerArguments().also { it.noReflect = true })
}
configuration.addJvmClasspathRoots(getLibraryFilesExceptRealRuntime(configurationKind, module.directives))
configuration.addJvmClasspathRoots(getLibraryFilesExceptRealRuntime(testServices, configurationKind, module.directives))
val isIr = module.targetBackend?.isIR == true
configuration.put(JVMConfigurationKeys.IR, isIr)
@@ -373,25 +403,6 @@ class JvmEnvironmentConfigurator(testServices: TestServices) : EnvironmentConfig
)
}
private fun getLibraryFilesExceptRealRuntime(configurationKind: ConfigurationKind, directives: RegisteredDirectives): List<File> {
val provider = testServices.standardLibrariesPathProvider
val files = mutableListOf<File>()
if (configurationKind.withRuntime) {
files.add(provider.kotlinTestJarForTests())
} else if (configurationKind.withMockRuntime) {
files.add(provider.minimalRuntimeJarForTests())
files.add(provider.scriptRuntimeJarForTests())
}
if (configurationKind.withReflection) {
files.add(provider.reflectJarForTests())
}
files.add(KtTestUtil.getAnnotationsJar())
if (JvmEnvironmentConfigurationDirectives.STDLIB_JDK8 in directives) {
files.add(provider.runtimeJarForTestsWithJdk8())
}
files.add(KtTestUtil.getAnnotationsJar())
return files
}
}