[JS FIR] Enable FirJsLineNumberTests for FIR

^KT-64426 Fixed
This commit is contained in:
Alexander Korepanov
2023-12-20 16:19:58 +01:00
committed by Space Team
parent ac30911497
commit 6df0e0c847
58 changed files with 460 additions and 146 deletions
@@ -165,10 +165,9 @@ fun main(args: Array<String>) {
// model("typescript-export/", pattern = "^([^_](.+))\\.kt$")
// }
// see todo on defining class
// testClass<AbstractJsFirLineNumberTest> {
// model("lineNumbers/")
// }
testClass<AbstractFirJsLineNumberTest> {
model("lineNumbers/")
}
}
testGroup("js/js.tests/tests-gen", "compiler/testData", testRunnerMethodName = "runTest0") {
@@ -7,6 +7,7 @@ import org.jetbrains.kotlin.js.test.converters.JsIrBackendFacade
import org.jetbrains.kotlin.js.test.converters.incremental.RecompileModuleJsIrBackendFacade
import org.jetbrains.kotlin.js.test.handlers.JsDebugRunner
import org.jetbrains.kotlin.js.test.handlers.JsIrRecompiledArtifactsIdentityHandler
import org.jetbrains.kotlin.js.test.handlers.createFirJsLineNumberHandler
import org.jetbrains.kotlin.parsing.parseBoolean
import org.jetbrains.kotlin.test.Constructor
import org.jetbrains.kotlin.test.FirParser
@@ -134,16 +135,25 @@ open class AbstractFirJsCodegenInlineTest : AbstractFirJsTest(
// }
//}
// TODO: implement separate expectations for FIR/JS to reuse testdata, disabled for now
//open class AbstractJsFirLineNumberTest : AbstractFirJsTest(
// pathToTestDir = "${JsEnvironmentConfigurator.TEST_DATA_DIR_PATH}/lineNumbers/",
// testGroupOutputDirPrefix = "firLineNumbers/"
//) {
// override fun configure(builder: TestConfigurationBuilder) {
// super.configure(builder)
// configureJsIrLineNumberTest(builder)
// }
//}
open class AbstractFirJsLineNumberTest : AbstractFirJsTest(
pathToTestDir = "${JsEnvironmentConfigurator.TEST_DATA_DIR_PATH}/lineNumbers/",
testGroupOutputDirPrefix = "firLineNumbers/"
) {
override fun configure(builder: TestConfigurationBuilder) {
super.configure(builder)
with(builder) {
defaultDirectives {
+JsEnvironmentConfigurationDirectives.KJS_WITH_FULL_RUNTIME
+JsEnvironmentConfigurationDirectives.NO_COMMON_FILES
-JsEnvironmentConfigurationDirectives.GENERATE_NODE_JS_RUNNER
JsEnvironmentConfigurationDirectives.DONT_RUN_GENERATED_CODE.with(listOf("JS", "JS_IR", "JS_IR_ES6"))
}
configureJsArtifactsHandlersStep {
useHandlers(::createFirJsLineNumberHandler)
}
}
}
}
open class AbstractFirJsSteppingTest : AbstractFirJsTest(
pathToTestDir = "compiler/testData/debug/stepping/",
@@ -9,39 +9,36 @@ import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.CompilationOutputs
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.TranslationMode
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.safeModuleName
import org.jetbrains.kotlin.js.backend.ast.JsProgram
import org.jetbrains.kotlin.js.facade.TranslationResult
import org.jetbrains.kotlin.js.test.utils.LineCollector
import org.jetbrains.kotlin.js.test.utils.LineOutputToStringVisitor
import org.jetbrains.kotlin.js.util.TextOutputImpl
import org.jetbrains.kotlin.test.backend.handlers.JsBinaryArtifactHandler
import org.jetbrains.kotlin.test.model.BinaryArtifacts
import org.jetbrains.kotlin.test.model.FrontendKind
import org.jetbrains.kotlin.test.model.FrontendKinds
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.configuration.JsEnvironmentConfigurator
import org.jetbrains.kotlin.test.services.moduleStructure
import org.jetbrains.kotlin.utils.addToStdlib.cast
import java.io.File
/**
* Verifies the `// LINE` comments in lineNumber tests.
*
* The test file is expected to contain the `// LINE(backend)` directive, followed by the line numbers that the corresponding JS statements
* are generated from.
* The test file is expected to contain the `// LINE($linePattern)` directive,
* followed by the line numbers that the corresponding JS statements are generated from.
*
* This handler traverses the JS AST and collects the actual line numbers using [LineCollector], and generates a JavaScript file
* with those line numbers printed as comments for ease of debugging these tests.
*/
class JsLineNumberHandler(testServices: TestServices) : JsBinaryArtifactHandler(testServices) {
private class JsLineNumberHandler(private val frontend: FrontendKind<*>, testServices: TestServices) : JsBinaryArtifactHandler(testServices) {
private val translationModeForIr = TranslationMode.PER_MODULE_DEV
override fun processAfterAllModules(someAssertionWasFailed: Boolean) {}
override fun processModule(module: TestModule, info: BinaryArtifacts.Js) {
when (val artifact = info.unwrap()) {
is BinaryArtifacts.Js.OldJsArtifact ->
verifyModule(module, TranslationMode.FULL_DEV, artifact.translationResult.cast<TranslationResult.Success>().program, "JS")
is BinaryArtifacts.Js.JsIrArtifact -> {
val testModules = testServices.moduleStructure.modules
val moduleId2TestModule = testModules.associateBy { it.name.safeModuleName }
@@ -58,7 +55,7 @@ class JsLineNumberHandler(testServices: TestServices) : JsBinaryArtifactHandler(
}
}
verifyModule(module, translationModeForIr, compilationOutputs.jsProgram!!, "JS_IR")
verifyModule(module, translationModeForIr, compilationOutputs.jsProgram!!)
verifiedModuleCount += 1
}
@@ -77,8 +74,7 @@ class JsLineNumberHandler(testServices: TestServices) : JsBinaryArtifactHandler(
private fun verifyModule(
module: TestModule,
translationMode: TranslationMode,
jsProgram: JsProgram,
backendPattern: String
jsProgram: JsProgram
) {
val baseOutputPath = JsEnvironmentConfigurator.getJsModuleArtifactPath(testServices, module.name, translationMode)
@@ -96,12 +92,12 @@ class JsLineNumberHandler(testServices: TestServices) : JsBinaryArtifactHandler(
writeText(generatedCode)
}
val linesPattern = Regex("^ *// *LINES\\($backendPattern\\): *(.*)$", RegexOption.MULTILINE)
val linesPattern = Regex("^ *// *LINES\\((?:$frontend )? *JS_IR\\): *(.*)$", RegexOption.MULTILINE)
val linesMatcher = module.files
.firstNotNullOfOrNull { linesPattern.find(it.originalContent) }
?: testServices.assertions.fail {
"'// LINES($backendPattern): ' comment was not found in source file. Generated code is:\n$generatedCode"
"'// LINES(${linesPattern.pattern}): ' comment was not found in source file. Generated code is:\n$generatedCode"
}
fun List<Int?>.render() = joinToString(" ") { it?.toString() ?: "*" }
@@ -117,3 +113,11 @@ class JsLineNumberHandler(testServices: TestServices) : JsBinaryArtifactHandler(
testServices.assertions.assertEquals(expectedLines, actualLines) { generatedCode }
}
}
fun createIrJsLineNumberHandler(testServices: TestServices): JsBinaryArtifactHandler {
return JsLineNumberHandler(FrontendKinds.ClassicFrontend, testServices)
}
fun createFirJsLineNumberHandler(testServices: TestServices): JsBinaryArtifactHandler {
return JsLineNumberHandler(FrontendKinds.FIR, testServices)
}
@@ -138,7 +138,17 @@ open class AbstractJsIrLineNumberTest : AbstractJsIrTest(
) {
override fun configure(builder: TestConfigurationBuilder) {
super.configure(builder)
configureJsIrLineNumberTest(builder)
with(builder) {
defaultDirectives {
+JsEnvironmentConfigurationDirectives.KJS_WITH_FULL_RUNTIME
+JsEnvironmentConfigurationDirectives.NO_COMMON_FILES
-JsEnvironmentConfigurationDirectives.GENERATE_NODE_JS_RUNNER
JsEnvironmentConfigurationDirectives.DONT_RUN_GENERATED_CODE.with(listOf("JS", "JS_IR", "JS_IR_ES6"))
}
configureJsArtifactsHandlersStep {
useHandlers(::createIrJsLineNumberHandler)
}
}
}
}
@@ -193,20 +203,6 @@ open class AbstractWebDemoExamplesTest : AbstractJsIrTest(
}
}
private fun configureJsIrLineNumberTest(builder: TestConfigurationBuilder) {
with(builder) {
defaultDirectives {
+JsEnvironmentConfigurationDirectives.KJS_WITH_FULL_RUNTIME
+JsEnvironmentConfigurationDirectives.NO_COMMON_FILES
-JsEnvironmentConfigurationDirectives.GENERATE_NODE_JS_RUNNER
JsEnvironmentConfigurationDirectives.DONT_RUN_GENERATED_CODE.with(listOf("JS", "JS_IR", "JS_IR_ES6"))
}
configureJsArtifactsHandlersStep {
useHandlers(::JsLineNumberHandler)
}
}
}
open class AbstractIrJsSteppingTest : AbstractJsIrTest(
pathToTestDir = "compiler/testData/debug/stepping/",
testGroupOutputDirPrefix = "debug/irStepping/"
@@ -0,0 +1,343 @@
/*
* Copyright 2010-2024 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.js.test.fir;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.util.KtTestUtil;
import org.jetbrains.kotlin.test.TargetBackend;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.GenerateJsTestsKt}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("js/js.translator/testData/lineNumbers")
@TestDataPath("$PROJECT_ROOT")
public class FirJsLineNumberTestGenerated extends AbstractFirJsLineNumberTest {
@Test
public void testAllFilesPresentInLineNumbers() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/lineNumbers"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
}
@Test
@TestMetadata("andAndWithSideEffect.kt")
public void testAndAndWithSideEffect() throws Exception {
runTest("js/js.translator/testData/lineNumbers/andAndWithSideEffect.kt");
}
@Test
@TestMetadata("backingField.kt")
public void testBackingField() throws Exception {
runTest("js/js.translator/testData/lineNumbers/backingField.kt");
}
@Test
@TestMetadata("catch.kt")
public void testCatch() throws Exception {
runTest("js/js.translator/testData/lineNumbers/catch.kt");
}
@Test
@TestMetadata("chainedCall.kt")
public void testChainedCall() throws Exception {
runTest("js/js.translator/testData/lineNumbers/chainedCall.kt");
}
@Test
@TestMetadata("classCapturingLocals.kt")
public void testClassCapturingLocals() throws Exception {
runTest("js/js.translator/testData/lineNumbers/classCapturingLocals.kt");
}
@Test
@TestMetadata("closure.kt")
public void testClosure() throws Exception {
runTest("js/js.translator/testData/lineNumbers/closure.kt");
}
@Test
@TestMetadata("complexExpressionAsDefaultArgument.kt")
public void testComplexExpressionAsDefaultArgument() throws Exception {
runTest("js/js.translator/testData/lineNumbers/complexExpressionAsDefaultArgument.kt");
}
@Test
@TestMetadata("conditionalDecomposed.kt")
public void testConditionalDecomposed() throws Exception {
runTest("js/js.translator/testData/lineNumbers/conditionalDecomposed.kt");
}
@Test
@TestMetadata("coroutine.kt")
public void testCoroutine() throws Exception {
runTest("js/js.translator/testData/lineNumbers/coroutine.kt");
}
@Test
@TestMetadata("coroutineNullAssertion.kt")
public void testCoroutineNullAssertion() throws Exception {
runTest("js/js.translator/testData/lineNumbers/coroutineNullAssertion.kt");
}
@Test
@TestMetadata("dataClass.kt")
public void testDataClass() throws Exception {
runTest("js/js.translator/testData/lineNumbers/dataClass.kt");
}
@Test
@TestMetadata("delegateMemberVal.kt")
public void testDelegateMemberVal() throws Exception {
runTest("js/js.translator/testData/lineNumbers/delegateMemberVal.kt");
}
@Test
@TestMetadata("delegatedProperty.kt")
public void testDelegatedProperty() throws Exception {
runTest("js/js.translator/testData/lineNumbers/delegatedProperty.kt");
}
@Test
@TestMetadata("delegation.kt")
public void testDelegation() throws Exception {
runTest("js/js.translator/testData/lineNumbers/delegation.kt");
}
@Test
@TestMetadata("destructuring.kt")
public void testDestructuring() throws Exception {
runTest("js/js.translator/testData/lineNumbers/destructuring.kt");
}
@Test
@TestMetadata("destructuringInline.kt")
public void testDestructuringInline() throws Exception {
runTest("js/js.translator/testData/lineNumbers/destructuringInline.kt");
}
@Test
@TestMetadata("doWhileWithComplexCondition.kt")
public void testDoWhileWithComplexCondition() throws Exception {
runTest("js/js.translator/testData/lineNumbers/doWhileWithComplexCondition.kt");
}
@Test
@TestMetadata("elvis.kt")
public void testElvis() throws Exception {
runTest("js/js.translator/testData/lineNumbers/elvis.kt");
}
@Test
@TestMetadata("enumCompanionObject.kt")
public void testEnumCompanionObject() throws Exception {
runTest("js/js.translator/testData/lineNumbers/enumCompanionObject.kt");
}
@Test
@TestMetadata("enumObject.kt")
public void testEnumObject() throws Exception {
runTest("js/js.translator/testData/lineNumbers/enumObject.kt");
}
@Test
@TestMetadata("expressionAsFunctionBody.kt")
public void testExpressionAsFunctionBody() throws Exception {
runTest("js/js.translator/testData/lineNumbers/expressionAsFunctionBody.kt");
}
@Test
@TestMetadata("for.kt")
public void testFor() throws Exception {
runTest("js/js.translator/testData/lineNumbers/for.kt");
}
@Test
@TestMetadata("increment.kt")
public void testIncrement() throws Exception {
runTest("js/js.translator/testData/lineNumbers/increment.kt");
}
@Test
@TestMetadata("inlineArguments.kt")
public void testInlineArguments() throws Exception {
runTest("js/js.translator/testData/lineNumbers/inlineArguments.kt");
}
@Test
@TestMetadata("inlineLocalVarsRef.kt")
public void testInlineLocalVarsRef() throws Exception {
runTest("js/js.translator/testData/lineNumbers/inlineLocalVarsRef.kt");
}
@Test
@TestMetadata("inlineReturn.kt")
public void testInlineReturn() throws Exception {
runTest("js/js.translator/testData/lineNumbers/inlineReturn.kt");
}
@Test
@TestMetadata("inlining.kt")
public void testInlining() throws Exception {
runTest("js/js.translator/testData/lineNumbers/inlining.kt");
}
@Test
@TestMetadata("inliningWithLambda.kt")
public void testInliningWithLambda() throws Exception {
runTest("js/js.translator/testData/lineNumbers/inliningWithLambda.kt");
}
@Test
@TestMetadata("innerClass.kt")
public void testInnerClass() throws Exception {
runTest("js/js.translator/testData/lineNumbers/innerClass.kt");
}
@Test
@TestMetadata("isOperator.kt")
public void testIsOperator() throws Exception {
runTest("js/js.translator/testData/lineNumbers/isOperator.kt");
}
@Test
@TestMetadata("jsCode.kt")
public void testJsCode() throws Exception {
runTest("js/js.translator/testData/lineNumbers/jsCode.kt");
}
@Test
@TestMetadata("lambdaWithClosure.kt")
public void testLambdaWithClosure() throws Exception {
runTest("js/js.translator/testData/lineNumbers/lambdaWithClosure.kt");
}
@Test
@TestMetadata("lastExpressionInInlineLambda.kt")
public void testLastExpressionInInlineLambda() throws Exception {
runTest("js/js.translator/testData/lineNumbers/lastExpressionInInlineLambda.kt");
}
@Test
@TestMetadata("literals.kt")
public void testLiterals() throws Exception {
runTest("js/js.translator/testData/lineNumbers/literals.kt");
}
@Test
@TestMetadata("longLiteral.kt")
public void testLongLiteral() throws Exception {
runTest("js/js.translator/testData/lineNumbers/longLiteral.kt");
}
@Test
@TestMetadata("memberFunWithDefaultParam.kt")
public void testMemberFunWithDefaultParam() throws Exception {
runTest("js/js.translator/testData/lineNumbers/memberFunWithDefaultParam.kt");
}
@Test
@TestMetadata("multipleReferences.kt")
public void testMultipleReferences() throws Exception {
runTest("js/js.translator/testData/lineNumbers/multipleReferences.kt");
}
@Test
@TestMetadata("objectInstanceFunction.kt")
public void testObjectInstanceFunction() throws Exception {
runTest("js/js.translator/testData/lineNumbers/objectInstanceFunction.kt");
}
@Test
@TestMetadata("optionalArgs.kt")
public void testOptionalArgs() throws Exception {
runTest("js/js.translator/testData/lineNumbers/optionalArgs.kt");
}
@Test
@TestMetadata("propertyWithoutInitializer.kt")
public void testPropertyWithoutInitializer() throws Exception {
runTest("js/js.translator/testData/lineNumbers/propertyWithoutInitializer.kt");
}
@Test
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
runTest("js/js.translator/testData/lineNumbers/simple.kt");
}
@Test
@TestMetadata("stringLiteral.kt")
public void testStringLiteral() throws Exception {
runTest("js/js.translator/testData/lineNumbers/stringLiteral.kt");
}
@Test
@TestMetadata("syntheticCodeInConstructors.kt")
public void testSyntheticCodeInConstructors() throws Exception {
runTest("js/js.translator/testData/lineNumbers/syntheticCodeInConstructors.kt");
}
@Test
@TestMetadata("syntheticCodeInEnums.kt")
public void testSyntheticCodeInEnums() throws Exception {
runTest("js/js.translator/testData/lineNumbers/syntheticCodeInEnums.kt");
}
@Test
@TestMetadata("valParameter.kt")
public void testValParameter() throws Exception {
runTest("js/js.translator/testData/lineNumbers/valParameter.kt");
}
@Test
@TestMetadata("whenEntryWithMultipleConditions.kt")
public void testWhenEntryWithMultipleConditions() throws Exception {
runTest("js/js.translator/testData/lineNumbers/whenEntryWithMultipleConditions.kt");
}
@Test
@TestMetadata("whenEntryWithMultipleConditionsNonOptimized.kt")
public void testWhenEntryWithMultipleConditionsNonOptimized() throws Exception {
runTest("js/js.translator/testData/lineNumbers/whenEntryWithMultipleConditionsNonOptimized.kt");
}
@Test
@TestMetadata("whenIn.kt")
public void testWhenIn() throws Exception {
runTest("js/js.translator/testData/lineNumbers/whenIn.kt");
}
@Test
@TestMetadata("whenIs.kt")
public void testWhenIs() throws Exception {
runTest("js/js.translator/testData/lineNumbers/whenIs.kt");
}
@Test
@TestMetadata("whileWithComplexCondition.kt")
public void testWhileWithComplexCondition() throws Exception {
runTest("js/js.translator/testData/lineNumbers/whileWithComplexCondition.kt");
}
@Nested
@TestMetadata("js/js.translator/testData/lineNumbers/inlineMultiModule")
@TestDataPath("$PROJECT_ROOT")
public class InlineMultiModule {
@Test
public void testAllFilesPresentInInlineMultiModule() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/lineNumbers/inlineMultiModule"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
}
@Test
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
runTest("js/js.translator/testData/lineNumbers/inlineMultiModule/simple.kt");
}
}
}
@@ -205,6 +205,12 @@ public class JsIrLineNumberTestGenerated extends AbstractJsIrLineNumberTest {
runTest("js/js.translator/testData/lineNumbers/isOperator.kt");
}
@Test
@TestMetadata("jsCode.kt")
public void testJsCode() throws Exception {
runTest("js/js.translator/testData/lineNumbers/jsCode.kt");
}
@Test
@TestMetadata("lambdaWithClosure.kt")
public void testLambdaWithClosure() throws Exception {