FIR IDE: simplify test generation dsl

This commit is contained in:
Ilya Kirillov
2021-12-31 19:36:08 +03:00
parent b916c5116a
commit 5c22a03e82
11 changed files with 259 additions and 194 deletions
@@ -7,10 +7,11 @@ package org.jetbrains.kotlin.generators.tests.analysis.api
import org.jetbrains.kotlin.generators.TestGroupSuite import org.jetbrains.kotlin.generators.TestGroupSuite
import org.jetbrains.kotlin.generators.generateTestGroupSuiteWithJUnit5 import org.jetbrains.kotlin.generators.generateTestGroupSuiteWithJUnit5
import org.jetbrains.kotlin.generators.tests.analysis.api.dsl.FrontendConfiguratorTestGenerator
fun main(args: Array<String>) { fun main(args: Array<String>) {
System.setProperty("java.awt.headless", "true") System.setProperty("java.awt.headless", "true")
generateTestGroupSuiteWithJUnit5(args) { generateTestGroupSuiteWithJUnit5(args, additionalMethodGenerators = listOf(FrontendConfiguratorTestGenerator)) {
generateTests() generateTests()
} }
} }
@@ -5,57 +5,40 @@
package org.jetbrains.kotlin.generators.tests.analysis.api package org.jetbrains.kotlin.generators.tests.analysis.api
import org.jetbrains.kotlin.analysis.api.descriptors.test.annotations.AbstractAnalysisApiFe10AnnotationsOnDeclarationsTest
import org.jetbrains.kotlin.analysis.api.descriptors.test.annotations.AbstractAnalysisApiFe10AnnotationsOnTypesTest
import org.jetbrains.kotlin.analysis.api.descriptors.test.components.callResolver.AbstractKtFe10ResolveCallTest
import org.jetbrains.kotlin.analysis.api.descriptors.test.components.compileTimeConstantProvider.AbstractKtFe10CompileTimeConstantEvaluatorTest
import org.jetbrains.kotlin.analysis.api.descriptors.test.components.diagnosticsProvider.AbstractKtFe10CollectDiagnosticsTest
import org.jetbrains.kotlin.analysis.api.descriptors.test.components.expressionInfoProvider.AbstractKtFe10ReturnTargetSymbolTest
import org.jetbrains.kotlin.analysis.api.descriptors.test.components.expressionInfoProvider.AbstractKtFe10WhenMissingCasesTest
import org.jetbrains.kotlin.analysis.api.descriptors.test.components.expressionTypeProvider.AbstractKtFe10DeclarationReturnTypeTest
import org.jetbrains.kotlin.analysis.api.descriptors.test.components.expressionTypeProvider.AbstractKtFe10ExpectedExpressionTypeTest
import org.jetbrains.kotlin.analysis.api.descriptors.test.components.expressionTypeProvider.AbstractKtFe10HLExpressionTypeTest
import org.jetbrains.kotlin.analysis.api.descriptors.test.components.smartCastProvider.AbstractKtFe10HLSmartCastInfoTest
import org.jetbrains.kotlin.analysis.api.descriptors.test.components.symbolDeclarationOverridesProvider.AbstractKtFe10OverriddenDeclarationProviderTest
import org.jetbrains.kotlin.analysis.api.descriptors.test.components.symbolDeclarationRenderer.AbstractKtFe10RendererTest
import org.jetbrains.kotlin.analysis.api.descriptors.test.components.typeCreator.AbstractKtFe10TypeParameterTypeTest
import org.jetbrains.kotlin.analysis.api.descriptors.test.components.typeProvider.AbstractKtFe10HasCommonSubtypeTest
import org.jetbrains.kotlin.analysis.api.descriptors.test.scopes.AbstractKtFe10SubstitutionOverridesUnwrappingTest
import org.jetbrains.kotlin.analysis.api.descriptors.test.components.typeProvider.AbstractKtFe10IsDenotableTest
import org.jetbrains.kotlin.analysis.api.descriptors.test.symbols.AbstractKtFe10SymbolByFqNameTest
import org.jetbrains.kotlin.analysis.api.descriptors.test.symbols.AbstractKtFe10SymbolByPsiTest
import org.jetbrains.kotlin.analysis.api.descriptors.test.symbols.AbstractKtFe10SymbolByReferenceTest
import org.jetbrains.kotlin.analysis.api.fir.AbstractFirReferenceResolveTest
import org.jetbrains.kotlin.analysis.api.fir.annotations.AbstractAnalysisApiFirAnnotationsOnDeclarationsTest
import org.jetbrains.kotlin.analysis.api.fir.annotations.AbstractAnalysisApiFirAnnotationsOnFilesTest
import org.jetbrains.kotlin.analysis.api.fir.annotations.AbstractAnalysisApiFirAnnotationsOnTypesTest
import org.jetbrains.kotlin.analysis.api.fir.components.callResolver.AbstractFirResolveCallTest
import org.jetbrains.kotlin.analysis.api.fir.components.compileTimeConstantProvider.AbstractFirCompileTimeConstantEvaluatorTest
import org.jetbrains.kotlin.analysis.api.fir.components.diagnosticsProvider.AbstractFirCollectDiagnosticsTest
import org.jetbrains.kotlin.analysis.api.fir.components.expressionInfoProvider.AbstractFirReturnTargetSymbolTest
import org.jetbrains.kotlin.analysis.api.fir.components.expressionInfoProvider.AbstractFirWhenMissingCasesTest
import org.jetbrains.kotlin.analysis.api.fir.components.expressionTypeProvider.AbstractFirDeclarationReturnTypeTest
import org.jetbrains.kotlin.analysis.api.fir.components.expressionTypeProvider.AbstractFirExpectedExpressionTypeTest
import org.jetbrains.kotlin.analysis.api.fir.components.expressionTypeProvider.AbstractFirHLExpressionTypeTest
import org.jetbrains.kotlin.analysis.api.fir.components.importOptimizer.AbstractHLImportOptimizerTest import org.jetbrains.kotlin.analysis.api.fir.components.importOptimizer.AbstractHLImportOptimizerTest
import org.jetbrains.kotlin.analysis.api.fir.components.psiTypeProvider.AbstractExpressionPsiTypeProviderTest import org.jetbrains.kotlin.analysis.api.fir.components.psiTypeProvider.AbstractExpressionPsiTypeProviderTest
import org.jetbrains.kotlin.analysis.api.fir.components.psiTypeProvider.AbstractPsiTypeProviderTest import org.jetbrains.kotlin.analysis.api.fir.components.psiTypeProvider.AbstractPsiTypeProviderTest
import org.jetbrains.kotlin.analysis.api.fir.components.smartCastProvider.AbstractFirHLSmartCastInfoTest
import org.jetbrains.kotlin.analysis.api.fir.components.symbolDeclarationOverridesProvider.AbstractFirOverriddenDeclarationProviderTest
import org.jetbrains.kotlin.analysis.api.fir.components.symbolDeclarationRenderer.AbstractFirRendererTest
import org.jetbrains.kotlin.analysis.api.fir.components.typeCreator.AbstractFirTypeParameterTypeTest
import org.jetbrains.kotlin.analysis.api.fir.components.typeInfoProvider.AbstractFirFunctionClassKindTest
import org.jetbrains.kotlin.analysis.api.fir.components.typeProvider.AbstractFirGetSuperTypesTest import org.jetbrains.kotlin.analysis.api.fir.components.typeProvider.AbstractFirGetSuperTypesTest
import org.jetbrains.kotlin.analysis.api.fir.components.typeProvider.AbstractFirHasCommonSubtypeTest import org.jetbrains.kotlin.analysis.api.impl.base.test.AbstractReferenceResolveTest
import org.jetbrains.kotlin.analysis.api.fir.components.typeProvider.AbstractFirIsDenotableTest import org.jetbrains.kotlin.analysis.api.impl.base.test.annotations.AbstractAnalysisApiAnnotationsOnDeclarationsTest
import org.jetbrains.kotlin.analysis.api.fir.scopes.AbstractFirDelegateMemberScopeTest import org.jetbrains.kotlin.analysis.api.impl.base.test.annotations.AbstractAnalysisApiAnnotationsOnFilesTest
import org.jetbrains.kotlin.analysis.api.fir.scopes.AbstractFirFileScopeTest import org.jetbrains.kotlin.analysis.api.impl.base.test.annotations.AbstractAnalysisApiAnnotationsOnTypesTest
import org.jetbrains.kotlin.analysis.api.fir.scopes.AbstractFirMemberScopeByFqNameTest import org.jetbrains.kotlin.analysis.api.impl.base.test.components.compileTimeConstantProvider.AbstractCompileTimeConstantEvaluatorTest
import org.jetbrains.kotlin.analysis.api.fir.scopes.AbstractFirSubstitutionOverridesUnwrappingTest import org.jetbrains.kotlin.analysis.api.impl.base.test.components.diagnosticProvider.AbstractCollectDiagnosticsTest
import org.jetbrains.kotlin.analysis.api.fir.symbols.AbstractFirSymbolByFqNameTest import org.jetbrains.kotlin.analysis.api.impl.base.test.components.expressionInfoProvider.AbstractReturnTargetSymbolTest
import org.jetbrains.kotlin.analysis.api.fir.symbols.AbstractFirSymbolByPsiTest import org.jetbrains.kotlin.analysis.api.impl.base.test.components.expressionInfoProvider.AbstractWhenMissingCasesTest
import org.jetbrains.kotlin.analysis.api.fir.symbols.AbstractFirSymbolByReferenceTest import org.jetbrains.kotlin.analysis.api.impl.base.test.components.expressionTypeProvider.AbstractDeclarationReturnTypeTest
import org.jetbrains.kotlin.analysis.api.impl.base.test.components.expressionTypeProvider.AbstractExpectedExpressionTypeTest
import org.jetbrains.kotlin.analysis.api.impl.base.test.components.expressionTypeProvider.AbstractHLExpressionTypeTest
import org.jetbrains.kotlin.analysis.api.impl.base.test.components.smartCastProvider.AbstractHLSmartCastInfoTest
import org.jetbrains.kotlin.analysis.api.impl.base.test.components.symbolDeclarationOverridesProvider.AbstractOverriddenDeclarationProviderTest
import org.jetbrains.kotlin.analysis.api.impl.base.test.components.symbolDeclarationRenderer.AbstractRendererTest
import org.jetbrains.kotlin.analysis.api.impl.base.test.components.typeCreator.AbstractTypeParameterTypeTest
import org.jetbrains.kotlin.analysis.api.impl.base.test.components.typeInfoProvider.AbstractFunctionClassKindTest
import org.jetbrains.kotlin.analysis.api.impl.base.test.components.typeInfoProvider.AbstractIsDenotableTest
import org.jetbrains.kotlin.analysis.api.impl.base.test.components.typeProvider.AbstractHasCommonSubtypeTest
import org.jetbrains.kotlin.analysis.api.impl.base.test.fir.AbstractResolveCallTest
import org.jetbrains.kotlin.analysis.api.impl.base.test.scopes.AbstractDelegateMemberScopeTest
import org.jetbrains.kotlin.analysis.api.impl.base.test.scopes.AbstractFileScopeTest
import org.jetbrains.kotlin.analysis.api.impl.base.test.scopes.AbstractMemberScopeByFqNameTest
import org.jetbrains.kotlin.analysis.api.impl.base.test.scopes.AbstractSubstitutionOverridesUnwrappingTest
import org.jetbrains.kotlin.analysis.api.impl.base.test.symbols.AbstractSymbolByFqNameTest
import org.jetbrains.kotlin.analysis.api.impl.base.test.symbols.AbstractSymbolByPsiTest
import org.jetbrains.kotlin.analysis.api.impl.base.test.symbols.AbstractSymbolByReferenceTest
import org.jetbrains.kotlin.generators.TestGroupSuite import org.jetbrains.kotlin.generators.TestGroupSuite
import org.jetbrains.kotlin.generators.tests.analysis.api.dsl.component
import org.jetbrains.kotlin.generators.tests.analysis.api.dsl.group
import org.jetbrains.kotlin.generators.tests.analysis.api.dsl.test
import org.jetbrains.kotlin.generators.util.TestGeneratorUtil import org.jetbrains.kotlin.generators.util.TestGeneratorUtil
fun TestGroupSuite.generateAnalysisApiTests() { fun TestGroupSuite.generateAnalysisApiTests() {
@@ -65,83 +48,70 @@ fun TestGroupSuite.generateAnalysisApiTests() {
private fun TestGroupSuite.generateAnalysisApiNonComponentsTests() { private fun TestGroupSuite.generateAnalysisApiNonComponentsTests() {
test( test(
fir = AbstractFirReferenceResolveTest::class, fe10 = null, AbstractReferenceResolveTest::class,
addFe10 = false,
) { ) {
model("referenceResolve", pattern = TestGeneratorUtil.KT_WITHOUT_DOTS_IN_NAME) model("referenceResolve", pattern = TestGeneratorUtil.KT_WITHOUT_DOTS_IN_NAME)
} }
group("scopes") { group("scopes") {
test( test(
fir = AbstractFirSubstitutionOverridesUnwrappingTest::class, AbstractSubstitutionOverridesUnwrappingTest::class,
fe10 = AbstractKtFe10SubstitutionOverridesUnwrappingTest::class, generateFe10 = false,
) { ) {
model("substitutionOverridesUnwrapping") model("substitutionOverridesUnwrapping")
} }
test( test(
fir = AbstractFirMemberScopeByFqNameTest::class, AbstractMemberScopeByFqNameTest::class,
fe10 = null, generateFe10 = false,
) { ) {
model("memberScopeByFqName") model("memberScopeByFqName")
} }
test( test(
fir = AbstractFirFileScopeTest::class, AbstractFileScopeTest::class,
fe10 = null, generateFe10 = false,
) { ) {
model("fileScopeTest", extension = "kt") model("fileScopeTest", extension = "kt")
} }
test( test(
fir = AbstractFirDelegateMemberScopeTest::class, AbstractDelegateMemberScopeTest::class,
fe10 = null, generateFe10 = false,
) { ) {
model("delegatedMemberScope") model("delegatedMemberScope")
} }
} }
group("symbols") { group("symbols") {
test( test(AbstractSymbolByPsiTest::class) {
fir = AbstractFirSymbolByPsiTest::class,
fe10 = AbstractKtFe10SymbolByPsiTest::class,
) {
model("symbolByPsi") model("symbolByPsi")
} }
test( test(
fir = AbstractFirSymbolByFqNameTest::class, AbstractSymbolByFqNameTest::class
fe10 = AbstractKtFe10SymbolByFqNameTest::class,
) { ) {
model("symbolByFqName") model("symbolByFqName")
} }
test( test(AbstractSymbolByReferenceTest::class) {
fir = AbstractFirSymbolByReferenceTest::class,
fe10 = AbstractKtFe10SymbolByReferenceTest::class,
) {
model("symbolByReference") model("symbolByReference")
} }
} }
group("annotations") { group("annotations") {
test( test(AbstractAnalysisApiAnnotationsOnTypesTest::class) {
fir = AbstractAnalysisApiFirAnnotationsOnTypesTest::class,
fe10 = AbstractAnalysisApiFe10AnnotationsOnTypesTest::class
) {
model("annotationsOnTypes") model("annotationsOnTypes")
} }
test( test(AbstractAnalysisApiAnnotationsOnDeclarationsTest::class) {
fir = AbstractAnalysisApiFirAnnotationsOnDeclarationsTest::class,
fe10 = AbstractAnalysisApiFe10AnnotationsOnDeclarationsTest::class,
) {
model("annotationsOnDeclaration") model("annotationsOnDeclaration")
} }
test( test(
fir = AbstractAnalysisApiFirAnnotationsOnFilesTest::class, AbstractAnalysisApiAnnotationsOnFilesTest::class,
fe10 = null // TODO "fails with Rewrite at slice ANNOTATION key" generateFe10 = false // TODO "fails with Rewrite at slice ANNOTATION key"
/*AbstractAnalysisApiFE10AnnotationsOnFilesTest*/
) { ) {
model("annotationsOnFiles") model("annotationsOnFiles")
} }
@@ -151,121 +121,108 @@ private fun TestGroupSuite.generateAnalysisApiNonComponentsTests() {
private fun TestGroupSuite.generateAnalysisApiComponentsTests() { private fun TestGroupSuite.generateAnalysisApiComponentsTests() {
component("callResolver") { component("callResolver") {
test( test(AbstractResolveCallTest::class) {
fir = AbstractFirResolveCallTest::class,
fe10 = AbstractKtFe10ResolveCallTest::class,
) {
model("resolveCall") model("resolveCall")
} }
} }
component("compileTimeConstantProvider") { component("compileTimeConstantProvider") {
test( test(AbstractCompileTimeConstantEvaluatorTest::class) {
fir = AbstractFirCompileTimeConstantEvaluatorTest::class, fe10 = AbstractKtFe10CompileTimeConstantEvaluatorTest::class,
) {
model("evaluate") model("evaluate")
} }
} }
component("expressionInfoProvider") { component("expressionInfoProvider") {
test( test(AbstractWhenMissingCasesTest::class) {
fir = AbstractFirWhenMissingCasesTest::class, fe10 = AbstractKtFe10WhenMissingCasesTest::class
) {
model("whenMissingCases") model("whenMissingCases")
} }
test( test(AbstractReturnTargetSymbolTest::class) {
fir = AbstractFirReturnTargetSymbolTest::class, fe10 = AbstractKtFe10ReturnTargetSymbolTest::class
) {
model("returnExpressionTargetSymbol") model("returnExpressionTargetSymbol")
} }
} }
component("expressionTypeProvider") { component("expressionTypeProvider") {
test( test(AbstractExpectedExpressionTypeTest::class) {
fir = AbstractFirExpectedExpressionTypeTest::class, fe10 = AbstractKtFe10ExpectedExpressionTypeTest::class
) {
model("expectedExpressionType") model("expectedExpressionType")
} }
test( test(
fir = AbstractFirHLExpressionTypeTest::class, fe10 = AbstractKtFe10HLExpressionTypeTest::class AbstractHLExpressionTypeTest::class
) { ) {
model("expressionType") model("expressionType")
} }
test( test(
fir = AbstractFirDeclarationReturnTypeTest::class, fe10 = AbstractKtFe10DeclarationReturnTypeTest::class AbstractDeclarationReturnTypeTest::class
) { ) {
model("declarationReturnType") model("declarationReturnType")
} }
} }
component("diagnosticsProvider") { component("diagnosticsProvider") {
test( test(AbstractCollectDiagnosticsTest::class) {
fir = AbstractFirCollectDiagnosticsTest::class, fe10 = AbstractKtFe10CollectDiagnosticsTest::class
) {
model("diagnostics") model("diagnostics")
} }
} }
component("importOptimizer") { component("importOptimizer") {
test( test(
fir = AbstractHLImportOptimizerTest::class, AbstractHLImportOptimizerTest::class,
fe10 = null, generateFe10 = false,
) { ) {
model("analyseImports", pattern = TestGeneratorUtil.KT_WITHOUT_DOTS_IN_NAME) model("analyseImports", pattern = TestGeneratorUtil.KT_WITHOUT_DOTS_IN_NAME)
} }
} }
component("psiTypeProvider") { component("psiTypeProvider") {
test(fir = AbstractPsiTypeProviderTest::class, fe10 = null) { test(AbstractPsiTypeProviderTest::class, generateFe10 = false) {
model("psiType/forDeclaration") model("psiType/forDeclaration")
} }
test(fir = AbstractExpressionPsiTypeProviderTest::class, fe10 = null) { test(AbstractExpressionPsiTypeProviderTest::class, generateFe10 = false) {
model("psiType/forExpression") model("psiType/forExpression")
} }
} }
component("smartCastProvider") { component("smartCastProvider") {
test(fir = AbstractFirHLSmartCastInfoTest::class, fe10 = AbstractKtFe10HLSmartCastInfoTest::class) { test(AbstractHLSmartCastInfoTest::class) {
model("smartCastInfo") model("smartCastInfo")
} }
} }
component("symbolDeclarationOverridesProvider") { component("symbolDeclarationOverridesProvider") {
test(fir = AbstractFirOverriddenDeclarationProviderTest::class, fe10 = AbstractKtFe10OverriddenDeclarationProviderTest::class) { test(AbstractOverriddenDeclarationProviderTest::class) {
model("overriddenSymbols") model("overriddenSymbols")
} }
} }
component("symbolDeclarationRenderer") { component("symbolDeclarationRenderer") {
test(fir = AbstractFirRendererTest::class, fe10 = AbstractKtFe10RendererTest::class) { test(AbstractRendererTest::class) {
model("renderDeclaration") model("renderDeclaration")
} }
} }
component("typeCreator") { component("typeCreator") {
test(fir = AbstractFirTypeParameterTypeTest::class, fe10 = AbstractKtFe10TypeParameterTypeTest::class) { test(AbstractTypeParameterTypeTest::class) {
model("typeParameter") model("typeParameter")
} }
} }
component("typeInfoProvider") { component("typeInfoProvider") {
test(fir = AbstractFirFunctionClassKindTest::class, fe10 = null) { test(AbstractFunctionClassKindTest::class, generateFe10 = false) {
model("functionClassKind") model("functionClassKind")
} }
test(fir = AbstractFirGetSuperTypesTest::class, fe10 = null) { test(AbstractFirGetSuperTypesTest::class, generateFe10 = false) {
model("superTypes") model("superTypes")
} }
test(fir = AbstractFirIsDenotableTest::class, fe10 = AbstractKtFe10IsDenotableTest::class) { test(AbstractIsDenotableTest::class) {
model("isDenotable", excludedPattern = ".*\\.descriptors\\.kt$") model("isDenotable", excludedPattern = ".*\\.descriptors\\.kt$")
} }
} }
component("typeProvider") { component("typeProvider") {
test(fir = AbstractFirHasCommonSubtypeTest::class, fe10 = AbstractKtFe10HasCommonSubtypeTest::class) { test(AbstractHasCommonSubtypeTest::class) {
model("haveCommonSubtype") model("haveCommonSubtype")
} }
} }
@@ -1,71 +0,0 @@
/*
* 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.generators.tests.analysis.api
import org.jetbrains.kotlin.generators.TestGroup
import org.jetbrains.kotlin.generators.TestGroupSuite
import kotlin.reflect.KClass
internal class FirAndFe10TestGroup(
val suite: TestGroupSuite,
val directory: String?
)
internal fun FirAndFe10TestGroup.test(
fir: KClass<*>?,
fe10: KClass<*>?,
init: TestGroup.TestClass.() -> Unit,
) {
if (fir != null) {
analysisApiTest("analysis/analysis-api-fir/tests", fir, init)
}
if (fe10 != null) {
analysisApiTest("analysis/analysis-api-fe10/tests", fe10, init)
}
}
internal fun TestGroupSuite.test(
fir: KClass<*>?,
fe10: KClass<*>?,
init: TestGroup.TestClass.() -> Unit,
) {
FirAndFe10TestGroup(this, directory = null).test(fir, fe10, init)
}
internal fun TestGroupSuite.group(
directory: String,
init: FirAndFe10TestGroup.() -> Unit,
) {
FirAndFe10TestGroup(this, directory).init()
}
internal fun TestGroupSuite.component(
directory: String,
init: FirAndFe10TestGroup.() -> Unit,
) {
group("components/$directory", init)
}
private fun FirAndFe10TestGroup.analysisApiTest(
testRoot: String,
testClass: KClass<*>,
init: TestGroup.TestClass.() -> Unit,
) {
with(suite) {
val fullTestPath = "analysis/analysis-api/testData" + directory?.let { "/$it" }.orEmpty()
testGroup(testRoot, fullTestPath) {
testClass(testClass, useJunit4 = false) {
init()
}
}
}
}
@@ -0,0 +1,57 @@
/*
* 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.generators.tests.analysis.api.dsl
import org.jetbrains.annotations.NotNull
import org.jetbrains.kotlin.analysis.api.descriptors.test.KtFe10FrontendApiTestConfiguratorService
import org.jetbrains.kotlin.analysis.api.fir.FirFrontendApiTestConfiguratorService
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.FrontendApiTestConfiguratorService
import org.jetbrains.kotlin.generators.MethodGenerator
import org.jetbrains.kotlin.generators.model.MethodModel
import org.jetbrains.kotlin.utils.Printer
import kotlin.reflect.KClass
object FrontendConfiguratorTestGenerator : MethodGenerator<FrontendConfiguratorTestModel>() {
override val kind: MethodModel.Kind get() = FrontendConfiguratorTestModelKind
override fun generateSignature(method: FrontendConfiguratorTestModel, p: Printer): Unit = with(p) {
println("@NotNull")
println("@Override")
print("public FrontendApiTestConfiguratorService getConfigurator()")
}
override fun generateBody(method: FrontendConfiguratorTestModel, p: Printer): Unit = with(p) {
print("return ")
printWithNoIndent(method.frontendConfiguratorType.configuratorClass.simpleName)
printWithNoIndent(".INSTANCE")
printlnWithNoIndent(";")
}
}
object FrontendConfiguratorTestModelKind : MethodModel.Kind()
class FrontendConfiguratorTestModel(val frontendConfiguratorType: FrontendConfiguratorType) : MethodModel {
override val kind: MethodModel.Kind get() = FrontendConfiguratorTestModelKind
override val name: String get() = "getConfigurator"
override val dataString: String? get() = null
override val tags: List<String> get() = emptyList()
override fun isTestMethod(): Boolean = false
override fun shouldBeGeneratedForInnerTestClass(): Boolean = false
override fun imports(): Collection<Class<*>> {
return buildList {
add(NotNull::class.java)
add(FrontendApiTestConfiguratorService::class.java)
add(frontendConfiguratorType.configuratorClass.java)
}
}
enum class FrontendConfiguratorType(val configuratorClass: KClass<out FrontendApiTestConfiguratorService>) {
FIR(FirFrontendApiTestConfiguratorService::class),
FE10(KtFe10FrontendApiTestConfiguratorService::class);
}
}
@@ -0,0 +1,101 @@
/*
* 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.generators.tests.analysis.api.dsl
import org.jetbrains.kotlin.generators.TestGroup
import org.jetbrains.kotlin.generators.TestGroupSuite
import org.jetbrains.kotlin.generators.getDefaultSuiteTestClassName
import kotlin.reflect.KClass
internal class FirAndFe10TestGroup(
val suite: TestGroupSuite,
val directory: String?
)
internal fun FirAndFe10TestGroup.test(
baseClass: KClass<*>,
generateFe10: Boolean = true,
init: TestGroup.TestClass.() -> Unit,
) {
analysisApiTest(
"analysis/analysis-api-fir/tests",
FrontendConfiguratorTestModel.FrontendConfiguratorType.FIR,
baseClass,
init
)
if (generateFe10) {
analysisApiTest(
"analysis/analysis-api-fe10/tests",
FrontendConfiguratorTestModel.FrontendConfiguratorType.FE10,
baseClass,
init
)
}
}
internal fun TestGroupSuite.test(
baseClass: KClass<*>,
addFe10: Boolean = true,
init: TestGroup.TestClass.() -> Unit,
) {
FirAndFe10TestGroup(this, directory = null).test(baseClass, addFe10, init)
}
internal fun TestGroupSuite.group(
directory: String,
init: FirAndFe10TestGroup.() -> Unit,
) {
FirAndFe10TestGroup(this, directory).init()
}
internal fun TestGroupSuite.component(
directory: String,
init: FirAndFe10TestGroup.() -> Unit,
) {
group("components/$directory", init)
}
private fun FirAndFe10TestGroup.analysisApiTest(
testRoot: String,
frontendConfiguratorType: FrontendConfiguratorTestModel.FrontendConfiguratorType,
testClass: KClass<*>,
init: TestGroup.TestClass.() -> Unit,
) {
with(suite) {
val fullTestPath = "analysis/analysis-api/testData" + directory?.let { "/$it" }.orEmpty()
testGroup(testRoot, fullTestPath) {
val prefix = when (frontendConfiguratorType) {
FrontendConfiguratorTestModel.FrontendConfiguratorType.FIR -> "Fir"
FrontendConfiguratorTestModel.FrontendConfiguratorType.FE10 -> "Fe10"
}
val fullPackage = getPackageName(prefix, testClass)
testClass(
testClass,
suiteTestClassName = fullPackage + prefix + getDefaultSuiteTestClassName(testClass.java.simpleName),
useJunit4 = false
) {
method(FrontendConfiguratorTestModel(frontendConfiguratorType))
init()
}
}
}
}
private fun getPackageName(prefix: String, testClass: KClass<*>): String {
val basePrefix = "org.jetbrains.kotlin.analysis.api.${prefix.lowercase()}"
val packagePrefix = testClass.java.name
.substringAfter("org.jetbrains.kotlin.analysis.api.impl.base.test.")
.substringBeforeLast('.', "")
return if (packagePrefix.isEmpty()) "$basePrefix." else "$basePrefix.$packagePrefix."
}
@@ -7,19 +7,21 @@ package org.jetbrains.kotlin.generators
fun generateTestGroupSuiteWithJUnit5( fun generateTestGroupSuiteWithJUnit5(
args: Array<String>, args: Array<String>,
additionalMethodGenerators: List<MethodGenerator<Nothing>> = emptyList(),
init: TestGroupSuite.() -> Unit init: TestGroupSuite.() -> Unit
) { ) {
generateTestGroupSuiteWithJUnit5(InconsistencyChecker.hasDryRunArg(args), init) generateTestGroupSuiteWithJUnit5(InconsistencyChecker.hasDryRunArg(args), additionalMethodGenerators, init)
} }
fun generateTestGroupSuiteWithJUnit5( fun generateTestGroupSuiteWithJUnit5(
dryRun: Boolean = false, dryRun: Boolean = false,
additionalMethodGenerators: List<MethodGenerator<Nothing>> = emptyList(),
init: TestGroupSuite.() -> Unit init: TestGroupSuite.() -> Unit
) { ) {
val suite = TestGroupSuite(ReflectionBasedTargetBackendComputer).apply(init) val suite = TestGroupSuite(ReflectionBasedTargetBackendComputer).apply(init)
for (testGroup in suite.testGroups) { for (testGroup in suite.testGroups) {
for (testClass in testGroup.testClasses) { for (testClass in testGroup.testClasses) {
val (changed, testSourceFilePath) = NewTestGeneratorImpl.generateAndSave(testClass, dryRun) val (changed, testSourceFilePath) = NewTestGeneratorImpl(additionalMethodGenerators).generateAndSave(testClass, dryRun)
if (changed) { if (changed) {
InconsistencyChecker.inconsistencyChecker(dryRun).add(testSourceFilePath) InconsistencyChecker.inconsistencyChecker(dryRun).add(testSourceFilePath)
} }
@@ -29,7 +29,10 @@ private val METHOD_GENERATORS = listOf(
TransformingTestMethodGenerator, TransformingTestMethodGenerator,
) )
object NewTestGeneratorImpl : TestGenerator(METHOD_GENERATORS) { class NewTestGeneratorImpl(
additionalMethodGenerators: List<MethodGenerator<Nothing>>
) : TestGenerator(METHOD_GENERATORS + additionalMethodGenerators) {
private val GENERATED_FILES = HashSet<String>() private val GENERATED_FILES = HashSet<String>()
private fun Printer.generateMetadata(testDataSource: TestEntityModel) { private fun Printer.generateMetadata(testDataSource: TestEntityModel) {
@@ -84,7 +87,7 @@ object NewTestGeneratorImpl : TestGenerator(METHOD_GENERATORS) {
return generatorInstance.generateAndSave(dryRun) return generatorInstance.generateAndSave(dryRun)
} }
private class TestGeneratorInstance( private inner class TestGeneratorInstance(
baseDir: String, baseDir: String,
suiteTestClassFqName: String, suiteTestClassFqName: String,
baseTestClassFqName: String, baseTestClassFqName: String,
@@ -95,7 +98,8 @@ object NewTestGeneratorImpl : TestGenerator(METHOD_GENERATORS) {
private val baseTestClassName: String = baseTestClassFqName.substringAfterLast('.', baseTestClassFqName) private val baseTestClassName: String = baseTestClassFqName.substringAfterLast('.', baseTestClassFqName)
private val suiteClassPackage: String = suiteTestClassFqName.substringBeforeLast('.', baseTestClassPackage) private val suiteClassPackage: String = suiteTestClassFqName.substringBeforeLast('.', baseTestClassPackage)
private val suiteClassName: String = suiteTestClassFqName.substringAfterLast('.', suiteTestClassFqName) private val suiteClassName: String = suiteTestClassFqName.substringAfterLast('.', suiteTestClassFqName)
private val testSourceFilePath: String = baseDir + "/" + this.suiteClassPackage.replace(".", "/") + "/" + this.suiteClassName + ".java" private val testSourceFilePath: String =
baseDir + "/" + this.suiteClassPackage.replace(".", "/") + "/" + this.suiteClassName + ".java"
init { init {
if (!GENERATED_FILES.add(testSourceFilePath)) { if (!GENERATED_FILES.add(testSourceFilePath)) {
@@ -256,9 +260,11 @@ object NewTestGeneratorImpl : TestGenerator(METHOD_GENERATORS) {
private fun generateTestMethod(p: Printer, methodModel: MethodModel) { private fun generateTestMethod(p: Printer, methodModel: MethodModel) {
val generator = methodGenerators.getValue(methodModel.kind) val generator = methodGenerators.getValue(methodModel.kind)
p.generateTestAnnotation() if (methodModel.isTestMethod()) {
p.generateTags(methodModel) p.generateTestAnnotation()
p.generateMetadata(methodModel) p.generateTags(methodModel)
p.generateMetadata(methodModel)
}
generator.hackyGenerateSignature(methodModel, p) generator.hackyGenerateSignature(methodModel, p)
p.printWithNoIndent(" {") p.printWithNoIndent(" {")
p.println() p.println()
@@ -86,6 +86,11 @@ class TestGroup(
get() = this@TestGroup.testsRoot get() = this@TestGroup.testsRoot
val testModels = ArrayList<TestClassModel>() val testModels = ArrayList<TestClassModel>()
private val methodModels = mutableListOf<MethodModel>()
fun method(method: MethodModel) {
methodModels += method
}
fun model( fun model(
relativeRootPath: String, relativeRootPath: String,
@@ -117,14 +122,14 @@ class TestGroup(
SingleClassTestModel( SingleClassTestModel(
rootFile, compiledPattern, compiledExcludedPattern, filenameStartsLowerCase, testMethod, className, rootFile, compiledPattern, compiledExcludedPattern, filenameStartsLowerCase, testMethod, className,
realTargetBackend, skipIgnored, testRunnerMethodName, additionalRunnerArguments, annotations, realTargetBackend, skipIgnored, testRunnerMethodName, additionalRunnerArguments, annotations,
extractTagsFromDirectory(rootFile) extractTagsFromDirectory(rootFile), methodModels
) )
} else { } else {
SimpleTestClassModel( SimpleTestClassModel(
rootFile, recursive, excludeParentDirs, rootFile, recursive, excludeParentDirs,
compiledPattern, compiledExcludedPattern, filenameStartsLowerCase, testMethod, className, compiledPattern, compiledExcludedPattern, filenameStartsLowerCase, testMethod, className,
realTargetBackend, excludeDirs, skipIgnored, testRunnerMethodName, additionalRunnerArguments, deep, annotations, realTargetBackend, excludeDirs, skipIgnored, testRunnerMethodName, additionalRunnerArguments, deep, annotations,
extractTagsFromDirectory(rootFile) extractTagsFromDirectory(rootFile), methodModels
) )
} }
) )
@@ -30,7 +30,8 @@ class SimpleTestClassModel(
private val additionalRunnerArguments: List<String>, private val additionalRunnerArguments: List<String>,
private val deep: Int?, private val deep: Int?,
override val annotations: Collection<AnnotationModel>, override val annotations: Collection<AnnotationModel>,
override val tags: List<String> override val tags: List<String>,
private val additionalMethods: Collection<MethodModel>,
) : TestClassModel() { ) : TestClassModel() {
override val name: String override val name: String
get() = testClassName get() = testClassName
@@ -63,7 +64,8 @@ class SimpleTestClassModel(
additionalRunnerArguments, additionalRunnerArguments,
if (deep != null) deep - 1 else null, if (deep != null) deep - 1 else null,
annotations, annotations,
extractTagsFromDirectory(file) extractTagsFromDirectory(file),
additionalMethods.filter { it.shouldBeGeneratedForInnerTestClass() },
) )
) )
} }
@@ -100,6 +102,7 @@ class SimpleTestClassModel(
val result = mutableListOf<MethodModel>() val result = mutableListOf<MethodModel>()
result.add(RunTestMethodModel(targetBackend, doTestMethodName, testRunnerMethodName, additionalRunnerArguments)) result.add(RunTestMethodModel(targetBackend, doTestMethodName, testRunnerMethodName, additionalRunnerArguments))
result.add(TestAllFilesPresentMethodModel()) result.add(TestAllFilesPresentMethodModel())
result.addAll(additionalMethods)
val listFiles = rootFile.listFiles() val listFiles = rootFile.listFiles()
if (listFiles != null && (deep == null || deep == 0)) { if (listFiles != null && (deep == null || deep == 0)) {
for (file in listFiles) { for (file in listFiles) {
@@ -23,7 +23,8 @@ class SingleClassTestModel(
private val testRunnerMethodName: String, private val testRunnerMethodName: String,
private val additionalRunnerArguments: List<String>, private val additionalRunnerArguments: List<String>,
override val annotations: List<AnnotationModel>, override val annotations: List<AnnotationModel>,
override val tags: List<String> override val tags: List<String>,
private val additionalMethods: Collection<MethodModel>,
) : TestClassModel() { ) : TestClassModel() {
override val name: String override val name: String
get() = testClassName get() = testClassName
@@ -32,6 +33,7 @@ class SingleClassTestModel(
val result: MutableList<MethodModel> = ArrayList() val result: MutableList<MethodModel> = ArrayList()
result.add(RunTestMethodModel(targetBackend, doTestMethodName, testRunnerMethodName, additionalRunnerArguments)) result.add(RunTestMethodModel(targetBackend, doTestMethodName, testRunnerMethodName, additionalRunnerArguments))
result.add(TestAllFilesPresentMethodModel()) result.add(TestAllFilesPresentMethodModel())
result.addAll(additionalMethods)
FileUtil.processFilesRecursively(rootFile) { file: File -> FileUtil.processFilesRecursively(rootFile) { file: File ->
if (!file.isDirectory && filenamePattern.matcher(file.name).matches()) { if (!file.isDirectory && filenamePattern.matcher(file.name).matches()) {
result.addAll(getTestMethodsFromFile(file)) result.addAll(getTestMethodsFromFile(file))
@@ -35,6 +35,8 @@ interface MethodModel : TestEntityModel {
abstract class Kind abstract class Kind
val kind: Kind val kind: Kind
fun isTestMethod(): Boolean = true
fun shouldBeGeneratedForInnerTestClass(): Boolean = true
fun shouldBeGenerated(): Boolean = true fun shouldBeGenerated(): Boolean = true
fun imports(): Collection<Class<*>> = emptyList() fun imports(): Collection<Class<*>> = emptyList()
} }