[analysis api] simplify dependent analysis mode tests

This commit is contained in:
Ilya Kirillov
2022-03-17 12:44:23 +01:00
parent 3206c0ce87
commit 12e0254918
20 changed files with 116 additions and 96 deletions
@@ -37,12 +37,11 @@ import kotlin.io.path.extension
import kotlin.io.path.nameWithoutExtension import kotlin.io.path.nameWithoutExtension
object KtFe10AnalysisApiTestConfiguratorService : AnalysisApiTestConfiguratorService { object KtFe10AnalysisApiTestConfiguratorService : AnalysisApiTestConfiguratorService {
override val analyseInDependentSession: Boolean get() = false
override val testPrefix: String override val testPrefix: String
get() = "descriptors" get() = "descriptors"
override val allowDependedAnalysisSession: Boolean
get() = false
override fun TestConfigurationBuilder.configureTest(disposable: Disposable) { override fun TestConfigurationBuilder.configureTest(disposable: Disposable) {
usePreAnalysisHandlers(::KtFe10ModuleRegistrarPreAnalysisHandler.bind(disposable)) usePreAnalysisHandlers(::KtFe10ModuleRegistrarPreAnalysisHandler.bind(disposable))
} }
@@ -64,7 +63,10 @@ object KtFe10AnalysisApiTestConfiguratorService : AnalysisApiTestConfiguratorSer
override fun registerApplicationServices(application: MockApplication) { override fun registerApplicationServices(application: MockApplication) {
if (application.getServiceIfCreated(KotlinReferenceProvidersService::class.java) == null) { if (application.getServiceIfCreated(KotlinReferenceProvidersService::class.java) == null) {
application.registerService(KotlinReferenceProvidersService::class.java, HLApiReferenceProviderService::class.java) application.registerService(KotlinReferenceProvidersService::class.java, HLApiReferenceProviderService::class.java)
application.registerService(KotlinReferenceProviderContributor::class.java, KtFe10KotlinReferenceProviderContributor::class.java) application.registerService(
KotlinReferenceProviderContributor::class.java,
KtFe10KotlinReferenceProviderContributor::class.java
)
} }
} }
@@ -23,7 +23,7 @@ import org.jetbrains.kotlin.psi.KotlinReferenceProvidersService
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
object FirAnalysisApiTestConfiguratorService : AnalysisApiTestConfiguratorService { open class FirAnalysisApiTestConfiguratorService(override val analyseInDependentSession: Boolean) : AnalysisApiTestConfiguratorService {
override fun TestConfigurationBuilder.configureTest(disposable: Disposable) { override fun TestConfigurationBuilder.configureTest(disposable: Disposable) {
with(FirLowLevelAnalysisApiTestConfiguratorService) { configureTest(disposable) } with(FirLowLevelAnalysisApiTestConfiguratorService) { configureTest(disposable) }
configureOptionalTestCompilerPlugin() configureOptionalTestCompilerPlugin()
@@ -67,3 +67,6 @@ object FirAnalysisApiTestConfiguratorService : AnalysisApiTestConfiguratorServic
FirLowLevelAnalysisApiTestConfiguratorService.doOutOfBlockModification(file) FirLowLevelAnalysisApiTestConfiguratorService.doOutOfBlockModification(file)
} }
} }
object FirAnalysisApiDependentModeTestConfiguratorService: FirAnalysisApiTestConfiguratorService(analyseInDependentSession = true)
object FirAnalysisApiNormalModeTestConfiguratorService: FirAnalysisApiTestConfiguratorService(analyseInDependentSession = false)
@@ -15,7 +15,7 @@ import com.intellij.psi.ClassFileViewProviderFactory
import com.intellij.psi.FileTypeFileViewProviders import com.intellij.psi.FileTypeFileViewProviders
import com.intellij.psi.compiled.ClassFileDecompilers import com.intellij.psi.compiled.ClassFileDecompilers
import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.analysis.api.fir.FirAnalysisApiTestConfiguratorService import org.jetbrains.kotlin.analysis.api.fir.FirAnalysisApiNormalModeTestConfiguratorService
import org.jetbrains.kotlin.analysis.test.framework.AnalysisApiTestConfiguratorService import org.jetbrains.kotlin.analysis.test.framework.AnalysisApiTestConfiguratorService
import org.jetbrains.kotlin.analysis.decompiler.psi.KotlinBuiltInDecompiler import org.jetbrains.kotlin.analysis.decompiler.psi.KotlinBuiltInDecompiler
import org.jetbrains.kotlin.analysis.decompiler.psi.KotlinClassFileDecompiler import org.jetbrains.kotlin.analysis.decompiler.psi.KotlinClassFileDecompiler
@@ -31,7 +31,7 @@ import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
object LibraryAnalysisApiTestConfiguratorService : AnalysisApiTestConfiguratorService { object LibraryAnalysisApiTestConfiguratorService : AnalysisApiTestConfiguratorService {
override val allowDependedAnalysisSession: Boolean get() = false override val analyseInDependentSession: Boolean get() = false
override fun TestConfigurationBuilder.configureTest(disposable: Disposable) { override fun TestConfigurationBuilder.configureTest(disposable: Disposable) {
useConfigurators(::LibraryEnvironmentConfigurator) useConfigurators(::LibraryEnvironmentConfigurator)
@@ -50,7 +50,7 @@ object LibraryAnalysisApiTestConfiguratorService : AnalysisApiTestConfiguratorSe
} }
override fun registerApplicationServices(application: MockApplication) { override fun registerApplicationServices(application: MockApplication) {
FirAnalysisApiTestConfiguratorService.registerApplicationServices(application) FirAnalysisApiNormalModeTestConfiguratorService.registerApplicationServices(application)
if (application.getServiceIfCreated(ClsKotlinBinaryClassCache::class.java) != null) return if (application.getServiceIfCreated(ClsKotlinBinaryClassCache::class.java) != null) return
application.registerService(ClsKotlinBinaryClassCache::class.java) application.registerService(ClsKotlinBinaryClassCache::class.java)
application.registerService(FileAttributeService::class.java, DummyFileAttributeService) application.registerService(FileAttributeService::class.java, DummyFileAttributeService)
@@ -68,6 +68,6 @@ object LibraryAnalysisApiTestConfiguratorService : AnalysisApiTestConfiguratorSe
} }
override fun doOutOfBlockModification(file: KtFile) { override fun doOutOfBlockModification(file: KtFile) {
FirAnalysisApiTestConfiguratorService.doOutOfBlockModification(file) FirAnalysisApiNormalModeTestConfiguratorService.doOutOfBlockModification(file)
} }
} }
@@ -10,7 +10,7 @@ import com.intellij.mock.MockProject
import com.intellij.openapi.Disposable import com.intellij.openapi.Disposable
import com.intellij.openapi.vfs.impl.jar.CoreJarFileSystem import com.intellij.openapi.vfs.impl.jar.CoreJarFileSystem
import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.analysis.api.fir.FirAnalysisApiTestConfiguratorService import org.jetbrains.kotlin.analysis.api.fir.FirAnalysisApiNormalModeTestConfiguratorService
import org.jetbrains.kotlin.analysis.test.framework.AnalysisApiTestConfiguratorService import org.jetbrains.kotlin.analysis.test.framework.AnalysisApiTestConfiguratorService
import org.jetbrains.kotlin.analysis.low.level.api.fir.compiler.based.registerTestServices import org.jetbrains.kotlin.analysis.low.level.api.fir.compiler.based.registerTestServices
import org.jetbrains.kotlin.analysis.project.structure.ProjectStructureProvider import org.jetbrains.kotlin.analysis.project.structure.ProjectStructureProvider
@@ -23,7 +23,7 @@ import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
import org.jetbrains.kotlin.test.services.ServiceRegistrationData import org.jetbrains.kotlin.test.services.ServiceRegistrationData
object LibrarySourceAnalysisApiTestConfiguratorService : AnalysisApiTestConfiguratorService { object LibrarySourceAnalysisApiTestConfiguratorService : AnalysisApiTestConfiguratorService {
override val allowDependedAnalysisSession: Boolean get() = false override val analyseInDependentSession: Boolean get() = false
override fun TestConfigurationBuilder.configureTest(disposable: Disposable) { override fun TestConfigurationBuilder.configureTest(disposable: Disposable) {
useConfigurators(::LibraryEnvironmentConfigurator) useConfigurators(::LibraryEnvironmentConfigurator)
@@ -43,10 +43,10 @@ object LibrarySourceAnalysisApiTestConfiguratorService : AnalysisApiTestConfigur
} }
override fun registerApplicationServices(application: MockApplication) { override fun registerApplicationServices(application: MockApplication) {
FirAnalysisApiTestConfiguratorService.registerApplicationServices(application) FirAnalysisApiNormalModeTestConfiguratorService.registerApplicationServices(application)
} }
override fun doOutOfBlockModification(file: KtFile) { override fun doOutOfBlockModification(file: KtFile) {
FirAnalysisApiTestConfiguratorService.doOutOfBlockModification(file) FirAnalysisApiNormalModeTestConfiguratorService.doOutOfBlockModification(file)
} }
} }
@@ -10,8 +10,8 @@ import org.jetbrains.kotlin.analysis.api.components.KtDeclarationRendererOptions
import org.jetbrains.kotlin.analysis.api.components.RendererModifier import org.jetbrains.kotlin.analysis.api.components.RendererModifier
import org.jetbrains.kotlin.analysis.test.framework.services.expressionMarkerProvider import org.jetbrains.kotlin.analysis.test.framework.services.expressionMarkerProvider
import org.jetbrains.kotlin.analysis.api.impl.base.test.TestReferenceResolveResultRenderer.renderResolvedTo 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.test.framework.base.AbstractAnalysisApiBasedSingleModuleTest import org.jetbrains.kotlin.analysis.test.framework.base.AbstractAnalysisApiBasedSingleModuleTest
import org.jetbrains.kotlin.analysis.test.framework.utils.findReferencesAtCaret
import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
@@ -10,6 +10,7 @@ import com.intellij.mock.MockProject
import com.intellij.openapi.Disposable import com.intellij.openapi.Disposable
import com.intellij.openapi.vfs.impl.jar.CoreJarFileSystem import com.intellij.openapi.vfs.impl.jar.CoreJarFileSystem
import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.analysis.api.fir.FirAnalysisApiNormalModeTestConfiguratorService
import org.jetbrains.kotlin.analysis.api.fir.FirAnalysisApiTestConfiguratorService import org.jetbrains.kotlin.analysis.api.fir.FirAnalysisApiTestConfiguratorService
import org.jetbrains.kotlin.analysis.test.framework.AnalysisApiTestConfiguratorService import org.jetbrains.kotlin.analysis.test.framework.AnalysisApiTestConfiguratorService
import org.jetbrains.kotlin.analysis.project.structure.ProjectStructureProvider import org.jetbrains.kotlin.analysis.project.structure.ProjectStructureProvider
@@ -19,11 +20,10 @@ import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
object StandaloneModeConfiguratorService : AnalysisApiTestConfiguratorService { object StandaloneModeConfiguratorService : AnalysisApiTestConfiguratorService {
override val allowDependedAnalysisSession: Boolean override val analyseInDependentSession: Boolean get() = false
get() = false
override fun TestConfigurationBuilder.configureTest(disposable: Disposable) { override fun TestConfigurationBuilder.configureTest(disposable: Disposable) {
with(FirAnalysisApiTestConfiguratorService) { configureTest(disposable) } with(FirAnalysisApiNormalModeTestConfiguratorService) { configureTest(disposable) }
} }
override fun registerProjectServices( override fun registerProjectServices(
@@ -48,6 +48,6 @@ object StandaloneModeConfiguratorService : AnalysisApiTestConfiguratorService {
} }
override fun doOutOfBlockModification(file: KtFile) { override fun doOutOfBlockModification(file: KtFile) {
FirAnalysisApiTestConfiguratorService.doOutOfBlockModification(file) FirAnalysisApiNormalModeTestConfiguratorService.doOutOfBlockModification(file)
} }
} }
@@ -20,7 +20,8 @@ import java.nio.file.Path
interface AnalysisApiTestConfiguratorService { interface AnalysisApiTestConfiguratorService {
val testPrefix: String? get() = null val testPrefix: String? get() = null
val allowDependedAnalysisSession: Boolean get() = true
val analyseInDependentSession: Boolean
fun TestConfigurationBuilder.configureTest(disposable: Disposable) fun TestConfigurationBuilder.configureTest(disposable: Disposable)
fun processTestFiles(files: List<KtFile>): List<KtFile> = files fun processTestFiles(files: List<KtFile>): List<KtFile> = files
@@ -35,19 +35,4 @@ abstract class AbstractAnalysisApiBasedSingleModuleTest : AbstractAnalysisApiBas
protected inline fun <R> executeOnPooledThreadInReadAction(crossinline action: () -> R): R = protected inline fun <R> executeOnPooledThreadInReadAction(crossinline action: () -> R): R =
ApplicationManager.getApplication().executeOnPooledThread<R> { runReadAction(action) }.get() ApplicationManager.getApplication().executeOnPooledThread<R> { runReadAction(action) }.get()
protected fun <R> analyseForTest(contextElement: KtElement, action: KtAnalysisSession.() -> R): R {
return if (useDependedAnalysisSession) {
// Depended mode does not support analysing a KtFile.
// See org.jetbrains.kotlin.analysis.low.level.api.fir.api.LowLevelFirApiFacadeForResolveOnAir#getResolveStateForDependentCopy
if (contextElement is KtFile) {
throw SkipDependedModeException()
}
require(!contextElement.isPhysical)
analyseInDependedAnalysisSession(configurator.getOriginalFile(contextElement.containingKtFile), contextElement, action)
} else {
analyse(contextElement, action)
}
}
} }
@@ -11,6 +11,9 @@ import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.util.Disposer import com.intellij.openapi.util.Disposer
import com.intellij.testFramework.TestDataFile import com.intellij.testFramework.TestDataFile
import junit.framework.ComparisonFailure import junit.framework.ComparisonFailure
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
import org.jetbrains.kotlin.analysis.api.analyse
import org.jetbrains.kotlin.analysis.api.analyseInDependedAnalysisSession
import org.jetbrains.kotlin.analysis.test.framework.AnalysisApiTestConfiguratorService import org.jetbrains.kotlin.analysis.test.framework.AnalysisApiTestConfiguratorService
import org.jetbrains.kotlin.analysis.test.framework.TestWithDisposable import org.jetbrains.kotlin.analysis.test.framework.TestWithDisposable
import org.jetbrains.kotlin.analysis.test.framework.project.structure.KotlinProjectStructureProviderTestImpl import org.jetbrains.kotlin.analysis.test.framework.project.structure.KotlinProjectStructureProviderTestImpl
@@ -22,6 +25,7 @@ import org.jetbrains.kotlin.analysis.test.framework.project.structure.getKtFiles
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.cli.jvm.config.addJavaSourceRoots import org.jetbrains.kotlin.cli.jvm.config.addJavaSourceRoots
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.ExecutionListenerBasedDisposableProvider import org.jetbrains.kotlin.test.ExecutionListenerBasedDisposableProvider
import org.jetbrains.kotlin.test.InTextDirectivesUtils import org.jetbrains.kotlin.test.InTextDirectivesUtils
@@ -42,21 +46,15 @@ import org.junit.jupiter.api.TestInfo
import java.io.File import java.io.File
import java.nio.file.Path import java.nio.file.Path
import java.nio.file.Paths import java.nio.file.Paths
import java.util.concurrent.ExecutionException
import kotlin.io.path.exists import kotlin.io.path.exists
import kotlin.io.path.nameWithoutExtension import kotlin.io.path.nameWithoutExtension
abstract class AbstractAnalysisApiBasedTest : TestWithDisposable() { abstract class AbstractAnalysisApiBasedTest : TestWithDisposable() {
abstract val configurator: AnalysisApiTestConfiguratorService abstract val configurator: AnalysisApiTestConfiguratorService
protected open val enableTestInDependedMode: Boolean
get() = configurator.allowDependedAnalysisSession
protected lateinit var testInfo: KotlinTestInfo protected lateinit var testInfo: KotlinTestInfo
private set private set
protected var useDependedAnalysisSession: Boolean = false
protected lateinit var testDataPath: Path protected lateinit var testDataPath: Path
private set private set
@@ -192,21 +190,15 @@ abstract class AbstractAnalysisApiBasedTest : TestWithDisposable() {
configurator.prepareTestFiles(ktFiles, singleModule, testServices) configurator.prepareTestFiles(ktFiles, singleModule, testServices)
doTestByFileStructure(ktFiles, moduleStructure, testServices) doTestByFileStructure(ktFiles, moduleStructure, testServices)
if (!enableTestInDependedMode || ktFiles.any { }
InTextDirectivesUtils.isDirectiveDefined(it.text, DISABLE_DEPENDED_MODE_DIRECTIVE)
}) { protected fun <R> analyseForTest(contextElement: KtElement, action: KtAnalysisSession.() -> R): R {
return return if (configurator.analyseInDependentSession) {
} require(!contextElement.isPhysical)
try { val originalFile = configurator.getOriginalFile(contextElement.containingKtFile)
useDependedAnalysisSession = true analyseInDependedAnalysisSession(originalFile, contextElement, action)
doTestByFileStructure(configurator.processTestFiles(ktFiles), moduleStructure, testServices) } else {
} catch (e: SkipDependedModeException) { analyse(contextElement, action)
// Skip the test if needed
} catch (e: ExecutionException) {
if (e.cause !is SkipDependedModeException)
throw Exception("Test succeeded in normal analysis mode but failed in depended analysis mode.", e)
} catch (e: Exception) {
throw Exception("Test succeeded in normal analysis mode but failed in depended analysis mode.", e)
} }
} }
@@ -226,8 +218,6 @@ abstract class AbstractAnalysisApiBasedTest : TestWithDisposable() {
) )
} }
protected class SkipDependedModeException : Exception()
companion object { companion object {
val DISABLE_DEPENDED_MODE_DIRECTIVE = "DISABLE_DEPENDED_MODE" val DISABLE_DEPENDED_MODE_DIRECTIVE = "DISABLE_DEPENDED_MODE"
} }
@@ -78,8 +78,6 @@ abstract class AbstractFirLazyDeclarationResolveTest : AbstractLowLevelApiSingle
testServices.assertions.assertEqualsToTestDataFileSibling(resultBuilder.toString()) testServices.assertions.assertEqualsToTestDataFileSibling(resultBuilder.toString())
} }
override val enableTestInDependedMode: Boolean = false
override fun configureTest(builder: TestConfigurationBuilder) { override fun configureTest(builder: TestConfigurationBuilder) {
super.configureTest(builder) super.configureTest(builder)
with(builder) { with(builder) {
@@ -40,5 +40,5 @@ abstract class AbstractFirOnAirResolveTest : AbstractLowLevelApiSingleFileTest()
} }
} }
override val enableTestInDependedMode: Boolean get() = false // override val enableTestInDependedMode: Boolean get() = false
} }
@@ -24,6 +24,8 @@ import org.jetbrains.kotlin.test.bind
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
object FirLowLevelAnalysisApiTestConfiguratorService : AnalysisApiTestConfiguratorService { object FirLowLevelAnalysisApiTestConfiguratorService : AnalysisApiTestConfiguratorService {
override val analyseInDependentSession: Boolean get() = false
override fun TestConfigurationBuilder.configureTest(disposable: Disposable) { override fun TestConfigurationBuilder.configureTest(disposable: Disposable) {
usePreAnalysisHandlers(::ModuleRegistrarPreAnalysisHandler.bind(disposable, false)) usePreAnalysisHandlers(::ModuleRegistrarPreAnalysisHandler.bind(disposable, false))
} }
@@ -31,8 +31,6 @@ abstract class AbstractSymbolLightClassesTestBase(
override val configurator: AnalysisApiTestConfiguratorService override val configurator: AnalysisApiTestConfiguratorService
) : AbstractAnalysisApiBasedSingleModuleTest() { ) : AbstractAnalysisApiBasedSingleModuleTest() {
override val enableTestInDependedMode: Boolean get() = false
override fun configureTest(builder: TestConfigurationBuilder) { override fun configureTest(builder: TestConfigurationBuilder) {
super.configureTest(builder) super.configureTest(builder)
with(builder) { with(builder) {
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
import org.jetbrains.kotlin.test.services.ServiceRegistrationData import org.jetbrains.kotlin.test.services.ServiceRegistrationData
internal object SymbolLightClassesForLibraryAnalysisApiTestConfiguratorService : AnalysisApiTestConfiguratorService { internal object SymbolLightClassesForLibraryAnalysisApiTestConfiguratorService : AnalysisApiTestConfiguratorService {
override val analyseInDependentSession: Boolean get() = false
override fun TestConfigurationBuilder.configureTest(disposable: Disposable) { override fun TestConfigurationBuilder.configureTest(disposable: Disposable) {
with(LibraryAnalysisApiTestConfiguratorService) { with(LibraryAnalysisApiTestConfiguratorService) {
configureTest(disposable) configureTest(disposable)
@@ -5,12 +5,12 @@
package org.jetbrains.kotlin.light.classes.symbol.source package org.jetbrains.kotlin.light.classes.symbol.source
import org.jetbrains.kotlin.analysis.api.fir.FirAnalysisApiTestConfiguratorService import org.jetbrains.kotlin.analysis.api.fir.FirAnalysisApiNormalModeTestConfiguratorService
import org.jetbrains.kotlin.light.classes.symbol.base.AbstractSymbolLightClassesFacadeTest import org.jetbrains.kotlin.light.classes.symbol.base.AbstractSymbolLightClassesFacadeTest
abstract class AbstractSymbolLightClassesFacadeForSourceTest : abstract class AbstractSymbolLightClassesFacadeForSourceTest :
AbstractSymbolLightClassesFacadeTest( AbstractSymbolLightClassesFacadeTest(
FirAnalysisApiTestConfiguratorService, FirAnalysisApiNormalModeTestConfiguratorService,
EXTENSIONS.FIR_JAVA, EXTENSIONS.FIR_JAVA,
stopIfCompilationErrorDirectivePresent = false stopIfCompilationErrorDirectivePresent = false
) )
@@ -5,12 +5,12 @@
package org.jetbrains.kotlin.light.classes.symbol.source package org.jetbrains.kotlin.light.classes.symbol.source
import org.jetbrains.kotlin.analysis.api.fir.FirAnalysisApiTestConfiguratorService import org.jetbrains.kotlin.analysis.api.fir.FirAnalysisApiNormalModeTestConfiguratorService
import org.jetbrains.kotlin.light.classes.symbol.base.AbstractSymbolLightClassesTest import org.jetbrains.kotlin.light.classes.symbol.base.AbstractSymbolLightClassesTest
abstract class AbstractSymbolLightClassesForSourceTest : abstract class AbstractSymbolLightClassesForSourceTest :
AbstractSymbolLightClassesTest( AbstractSymbolLightClassesTest(
FirAnalysisApiTestConfiguratorService, FirAnalysisApiNormalModeTestConfiguratorService,
EXTENSIONS.FIR_JAVA, EXTENSIONS.FIR_JAVA,
stopIfCompilationErrorDirectivePresent = false stopIfCompilationErrorDirectivePresent = false
) )
@@ -5,12 +5,12 @@
package org.jetbrains.kotlin.light.classes.symbol.source package org.jetbrains.kotlin.light.classes.symbol.source
import org.jetbrains.kotlin.analysis.api.fir.FirAnalysisApiTestConfiguratorService import org.jetbrains.kotlin.analysis.api.fir.FirAnalysisApiNormalModeTestConfiguratorService
import org.jetbrains.kotlin.light.classes.symbol.base.AbstractSymbolLightClassesLoadingTest import org.jetbrains.kotlin.light.classes.symbol.base.AbstractSymbolLightClassesLoadingTest
abstract class AbstractSymbolLightClassesLoadingForSourceTest : abstract class AbstractSymbolLightClassesLoadingForSourceTest :
AbstractSymbolLightClassesLoadingTest( AbstractSymbolLightClassesLoadingTest(
FirAnalysisApiTestConfiguratorService, FirAnalysisApiNormalModeTestConfiguratorService,
EXTENSIONS.FIR_JAVA, EXTENSIONS.FIR_JAVA,
stopIfCompilationErrorDirectivePresent = false stopIfCompilationErrorDirectivePresent = false
) )
@@ -6,7 +6,7 @@
package org.jetbrains.kotlin.generators.tests.analysis.api.dsl package org.jetbrains.kotlin.generators.tests.analysis.api.dsl
import org.jetbrains.annotations.NotNull import org.jetbrains.annotations.NotNull
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.FrontendApiTestConfiguratorService import org.jetbrains.kotlin.analysis.test.framework.AnalysisApiTestConfiguratorService
import org.jetbrains.kotlin.generators.MethodGenerator import org.jetbrains.kotlin.generators.MethodGenerator
import org.jetbrains.kotlin.generators.model.MethodModel import org.jetbrains.kotlin.generators.model.MethodModel
import org.jetbrains.kotlin.utils.Printer import org.jetbrains.kotlin.utils.Printer
@@ -31,7 +31,7 @@ object FrontendConfiguratorTestGenerator : MethodGenerator<FrontendConfiguratorT
object FrontendConfiguratorTestModelKind : MethodModel.Kind() object FrontendConfiguratorTestModelKind : MethodModel.Kind()
class FrontendConfiguratorTestModel(val frontendConfiguratorClass: KClass<out FrontendApiTestConfiguratorService>) : MethodModel { class FrontendConfiguratorTestModel(val frontendConfiguratorClass: KClass<out AnalysisApiTestConfiguratorService>) : MethodModel {
override val kind: MethodModel.Kind get() = FrontendConfiguratorTestModelKind override val kind: MethodModel.Kind get() = FrontendConfiguratorTestModelKind
override val name: String get() = "getConfigurator" override val name: String get() = "getConfigurator"
override val dataString: String? get() = null override val dataString: String? get() = null
@@ -43,7 +43,7 @@ class FrontendConfiguratorTestModel(val frontendConfiguratorClass: KClass<out Fr
override fun imports(): Collection<Class<*>> { override fun imports(): Collection<Class<*>> {
return buildList { return buildList {
add(NotNull::class.java) add(NotNull::class.java)
add(FrontendApiTestConfiguratorService::class.java) add(AnalysisApiTestConfiguratorService::class.java)
add(frontendConfiguratorClass.java) add(frontendConfiguratorClass.java)
} }
} }
@@ -6,18 +6,19 @@
package org.jetbrains.kotlin.generators.tests.analysis.api.dsl package org.jetbrains.kotlin.generators.tests.analysis.api.dsl
import org.jetbrains.kotlin.analysis.api.descriptors.test.KtFe10AnalysisApiTestConfiguratorService import org.jetbrains.kotlin.analysis.api.descriptors.test.KtFe10AnalysisApiTestConfiguratorService
import org.jetbrains.kotlin.analysis.api.fir.FirAnalysisApiTestConfiguratorService import org.jetbrains.kotlin.analysis.api.fir.FirAnalysisApiDependentModeTestConfiguratorService
import org.jetbrains.kotlin.analysis.api.fir.FirAnalysisApiNormalModeTestConfiguratorService
import org.jetbrains.kotlin.analysis.api.fir.utils.libraries.binary.LibraryAnalysisApiTestConfiguratorService import org.jetbrains.kotlin.analysis.api.fir.utils.libraries.binary.LibraryAnalysisApiTestConfiguratorService
import org.jetbrains.kotlin.analysis.api.fir.utils.libraries.source.LibrarySourceAnalysisApiTestConfiguratorService import org.jetbrains.kotlin.analysis.api.fir.utils.libraries.source.LibrarySourceAnalysisApiTestConfiguratorService
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.FrontendApiTestConfiguratorService
import org.jetbrains.kotlin.analysis.api.standalone.StandaloneModeConfiguratorService import org.jetbrains.kotlin.analysis.api.standalone.StandaloneModeConfiguratorService
import org.jetbrains.kotlin.analysis.test.framework.AnalysisApiTestConfiguratorService
import org.jetbrains.kotlin.generators.TestGroup import org.jetbrains.kotlin.generators.TestGroup
import org.jetbrains.kotlin.generators.TestGroupSuite import org.jetbrains.kotlin.generators.TestGroupSuite
import org.jetbrains.kotlin.generators.getDefaultSuiteTestClassName import org.jetbrains.kotlin.generators.getDefaultSuiteTestClassName
import org.jetbrains.kotlin.util.capitalizeDecapitalize.capitalizeAsciiOnly import org.jetbrains.kotlin.util.capitalizeDecapitalize.capitalizeAsciiOnly
import kotlin.reflect.KClass import kotlin.reflect.KClass
internal class FirAndFe10TestGroup( internal data class FirAndFe10TestGroup(
val suite: TestGroupSuite, val suite: TestGroupSuite,
val directory: String?, val directory: String?,
val testModuleKinds: List<TestModuleKind>, val testModuleKinds: List<TestModuleKind>,
@@ -36,6 +37,11 @@ internal sealed class TestModuleKind(val componentName: String) {
} }
} }
internal enum class AnalysisMode(val suffix: String) {
NORMAL("NormalMode"),
DEPENDENT("DependentMode"),
}
internal enum class Frontend(val prefix: String) { internal enum class Frontend(val prefix: String) {
FIR("Fir"), FIR("Fir"),
FE10("Fe10"), FE10("Fe10"),
@@ -44,12 +50,14 @@ internal enum class Frontend(val prefix: String) {
internal fun FirAndFe10TestGroup.test( internal fun FirAndFe10TestGroup.test(
baseClass: KClass<*>, baseClass: KClass<*>,
generateFe10: Boolean = true, generateFe10: Boolean = true,
analysisModesForFir: List<AnalysisMode> = listOf(AnalysisMode.NORMAL, AnalysisMode.DEPENDENT),
init: TestGroup.TestClass.(module: TestModuleKind) -> Unit, init: TestGroup.TestClass.(module: TestModuleKind) -> Unit,
) { ) {
analysisApiTest( analysisApiTest(
"analysis/analysis-api-fir/tests", "analysis/analysis-api-fir/tests",
Frontend.FIR, Frontend.FIR,
baseClass, baseClass,
analysisModesForFir,
init init
) )
if (generateFe10) { if (generateFe10) {
@@ -57,6 +65,7 @@ internal fun FirAndFe10TestGroup.test(
"analysis/analysis-api-fe10/tests", "analysis/analysis-api-fe10/tests",
Frontend.FE10, Frontend.FE10,
baseClass, baseClass,
listOf(AnalysisMode.NORMAL),
init init
) )
} }
@@ -66,9 +75,10 @@ internal fun TestGroupSuite.test(
baseClass: KClass<*>, baseClass: KClass<*>,
addFe10: Boolean = true, addFe10: Boolean = true,
testModuleKinds: List<TestModuleKind> = TestModuleKind.SOURCE_ONLY, testModuleKinds: List<TestModuleKind> = TestModuleKind.SOURCE_ONLY,
analysisModesForFir: List<AnalysisMode> = listOf(AnalysisMode.NORMAL, AnalysisMode.DEPENDENT),
init: TestGroup.TestClass.(module: TestModuleKind) -> Unit, init: TestGroup.TestClass.(module: TestModuleKind) -> Unit,
) { ) {
FirAndFe10TestGroup(this, directory = null, testModuleKinds).test(baseClass, addFe10, init) FirAndFe10TestGroup(this, directory = null, testModuleKinds).test(baseClass, addFe10, analysisModesForFir, init)
} }
internal fun TestGroupSuite.group( internal fun TestGroupSuite.group(
@@ -90,16 +100,15 @@ private fun FirAndFe10TestGroup.analysisApiTest(
testRoot: String, testRoot: String,
frontend: Frontend, frontend: Frontend,
testClass: KClass<*>, testClass: KClass<*>,
analysisModes: List<AnalysisMode>,
init: TestGroup.TestClass.(module: TestModuleKind) -> Unit, init: TestGroup.TestClass.(module: TestModuleKind) -> Unit,
) { ) {
with(suite) { with(suite) {
val fullTestPath = "analysis/analysis-api/testData" + directory?.let { "/$it" }.orEmpty() val fullTestPath = "analysis/analysis-api/testData" + directory?.let { "/$it" }.orEmpty()
testGroup(testRoot, fullTestPath) { testGroup(testRoot, fullTestPath) {
if (testModuleKinds.size == 1) { for (testModuleKind in testModuleKinds) {
analysisApiTestClass(frontend, moduleKind = testModuleKinds.single(), testClass, prefixNeeded = false, init) for (analysisMode in analysisModes) {
} else { analysisApiTestClass(frontend, testModuleKind, analysisMode, testClass, init)
testModuleKinds.forEach { component ->
analysisApiTestClass(frontend, component, testClass, prefixNeeded = true, init)
} }
} }
} }
@@ -109,8 +118,8 @@ private fun FirAndFe10TestGroup.analysisApiTest(
private fun TestGroup.analysisApiTestClass( private fun TestGroup.analysisApiTestClass(
frontend: Frontend, frontend: Frontend,
moduleKind: TestModuleKind, moduleKind: TestModuleKind,
analysisMode: AnalysisMode,
testClass: KClass<*>, testClass: KClass<*>,
prefixNeeded: Boolean,
init: TestGroup.TestClass.(module: TestModuleKind) -> Unit init: TestGroup.TestClass.(module: TestModuleKind) -> Unit
) { ) {
val fullPackage = getPackageName(frontend.prefix, testClass) val fullPackage = getPackageName(frontend.prefix, testClass)
@@ -118,16 +127,15 @@ private fun TestGroup.analysisApiTestClass(
val suiteTestClassName = buildString { val suiteTestClassName = buildString {
append(fullPackage) append(fullPackage)
append(frontend.prefix) append(frontend.prefix)
moduleKind.componentName append(moduleKind.componentName.capitalizeAsciiOnly())
.capitalizeAsciiOnly() append(analysisMode.suffix)
.takeIf { prefixNeeded }
?.let(::append)
append(getDefaultSuiteTestClassName(testClass.java.simpleName)) append(getDefaultSuiteTestClassName(testClass.java.simpleName))
} }
getDefaultSuiteTestClassName(testClass.java.simpleName) getDefaultSuiteTestClassName(testClass.java.simpleName)
val configurator = createConfigurator(frontend, moduleKind) val configurator = createConfigurator(frontend, moduleKind, analysisMode)
testClass( testClass(
testClass, testClass,
@@ -141,25 +149,56 @@ private fun TestGroup.analysisApiTestClass(
internal fun createConfigurator( internal fun createConfigurator(
frontend: Frontend, frontend: Frontend,
moduleKind: TestModuleKind moduleKind: TestModuleKind,
): KClass<out FrontendApiTestConfiguratorService> = when (frontend) { analysisMode: AnalysisMode,
): KClass<out AnalysisApiTestConfiguratorService> = when (frontend) {
Frontend.FIR -> when (moduleKind) { Frontend.FIR -> when (moduleKind) {
TestModuleKind.SOURCE -> FirAnalysisApiTestConfiguratorService::class TestModuleKind.SOURCE -> when (analysisMode) {
TestModuleKind.LIBRARY -> LibraryAnalysisApiTestConfiguratorService::class AnalysisMode.NORMAL -> FirAnalysisApiNormalModeTestConfiguratorService::class
TestModuleKind.LIBRARY_SOURCE -> LibrarySourceAnalysisApiTestConfiguratorService::class AnalysisMode.DEPENDENT -> FirAnalysisApiDependentModeTestConfiguratorService::class
TestModuleKind.STANDALONE_MODE -> StandaloneModeConfiguratorService::class }
TestModuleKind.LIBRARY -> {
checkNormalMode(frontend, moduleKind, analysisMode)
LibraryAnalysisApiTestConfiguratorService::class
}
TestModuleKind.LIBRARY_SOURCE -> {
checkNormalMode(frontend, moduleKind, analysisMode)
LibrarySourceAnalysisApiTestConfiguratorService::class
}
TestModuleKind.STANDALONE_MODE -> {
checkNormalMode(frontend, moduleKind, analysisMode)
StandaloneModeConfiguratorService::class
}
} }
Frontend.FE10 -> when (moduleKind) { Frontend.FE10 -> when (moduleKind) {
TestModuleKind.SOURCE -> KtFe10AnalysisApiTestConfiguratorService::class TestModuleKind.SOURCE -> {
checkNormalMode(frontend, moduleKind, analysisMode)
KtFe10AnalysisApiTestConfiguratorService::class
}
TestModuleKind.LIBRARY -> TODO("TestModuleKind.LIBRARY is unsupported for fe10") TestModuleKind.LIBRARY -> TODO("TestModuleKind.LIBRARY is unsupported for fe10")
TestModuleKind.LIBRARY_SOURCE -> TODO("TestModuleKind.LIBRARY_SOURCE is unsupported for fe10") TestModuleKind.LIBRARY_SOURCE -> TODO("TestModuleKind.LIBRARY_SOURCE is unsupported for fe10")
TestModuleKind.STANDALONE_MODE -> TODO("TestModuleKind.STANDALONE_MODE is unsupported for fe10") TestModuleKind.STANDALONE_MODE -> TODO("TestModuleKind.STANDALONE_MODE is unsupported for fe10")
} }
} }
private fun checkNormalMode(
frontend: Frontend,
moduleKind: TestModuleKind,
analysisMode: AnalysisMode
) {
if (analysisMode == AnalysisMode.DEPENDENT) {
TODO("${AnalysisMode.DEPENDENT} is not supported for $frontend with $moduleKind")
}
}
private fun getPackageName(prefix: String, testClass: KClass<*>): String { private fun getPackageName(prefix: String, testClass: KClass<*>): String {
val basePrefix = "org.jetbrains.kotlin.analysis.api.${prefix.lowercase()}" val basePrefix = "org.jetbrains.kotlin.analysis.api.${prefix.lowercase()}.test.cases"
val packagePrefix = testClass.java.name val packagePrefix = testClass.java.name
.substringAfter("org.jetbrains.kotlin.analysis.api.impl.base.test.") .substringAfter("org.jetbrains.kotlin.analysis.api.impl.base.test.")
.substringBeforeLast('.', "") .substringBeforeLast('.', "")
@@ -7,8 +7,9 @@ package org.jetbrains.kotlin.generators.tests.analysis.api
import org.jetbrains.kotlin.generators.TestGroupSuite import org.jetbrains.kotlin.generators.TestGroupSuite
import org.jetbrains.kotlin.analysis.api.standalone.AbstractStandaloneModeSingleModuleTest import org.jetbrains.kotlin.analysis.api.standalone.AbstractStandaloneModeSingleModuleTest
import org.jetbrains.kotlin.generators.tests.analysis.api.dsl.*
import org.jetbrains.kotlin.generators.tests.analysis.api.dsl.AnalysisMode
import org.jetbrains.kotlin.generators.tests.analysis.api.dsl.Frontend import org.jetbrains.kotlin.generators.tests.analysis.api.dsl.Frontend
import org.jetbrains.kotlin.generators.tests.analysis.api.dsl.FrontendConfiguratorTestModel
import org.jetbrains.kotlin.generators.tests.analysis.api.dsl.TestModuleKind import org.jetbrains.kotlin.generators.tests.analysis.api.dsl.TestModuleKind
import org.jetbrains.kotlin.generators.tests.analysis.api.dsl.createConfigurator import org.jetbrains.kotlin.generators.tests.analysis.api.dsl.createConfigurator
@@ -17,7 +18,7 @@ internal fun TestGroupSuite.generateStandaloneModeTests() {
"analysis/analysis-api-standalone/tests", "analysis/analysis-api-standalone/tests",
"analysis/analysis-api/testData" "analysis/analysis-api/testData"
) { ) {
val configurator = createConfigurator(Frontend.FIR, TestModuleKind.STANDALONE_MODE) val configurator = createConfigurator(Frontend.FIR, TestModuleKind.STANDALONE_MODE, analysisMode = AnalysisMode.NORMAL)
testClass<AbstractStandaloneModeSingleModuleTest> { testClass<AbstractStandaloneModeSingleModuleTest> {
method(FrontendConfiguratorTestModel(configurator)) method(FrontendConfiguratorTestModel(configurator))
model("standalone/singleModule") model("standalone/singleModule")