AA: refactor service registrations

such that AA standalone mode doesn't need to unregister services that
were already registered by pre-analysis handlers
This commit is contained in:
Jinseong Jeon
2022-02-03 20:32:06 -08:00
committed by Ilya Kirillov
parent 26e923e3ae
commit a986aff429
18 changed files with 211 additions and 112 deletions
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.analysis.api.descriptors.test
import com.intellij.mock.MockApplication
import com.intellij.mock.MockProject
import com.intellij.openapi.Disposable
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.analysis.api.InvalidWayOfUsingAnalysisSession
import org.jetbrains.kotlin.analysis.api.KtAnalysisSessionProvider
import org.jetbrains.kotlin.analysis.api.descriptors.CliFe10AnalysisFacade
@@ -17,7 +18,10 @@ import org.jetbrains.kotlin.analysis.api.descriptors.KtFe10AnalysisSessionProvid
import org.jetbrains.kotlin.analysis.api.descriptors.references.base.KtFe10KotlinReferenceProviderContributor
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.FrontendApiTestConfiguratorService
import org.jetbrains.kotlin.analysis.api.impl.base.references.HLApiReferenceProviderService
import org.jetbrains.kotlin.analysis.project.structure.ProjectStructureProvider
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.idea.references.KotlinReferenceProviderContributor
import org.jetbrains.kotlin.load.kotlin.PackagePartProvider
import org.jetbrains.kotlin.psi.KotlinReferenceProvidersService
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.extensions.AnalysisHandlerExtension
@@ -43,7 +47,13 @@ object KtFe10FrontendApiTestConfiguratorService : FrontendApiTestConfiguratorSer
}
@OptIn(InvalidWayOfUsingAnalysisSession::class)
override fun registerProjectServices(project: MockProject) {
override fun registerProjectServices(
project: MockProject,
compilerConfig: CompilerConfiguration,
files: List<KtFile>,
packagePartProvider: (GlobalSearchScope) -> PackagePartProvider,
projectStructureProvider: ProjectStructureProvider
) {
project.registerService(KtAnalysisSessionProvider::class.java, KtFe10AnalysisSessionProvider())
project.registerService(Fe10AnalysisFacade::class.java, CliFe10AnalysisFacade(project))
AnalysisHandlerExtension.registerExtension(project, KtFe10AnalysisHandlerExtension())
@@ -73,4 +83,4 @@ object KtFe10FrontendApiTestConfiguratorService : FrontendApiTestConfiguratorSer
if (newPath.toFile().exists()) return newPath
return path
}
}
}
@@ -8,11 +8,16 @@ package org.jetbrains.kotlin.analysis.api.fir
import com.intellij.mock.MockApplication
import com.intellij.mock.MockProject
import com.intellij.openapi.Disposable
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.FrontendApiTestConfiguratorService
import org.jetbrains.kotlin.analysis.api.impl.base.references.HLApiReferenceProviderService
import org.jetbrains.kotlin.analysis.low.level.api.fir.compiler.based.registerTestServices
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.FirLowLevelFrontendApiTestConfiguratorService
import org.jetbrains.kotlin.analysis.project.structure.ProjectStructureProvider
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.idea.references.KotlinFirReferenceContributor
import org.jetbrains.kotlin.idea.references.KotlinReferenceProviderContributor
import org.jetbrains.kotlin.load.kotlin.PackagePartProvider
import org.jetbrains.kotlin.psi.KotlinReferenceProvidersService
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
@@ -30,8 +35,20 @@ object FirFrontendApiTestConfiguratorService : FrontendApiTestConfiguratorServic
return FirLowLevelFrontendApiTestConfiguratorService.getOriginalFile(file)
}
override fun registerProjectServices(project: MockProject) {
FirLowLevelFrontendApiTestConfiguratorService.registerProjectServices(project)
override fun registerProjectServices(
project: MockProject,
compilerConfig: CompilerConfiguration,
files: List<KtFile>,
packagePartProvider: (GlobalSearchScope) -> PackagePartProvider,
projectStructureProvider: ProjectStructureProvider
) {
FirLowLevelFrontendApiTestConfiguratorService.registerProjectServices(
project,
compilerConfig,
files,
packagePartProvider,
projectStructureProvider
)
}
override fun registerApplicationServices(application: MockApplication) {
@@ -13,6 +13,7 @@ import com.intellij.openapi.extensions.LoadingOrder
import com.intellij.psi.ClassFileViewProviderFactory
import com.intellij.psi.FileTypeFileViewProviders
import com.intellij.psi.compiled.ClassFileDecompilers
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.analysis.api.fir.FirFrontendApiTestConfiguratorService
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.FrontendApiTestConfiguratorService
import org.jetbrains.kotlin.analysis.api.impl.base.test.utils.libraries.LibraryEnvironmentConfigurator
@@ -21,6 +22,10 @@ import org.jetbrains.kotlin.analysis.decompiler.psi.KotlinClassFileDecompiler
import org.jetbrains.kotlin.analysis.decompiler.stub.file.ClsKotlinBinaryClassCache
import org.jetbrains.kotlin.analysis.decompiler.stub.file.FileAttributeService
import org.jetbrains.kotlin.analysis.decompiler.stub.files.DummyFileAttributeService
import org.jetbrains.kotlin.analysis.low.level.api.fir.compiler.based.registerTestServices
import org.jetbrains.kotlin.analysis.project.structure.ProjectStructureProvider
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.load.kotlin.PackagePartProvider
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
@@ -32,10 +37,16 @@ object LibraryFrontendApiTestConfiguratorService : FrontendApiTestConfiguratorSe
usePreAnalysisHandlers(::LibraryModuleRegistrarPreAnalysisHandler)
}
override fun registerProjectServices(project: MockProject) {
override fun registerProjectServices(
project: MockProject,
compilerConfig: CompilerConfiguration,
files: List<KtFile>,
packagePartProvider: (GlobalSearchScope) -> PackagePartProvider,
projectStructureProvider: ProjectStructureProvider
) {
project.registerTestServices(files, packagePartProvider, projectStructureProvider)
}
override fun registerApplicationServices(application: MockApplication) {
FirFrontendApiTestConfiguratorService.registerApplicationServices(application)
if (application.getServiceIfCreated(ClsKotlinBinaryClassCache::class.java) != null) return
@@ -5,7 +5,6 @@
package org.jetbrains.kotlin.analysis.api.fir.utils.libraries.binary
import com.intellij.mock.MockProject
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiManager
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.TestKtLibraryModule
@@ -13,14 +12,12 @@ import org.jetbrains.kotlin.analysis.api.impl.barebone.test.projectModuleProvide
import org.jetbrains.kotlin.analysis.api.impl.base.test.utils.libraries.compiledLibraryProvider
import org.jetbrains.kotlin.analysis.api.impl.base.util.LibraryUtils
import org.jetbrains.kotlin.analysis.decompiler.psi.file.KtClsFile
import org.jetbrains.kotlin.analysis.low.level.api.fir.compiler.based.registerTestServices
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) {
@@ -32,7 +29,6 @@ class LibraryModuleRegistrarPreAnalysisHandler(
val decompiledKtFiles = getDecompiledVirtualFilesFromLibrary(testModule, project)
moduleInfoProvider.registerModuleInfo(testModule, TestKtLibraryModule(project, testModule, decompiledKtFiles, testServices))
(project as MockProject).registerTestServices(testModule, decompiledKtFiles, testServices)
}
private fun getDecompiledVirtualFilesFromLibrary(module: TestModule, project: Project): List<KtClsFile> {
@@ -8,10 +8,15 @@ package org.jetbrains.kotlin.analysis.api.fir.utils.libraries.source
import com.intellij.mock.MockApplication
import com.intellij.mock.MockProject
import com.intellij.openapi.Disposable
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.analysis.api.fir.FirFrontendApiTestConfiguratorService
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.FrontendApiTestConfiguratorService
import org.jetbrains.kotlin.analysis.api.impl.base.test.utils.libraries.CompiledLibraryProvider
import org.jetbrains.kotlin.analysis.api.impl.base.test.utils.libraries.LibraryEnvironmentConfigurator
import org.jetbrains.kotlin.analysis.low.level.api.fir.compiler.based.registerTestServices
import org.jetbrains.kotlin.analysis.project.structure.ProjectStructureProvider
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.load.kotlin.PackagePartProvider
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
import org.jetbrains.kotlin.test.services.ServiceRegistrationData
@@ -25,10 +30,16 @@ object LibrarySourceFrontendApiTestConfiguratorService : FrontendApiTestConfigur
useAdditionalServices(ServiceRegistrationData(CompiledLibraryProvider::class, ::CompiledLibraryProvider))
}
override fun registerProjectServices(project: MockProject) {
override fun registerProjectServices(
project: MockProject,
compilerConfig: CompilerConfiguration,
files: List<KtFile>,
packagePartProvider: (GlobalSearchScope) -> PackagePartProvider,
projectStructureProvider: ProjectStructureProvider
) {
project.registerTestServices(files, packagePartProvider, projectStructureProvider)
}
override fun registerApplicationServices(application: MockApplication) {
FirFrontendApiTestConfiguratorService.registerApplicationServices(application)
}
@@ -5,7 +5,6 @@
package org.jetbrains.kotlin.analysis.api.fir.utils.libraries.source
import com.intellij.mock.MockProject
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiManager
import com.intellij.psi.search.GlobalSearchScope
@@ -13,7 +12,6 @@ import org.jetbrains.kotlin.analysis.api.impl.barebone.test.TestKtLibrarySourceM
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.projectModuleProvider
import org.jetbrains.kotlin.analysis.api.impl.base.test.utils.libraries.compiledLibraryProvider
import org.jetbrains.kotlin.analysis.api.impl.base.util.LibraryUtils
import org.jetbrains.kotlin.analysis.low.level.api.fir.compiler.based.registerTestServices
import org.jetbrains.kotlin.analysis.project.structure.KtLibraryModule
import org.jetbrains.kotlin.analysis.project.structure.KtLibrarySourceModule
import org.jetbrains.kotlin.analysis.project.structure.KtModule
@@ -54,7 +52,6 @@ class LibrarySourceModuleRegistrarPreAnalysisHandler(
libraryKtModule.librarySources = sourcesKtModule
moduleInfoProvider.registerModuleInfo(testModule, sourcesKtModule)
(project as MockProject).registerTestServices(testModule, librarySourceKtFiles, testServices)
}
}
@@ -10,9 +10,14 @@ import com.intellij.mock.MockProject
import com.intellij.openapi.Disposable
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.util.Disposer
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.testFramework.TestDataFile
import junit.framework.ComparisonFailure
import org.jetbrains.kotlin.analysis.project.structure.ProjectStructureProvider
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.cli.jvm.config.addJavaSourceRoots
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.load.kotlin.PackagePartProvider
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.InTextDirectivesUtils
@@ -31,6 +36,7 @@ import org.jetbrains.kotlin.test.services.configuration.JvmEnvironmentConfigurat
import org.jetbrains.kotlin.test.services.impl.TemporaryDirectoryManagerImpl
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.TestInfo
import java.io.File
import java.nio.file.Path
import java.nio.file.Paths
import java.util.concurrent.ExecutionException
@@ -47,9 +53,17 @@ interface FrontendApiTestConfiguratorService {
fun TestConfigurationBuilder.configureTest(disposable: Disposable)
fun processTestFiles(files: List<KtFile>): List<KtFile> = files
fun getOriginalFile(file: KtFile): KtFile = file
fun registerProjectServices(project: MockProject)
fun registerProjectServices(
project: MockProject,
compilerConfig: CompilerConfiguration,
files: List<KtFile>,
packagePartProvider: (GlobalSearchScope) -> PackagePartProvider,
projectStructureProvider: ProjectStructureProvider
)
fun registerApplicationServices(application: MockApplication)
fun prepareTestFiles(files: List<KtFile>, module: TestModule, testServices: TestServices) {}
@@ -164,11 +178,6 @@ abstract class AbstractFrontendApiTest : TestWithDisposable() {
return
}
val moduleInfoProvider = testServices.projectModuleProvider
with(project as MockProject) {
configurator.registerProjectServices(this)
}
registerApplicationServices()
testConfiguration.testServices.register(TestModuleStructure::class, moduleStructure)
testConfiguration.preAnalysisHandlers.forEach { preprocessor ->
@@ -182,14 +191,28 @@ abstract class AbstractFrontendApiTest : TestWithDisposable() {
}
}
val ktFiles = getKtFilesFromModule(testServices, singleModule)
with(project as MockProject) {
val compilerConfiguration = testServices.compilerConfigurationProvider.getCompilerConfiguration(singleModule)
compilerConfiguration.addJavaSourceRoots(ktFiles.map { File(it.virtualFilePath) })
configurator.registerProjectServices(
this,
compilerConfiguration,
ktFiles,
testServices.compilerConfigurationProvider.getPackagePartProviderFactory(singleModule),
KotlinProjectStructureProviderTestImpl(testServices)
)
}
val moduleInfo = moduleInfoProvider.getModule(singleModule.name)
val ktFiles = when (moduleInfo) {
is TestKtSourceModule -> moduleInfo.testFilesToKtFiles.filterKeys { testFile -> !testFile.isAdditional }.values.toList()
is TestKtLibraryModule -> moduleInfo.ktFiles.toList()
is TestKtLibrarySourceModule -> moduleInfo.ktFiles.toList()
else -> error("Unexpected $moduleInfo")
testConfiguration.preAnalysisHandlers.forEach { preprocessor ->
try {
preprocessor.prepareSealedClassInheritors(moduleStructure)
} catch (exception: Throwable) {
when (handleInitializationError(exception, moduleStructure)) {
InitializationErrorAction.IGNORE -> {}
InitializationErrorAction.THROW -> throw exception
}
}
}
configurator.prepareTestFiles(ktFiles, singleModule, testServices)
@@ -233,4 +256,14 @@ abstract class AbstractFrontendApiTest : TestWithDisposable() {
companion object {
val DISABLE_DEPENDED_MODE_DIRECTIVE = "DISABLE_DEPENDED_MODE"
}
}
}
fun getKtFilesFromModule(testServices: TestServices, testModule: TestModule): List<KtFile> {
val moduleInfoProvider = testServices.projectModuleProvider
return when (val moduleInfo = moduleInfoProvider.getModule(testModule.name)) {
is TestKtSourceModule -> moduleInfo.testFilesToKtFiles.filterKeys { testFile -> !testFile.isAdditional }.values.toList()
is TestKtLibraryModule -> moduleInfo.ktFiles.toList()
is TestKtLibrarySourceModule -> moduleInfo.ktFiles.toList()
else -> error("Unexpected $moduleInfo")
}
}
@@ -0,0 +1,20 @@
/*
* 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.impl.barebone.test
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.analysis.project.structure.KtModule
import org.jetbrains.kotlin.analysis.project.structure.ProjectStructureProvider
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.services.TestServices
class KotlinProjectStructureProviderTestImpl(testServices: TestServices) : ProjectStructureProvider() {
private val moduleInfoProvider = testServices.projectModuleProvider
override fun getKtModuleForKtElement(element: PsiElement): KtModule {
val containingFile = element.containingFile as KtFile
return moduleInfoProvider.getModuleInfoByKtFile(containingFile) as KtModule
}
}
@@ -6,7 +6,6 @@
package org.jetbrains.kotlin.analysis.api.standalone;
import com.intellij.mock.MockProject;
import org.jetbrains.annotations.TestOnly;
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirResolveStateService;
class RegisterComponentService {
@@ -16,9 +15,4 @@ class RegisterComponentService {
new LLFirResolveStateService(project)
);
}
@TestOnly
static void unregisterLLFirResolveStateService(MockProject project) {
project.getPicoContainer().unregisterComponent(LLFirResolveStateService.class.getName());
}
}
@@ -5,48 +5,22 @@
package org.jetbrains.kotlin.analysis.api.standalone
import com.intellij.mock.MockProject
import com.intellij.psi.util.PsiTreeUtil
import org.jetbrains.kotlin.analysis.api.InvalidWayOfUsingAnalysisSession
import org.jetbrains.kotlin.analysis.api.KtAnalysisSessionProvider
import org.jetbrains.kotlin.analysis.api.components.KtDeclarationRendererOptions
import org.jetbrains.kotlin.analysis.api.components.RendererModifier
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.expressionMarkerProvider
import org.jetbrains.kotlin.analysis.api.impl.base.test.TestReferenceResolveResultRenderer.renderResolvedTo
import org.jetbrains.kotlin.analysis.api.impl.base.test.findReferencesAtCaret
import org.jetbrains.kotlin.analysis.api.impl.base.test.test.framework.AbstractHLApiSingleModuleTest
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.services.FirSealedClassInheritorsProcessorFactory
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.services.PackagePartProviderFactory
import org.jetbrains.kotlin.analysis.project.structure.KtModuleScopeProvider
import org.jetbrains.kotlin.analysis.project.structure.ProjectStructureProvider
import org.jetbrains.kotlin.analysis.providers.KotlinDeclarationProviderFactory
import org.jetbrains.kotlin.analysis.providers.KotlinModificationTrackerFactory
import org.jetbrains.kotlin.analysis.providers.KotlinPackageProviderFactory
import org.jetbrains.kotlin.cli.jvm.config.addJavaSourceRoots
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.services.TestServices
import org.jetbrains.kotlin.test.services.assertions
import org.jetbrains.kotlin.test.services.compilerConfigurationProvider
import java.io.File
abstract class AbstractStandaloneModeSingleModuleTest : AbstractHLApiSingleModuleTest() {
override fun doTestByFileStructure(ktFiles: List<KtFile>, module: TestModule, testServices: TestServices) {
val project = testServices.compilerConfigurationProvider.getProject(module) as MockProject
// (project.picoContainer as DefaultPicoContainer).release() // is way too strong :( even PsiManager is gone
unregisterServices(project)
// TODO: better to be part of `StandaloneModeUtilsConfiguratorService`
val compilerConfiguration = testServices.compilerConfigurationProvider.getCompilerConfiguration(module)
compilerConfiguration.addJavaSourceRoots(ktFiles.map { File(it.virtualFilePath) })
configureProjectEnvironment(
project,
compilerConfiguration,
ktFiles,
testServices.compilerConfigurationProvider.getPackagePartProviderFactory(module)
)
val mainKtFile = ktFiles.singleOrNull() ?: ktFiles.first { it.name == "main.kt" }
val caretPosition = testServices.expressionMarkerProvider.getCaretPosition(mainKtFile)
val ktReferences = findReferencesAtCaret(mainKtFile, caretPosition)
@@ -70,17 +44,4 @@ abstract class AbstractStandaloneModeSingleModuleTest : AbstractHLApiSingleModul
modifiers = RendererModifier.DEFAULT - RendererModifier.ANNOTATIONS,
sortNestedDeclarations = true
)
@OptIn(InvalidWayOfUsingAnalysisSession::class)
private fun unregisterServices(project: MockProject) {
project.picoContainer.unregisterComponent(KtAnalysisSessionProvider::class.qualifiedName)
project.picoContainer.unregisterComponent(KotlinModificationTrackerFactory::class.qualifiedName)
RegisterComponentService.unregisterLLFirResolveStateService(project)
project.picoContainer.unregisterComponent(FirSealedClassInheritorsProcessorFactory::class.qualifiedName)
project.picoContainer.unregisterComponent(KtModuleScopeProvider::class.qualifiedName)
project.picoContainer.unregisterComponent(ProjectStructureProvider::class.qualifiedName)
project.picoContainer.unregisterComponent(KotlinDeclarationProviderFactory::class.qualifiedName)
project.picoContainer.unregisterComponent(KotlinPackageProviderFactory::class.qualifiedName)
project.picoContainer.unregisterComponent(PackagePartProviderFactory::class.qualifiedName)
}
}
@@ -8,8 +8,12 @@ package org.jetbrains.kotlin.analysis.api.standalone
import com.intellij.mock.MockApplication
import com.intellij.mock.MockProject
import com.intellij.openapi.Disposable
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.analysis.api.fir.FirFrontendApiTestConfiguratorService
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.FrontendApiTestConfiguratorService
import org.jetbrains.kotlin.analysis.project.structure.ProjectStructureProvider
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.load.kotlin.PackagePartProvider
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
@@ -21,9 +25,14 @@ object StandaloneModeConfiguratorService : FrontendApiTestConfiguratorService {
with(FirFrontendApiTestConfiguratorService) { configureTest(disposable) }
}
// TODO: other variant to register project services by compiler configuration?
override fun registerProjectServices(project: MockProject) {
// Will be configured at the test
override fun registerProjectServices(
project: MockProject,
compilerConfig: CompilerConfiguration,
files: List<KtFile>,
packagePartProvider: (GlobalSearchScope) -> PackagePartProvider,
projectStructureProvider: ProjectStructureProvider
) {
configureProjectEnvironment(project, compilerConfig, files, packagePartProvider)
}
override fun registerApplicationServices(application: MockApplication) {
@@ -40,7 +40,7 @@ abstract class AbstractCompilerBasedTestForFir : AbstractCompilerBasedTest() {
defaultConfiguration(this)
useAdditionalService(::TestKtModuleProvider)
usePreAnalysisHandlers(::ModuleRegistrarPreAnalysisHandler.bind(disposable))
usePreAnalysisHandlers(::ModuleRegistrarPreAnalysisHandler.bind(disposable, true))
firHandlersStep {
useHandlers(::LLDiagnosticParameterChecker)
@@ -89,4 +89,4 @@ abstract class AbstractCompilerBasedTestForFir : AbstractCompilerBasedTest() {
LLFirLazyTransformer.enableDeepEnsure = oldEnableDeepEnsure
}
}
}
}
@@ -7,7 +7,9 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.compiler.based
import com.intellij.mock.MockProject
import com.intellij.openapi.Disposable
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.KotlinProjectStructureProviderTestImpl
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.TestKtSourceModule
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.getKtFilesFromModule
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.projectModuleProvider
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirFile
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getResolveState
@@ -21,11 +23,11 @@ import org.jetbrains.kotlin.test.services.*
class ModuleRegistrarPreAnalysisHandler(
testServices: TestServices,
private val parentDisposable: Disposable
private val parentDisposable: Disposable,
private val shouldRegisterProjectServices: Boolean,
) : PreAnalysisHandler(testServices) {
private val moduleInfoProvider = testServices.projectModuleProvider
override fun preprocessModuleStructure(moduleStructure: TestModuleStructure) {
// todo rework after all modules will have the same Project instance
val ktFilesByModule = moduleStructure.modules.associateWith { testModule ->
@@ -38,14 +40,32 @@ class ModuleRegistrarPreAnalysisHandler(
ktFilesByModule.forEach { (testModule, ktFiles) ->
val project = testServices.compilerConfigurationProvider.getProject(testModule)
moduleInfoProvider.registerModuleInfo(testModule, TestKtSourceModule(project, testModule, ktFiles, testServices))
(project as MockProject).registerTestServices(testModule, allKtFiles, testServices)
// Register services for compiler-based tests
// On the other hand, frontend API tests will register services via test configurators.
if (shouldRegisterProjectServices) {
(project as MockProject).registerTestServices(
allKtFiles,
testServices.compilerConfigurationProvider.getPackagePartProviderFactory(testModule),
KotlinProjectStructureProviderTestImpl(testServices)
)
}
}
}
override fun prepareSealedClassInheritors(moduleStructure: TestModuleStructure) {
val ktFilesByModule = moduleStructure.modules.associateWith { testModule ->
getKtFilesFromModule(testServices, testModule)
}
ktFilesByModule.forEach { (testModule, ktFiles) ->
val project = testServices.compilerConfigurationProvider.getProject(testModule)
// Manually process all inheritors of sealed classes so that SealedClassInheritorsProviderTestImpl can work correctly for tests.
// In the actual IDE, SealedClassInheritorsProviderIdeImpl works by finding inheritors from the index instead of do a
// preprocessing of all files. Therefore, the IDE does not rely on such a pre-analysis pass of all files in the module.
val projectStructureProvider = project.getService(ProjectStructureProvider::class.java)
val allFirFiles = mutableListOf<FirFile>()
ktFiles.forEach { (_, ktFile) ->
ktFiles.forEach { ktFile ->
val ktModule = projectStructureProvider.getKtModuleForKtElement(ktFile)
val resolveState = ktModule.getResolveState(project)
allFirFiles.add(ktFile.getOrBuildFirFile(resolveState))
@@ -7,17 +7,14 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.compiler.based
import com.intellij.mock.MockProject
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiElementFinder
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.analysis.api.InvalidWayOfUsingAnalysisSession
import org.jetbrains.kotlin.analysis.api.KtAnalysisSessionProvider
import org.jetbrains.kotlin.analysis.api.fir.KtFirAnalysisSessionProvider
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.projectModuleProvider
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirResolveStateService
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.services.FirSealedClassInheritorsProcessorFactory
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.services.PackagePartProviderFactory
import org.jetbrains.kotlin.analysis.project.structure.KtModule
import org.jetbrains.kotlin.analysis.project.structure.KtModuleScopeProvider
import org.jetbrains.kotlin.analysis.project.structure.KtModuleScopeProviderImpl
import org.jetbrains.kotlin.analysis.project.structure.ProjectStructureProvider
@@ -35,18 +32,15 @@ import org.jetbrains.kotlin.light.classes.symbol.IDEKotlinAsJavaFirSupport
import org.jetbrains.kotlin.light.classes.symbol.caches.SymbolLightClassFacadeCache
import org.jetbrains.kotlin.load.kotlin.PackagePartProvider
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.services.TestServices
import org.jetbrains.kotlin.test.services.compilerConfigurationProvider
fun MockProject.registerTestServices(
testModule: TestModule,
allKtFiles: List<KtFile>,
testServices: TestServices,
packagePartProvider: (GlobalSearchScope) -> PackagePartProvider,
projectStructureProvider: ProjectStructureProvider
) {
registerService(
PackagePartProviderFactory::class.java,
PackagePartProviderTestImpl(testServices, testModule)
PackagePartProviderTestImpl(packagePartProvider)
)
registerService(
FirSealedClassInheritorsProcessorFactory::class.java,
@@ -60,7 +54,7 @@ fun MockProject.registerTestServices(
)
registerService(KotlinDeclarationProviderFactory::class.java, KotlinStaticDeclarationProviderFactory(allKtFiles))
registerService(KotlinPackageProviderFactory::class.java, KotlinStaticPackageProviderFactory(allKtFiles))
registerService(ProjectStructureProvider::class.java, KotlinProjectStructureProviderTestImpl(testServices))
registerService(ProjectStructureProvider::class.java, projectStructureProvider)
registerService(SymbolLightClassFacadeCache::class.java)
reRegisterJavaElementFinder(this)
}
@@ -72,20 +66,10 @@ private class FirSealedClassInheritorsProcessorFactoryTestImpl : FirSealedClassI
}
private class PackagePartProviderTestImpl(
private val testServices: TestServices,
private val testModule: TestModule
private val packagePartProvider: (GlobalSearchScope) -> PackagePartProvider,
) : PackagePartProviderFactory() {
override fun createPackagePartProviderForLibrary(scope: GlobalSearchScope): PackagePartProvider {
val factory = testServices.compilerConfigurationProvider.getPackagePartProviderFactory(testModule)
return factory(scope)
}
}
private class KotlinProjectStructureProviderTestImpl(testServices: TestServices) : ProjectStructureProvider() {
private val moduleInfoProvider = testServices.projectModuleProvider
override fun getKtModuleForKtElement(element: PsiElement): KtModule {
val containingFile = element.containingFile as KtFile
return moduleInfoProvider.getModuleInfoByKtFile(containingFile) as KtModule
return packagePartProvider(scope)
}
}
@@ -9,17 +9,22 @@ import com.intellij.mock.MockApplication
import com.intellij.mock.MockProject
import com.intellij.openapi.Disposable
import com.intellij.openapi.components.ServiceManager
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.FrontendApiTestConfiguratorService
import org.jetbrains.kotlin.analysis.low.level.api.fir.compiler.based.ModuleRegistrarPreAnalysisHandler
import org.jetbrains.kotlin.analysis.low.level.api.fir.compiler.based.registerTestServices
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.originalKtFile
import org.jetbrains.kotlin.analysis.project.structure.ProjectStructureProvider
import org.jetbrains.kotlin.analysis.providers.KotlinModificationTrackerFactory
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.load.kotlin.PackagePartProvider
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.bind
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
object FirLowLevelFrontendApiTestConfiguratorService : FrontendApiTestConfiguratorService {
override fun TestConfigurationBuilder.configureTest(disposable: Disposable) {
usePreAnalysisHandlers(::ModuleRegistrarPreAnalysisHandler.bind(disposable))
usePreAnalysisHandlers(::ModuleRegistrarPreAnalysisHandler.bind(disposable, false))
}
override fun processTestFiles(files: List<KtFile>): List<KtFile> {
@@ -34,11 +39,20 @@ object FirLowLevelFrontendApiTestConfiguratorService : FrontendApiTestConfigurat
return file.originalKtFile!!
}
override fun registerProjectServices(project: MockProject) {}
override fun registerProjectServices(
project: MockProject,
compilerConfig: CompilerConfiguration,
files: List<KtFile>,
packagePartProvider: (GlobalSearchScope) -> PackagePartProvider,
projectStructureProvider: ProjectStructureProvider
) {
project.registerTestServices(files, packagePartProvider, projectStructureProvider)
}
override fun registerApplicationServices(application: MockApplication) {}
override fun doOutOfBlockModification(file: KtFile) {
ServiceManager.getService(file.project, KotlinModificationTrackerFactory::class.java)
.incrementModificationsCount()
}
}
}
@@ -8,10 +8,14 @@ package org.jetbrains.kotlin.light.classes.symbol.decompiled.service
import com.intellij.mock.MockApplication
import com.intellij.mock.MockProject
import com.intellij.openapi.Disposable
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.analysis.api.fir.utils.libraries.binary.LibraryFrontendApiTestConfiguratorService
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.FrontendApiTestConfiguratorService
import org.jetbrains.kotlin.analysis.api.impl.base.test.utils.libraries.CompiledLibraryProvider
import org.jetbrains.kotlin.analysis.decompiled.light.classes.ClsJavaStubByVirtualFileCache
import org.jetbrains.kotlin.analysis.project.structure.ProjectStructureProvider
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.load.kotlin.PackagePartProvider
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
import org.jetbrains.kotlin.test.services.ServiceRegistrationData
@@ -24,8 +28,20 @@ internal object SymbolLightClassesForLibraryFrontendApiTestConfiguratorService :
useAdditionalServices(ServiceRegistrationData(CompiledLibraryProvider::class, ::CompiledLibraryProvider))
}
override fun registerProjectServices(project: MockProject) {
LibraryFrontendApiTestConfiguratorService.registerProjectServices(project)
override fun registerProjectServices(
project: MockProject,
compilerConfig: CompilerConfiguration,
files: List<KtFile>,
packagePartProvider: (GlobalSearchScope) -> PackagePartProvider,
projectStructureProvider: ProjectStructureProvider
) {
LibraryFrontendApiTestConfiguratorService.registerProjectServices(
project,
compilerConfig,
files,
packagePartProvider,
projectStructureProvider
)
project.registerService(ClsJavaStubByVirtualFileCache::class.java)
}
@@ -36,4 +52,4 @@ internal object SymbolLightClassesForLibraryFrontendApiTestConfiguratorService :
override fun doOutOfBlockModification(file: KtFile) {
LibraryFrontendApiTestConfiguratorService.doOutOfBlockModification(file)
}
}
}
@@ -47,3 +47,7 @@ abstract class TestConfiguration {
fun <T, R> ((TestServices, T) -> R).bind(value: T): Constructor<R> {
return { this.invoke(it, value) }
}
fun <T1, T2, R> ((TestServices, T1, T2) -> R).bind(value1: T1, value2: T2): Constructor<R> {
return { this.invoke(it, value1, value2) }
}
@@ -7,4 +7,6 @@ package org.jetbrains.kotlin.test.services
abstract class PreAnalysisHandler(protected val testServices: TestServices) {
abstract fun preprocessModuleStructure(moduleStructure: TestModuleStructure)
}
open fun prepareSealedClassInheritors(moduleStructure: TestModuleStructure) {}
}