From cf5a1615eabd5877df8a17c2ebe9719380abe32a Mon Sep 17 00:00:00 2001 From: "Vitaliy.Tikhonov" Date: Fri, 30 Aug 2019 14:41:54 +0300 Subject: [PATCH] [IR] add JsTextTest for IrScript --- .../ir/util/DeepCopyIrTreeWithSymbols.kt | 14 ++ .../ir/irJsText/scripting/arrayAssignment.kts | 10 + .../ir/irJsText/scripting/arrayAssignment.txt | 33 ++++ .../testData/ir/irJsText/scripting/fun.kts | 13 ++ .../testData/ir/irJsText/scripting/fun.txt | 60 ++++++ .../ir/irJsText/scripting/safeCalls.kts | 21 ++ .../ir/irJsText/scripting/safeCalls.txt | 183 ++++++++++++++++++ compiler/tests-common/build.gradle.kts | 1 + .../kotlin/codegen/CodegenTestCase.java | 7 +- .../kotlin/ir/AbstractIrTextTestCase.kt | 16 +- .../kotlin/ir/IrJsTextTestCaseGenerated.java | 28 +++ 11 files changed, 383 insertions(+), 3 deletions(-) create mode 100644 compiler/testData/ir/irJsText/scripting/arrayAssignment.kts create mode 100644 compiler/testData/ir/irJsText/scripting/arrayAssignment.txt create mode 100644 compiler/testData/ir/irJsText/scripting/fun.kts create mode 100644 compiler/testData/ir/irJsText/scripting/fun.txt create mode 100644 compiler/testData/ir/irJsText/scripting/safeCalls.kts create mode 100644 compiler/testData/ir/irJsText/scripting/safeCalls.txt diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTreeWithSymbols.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTreeWithSymbols.kt index b05320a9e36..05d2c09dca7 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTreeWithSymbols.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTreeWithSymbols.kt @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.ir.util +import org.jetbrains.kotlin.descriptors.ScriptDescriptor import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.declarations.* @@ -24,6 +25,7 @@ import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.symbols.impl.IrAnonymousInitializerSymbolImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrScriptSymbolImpl import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.acceptVoid @@ -117,6 +119,18 @@ open class DeepCopyIrTreeWithSymbols( override fun visitDeclaration(declaration: IrDeclaration): IrStatement = throw IllegalArgumentException("Unsupported declaration type: $declaration") + override fun visitScript(declaration: IrScript): IrStatement { + return IrScriptImpl( + //TODO: something may go wrong, because expected using symbolRemapper + IrScriptSymbolImpl(declaration.descriptor as ScriptDescriptor), + declaration.name + ).also { + it.thisReceiver = declaration.thisReceiver.transform() + declaration.transformDeclarationsTo(it) + it.statements.addAll(declaration.statements.map { it.transform() }) + } + } + override fun visitClass(declaration: IrClass): IrClass = IrClassImpl( declaration.startOffset, declaration.endOffset, diff --git a/compiler/testData/ir/irJsText/scripting/arrayAssignment.kts b/compiler/testData/ir/irJsText/scripting/arrayAssignment.kts new file mode 100644 index 00000000000..26fec9c8b2b --- /dev/null +++ b/compiler/testData/ir/irJsText/scripting/arrayAssignment.kts @@ -0,0 +1,10 @@ +fun test() { + val x = intArrayOf(1, 2, 3) + x[1] = 0 +} + +fun foo() = 1 + +fun test2() { + intArrayOf(1, 2, 3)[foo()] = 1 +} \ No newline at end of file diff --git a/compiler/testData/ir/irJsText/scripting/arrayAssignment.txt b/compiler/testData/ir/irJsText/scripting/arrayAssignment.txt new file mode 100644 index 00000000000..4c96e0310da --- /dev/null +++ b/compiler/testData/ir/irJsText/scripting/arrayAssignment.txt @@ -0,0 +1,33 @@ +FILE fqName: fileName:/arrayAssignment.kts + SCRIPT + FUN name:test visibility:public modality:FINAL <> ($this:.ArrayAssignment) returnType:kotlin.Unit + $this: VALUE_PARAMETER name: type:.ArrayAssignment + BLOCK_BODY + VAR name:x type:kotlin.IntArray [val] + CALL 'public final fun intArrayOf (vararg elements: kotlin.Int): kotlin.IntArray declared in kotlin' type=kotlin.IntArray origin=null + elements: VARARG type=kotlin.IntArray varargElementType=kotlin.Int + CONST Int type=kotlin.Int value=1 + CONST Int type=kotlin.Int value=2 + CONST Int type=kotlin.Int value=3 + CALL 'public final fun set (index: kotlin.Int, value: kotlin.Int): kotlin.Unit declared in kotlin.IntArray' type=kotlin.Unit origin=EQ + $this: GET_VAR 'val x: kotlin.IntArray [val] declared in .ArrayAssignment.test' type=kotlin.IntArray origin=null + index: CONST Int type=kotlin.Int value=1 + value: CONST Int type=kotlin.Int value=0 + FUN name:foo visibility:public modality:FINAL <> ($this:.ArrayAssignment) returnType:kotlin.Int + $this: VALUE_PARAMETER name: type:.ArrayAssignment + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun foo (): kotlin.Int declared in .ArrayAssignment' + CONST Int type=kotlin.Int value=1 + FUN name:test2 visibility:public modality:FINAL <> ($this:.ArrayAssignment) returnType:kotlin.Unit + $this: VALUE_PARAMETER name: type:.ArrayAssignment + BLOCK_BODY + CALL 'public final fun set (index: kotlin.Int, value: kotlin.Int): kotlin.Unit declared in kotlin.IntArray' type=kotlin.Unit origin=EQ + $this: CALL 'public final fun intArrayOf (vararg elements: kotlin.Int): kotlin.IntArray declared in kotlin' type=kotlin.IntArray origin=null + elements: VARARG type=kotlin.IntArray varargElementType=kotlin.Int + CONST Int type=kotlin.Int value=1 + CONST Int type=kotlin.Int value=2 + CONST Int type=kotlin.Int value=3 + index: CALL 'public final fun foo (): kotlin.Int declared in .ArrayAssignment' type=kotlin.Int origin=null + $this: GET_VAR ': .ArrayAssignment declared in .ArrayAssignment.test2' type=.ArrayAssignment origin=null + value: CONST Int type=kotlin.Int value=1 + VALUE_PARAMETER INSTANCE_RECEIVER name: type:.ArrayAssignment diff --git a/compiler/testData/ir/irJsText/scripting/fun.kts b/compiler/testData/ir/irJsText/scripting/fun.kts new file mode 100644 index 00000000000..db33117f471 --- /dev/null +++ b/compiler/testData/ir/irJsText/scripting/fun.kts @@ -0,0 +1,13 @@ +fun test1(i: Int, j: T) {} + +fun test2(i: Int = 0, j: String = "") {} + +fun test3(vararg args: String) {} + +fun String.textExt1(i: Int, j: String) {} + +class Host { + fun String.testMembetExt1(i: Int, j: String) {} + + fun String.testMembetExt2(i: Int, j: T) {} +} \ No newline at end of file diff --git a/compiler/testData/ir/irJsText/scripting/fun.txt b/compiler/testData/ir/irJsText/scripting/fun.txt new file mode 100644 index 00000000000..a175f4009ab --- /dev/null +++ b/compiler/testData/ir/irJsText/scripting/fun.txt @@ -0,0 +1,60 @@ +FILE fqName: fileName:/fun.kts + SCRIPT + FUN name:test1 visibility:public modality:FINAL ($this:.Fun, i:kotlin.Int, j:T of .Fun.test1) returnType:kotlin.Unit + TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?] + $this: VALUE_PARAMETER name: type:.Fun + VALUE_PARAMETER name:i index:0 type:kotlin.Int + VALUE_PARAMETER name:j index:1 type:T of .Fun.test1 + BLOCK_BODY + FUN name:test2 visibility:public modality:FINAL <> ($this:.Fun, i:kotlin.Int, j:kotlin.String) returnType:kotlin.Unit + $this: VALUE_PARAMETER name: type:.Fun + VALUE_PARAMETER name:i index:0 type:kotlin.Int + EXPRESSION_BODY + CONST Int type=kotlin.Int value=0 + VALUE_PARAMETER name:j index:1 type:kotlin.String + EXPRESSION_BODY + CONST String type=kotlin.String value="" + BLOCK_BODY + FUN name:test3 visibility:public modality:FINAL <> ($this:.Fun, args:kotlin.Array) returnType:kotlin.Unit + $this: VALUE_PARAMETER name: type:.Fun + VALUE_PARAMETER name:args index:0 type:kotlin.Array varargElementType:kotlin.String [vararg] + BLOCK_BODY + FUN name:textExt1 visibility:public modality:FINAL <> ($this:.Fun, $receiver:kotlin.String, i:kotlin.Int, j:kotlin.String) returnType:kotlin.Unit + $this: VALUE_PARAMETER name: type:.Fun + $receiver: VALUE_PARAMETER name: type:kotlin.String + VALUE_PARAMETER name:i index:0 type:kotlin.Int + VALUE_PARAMETER name:j index:1 type:kotlin.String + BLOCK_BODY + CLASS CLASS name:Host modality:FINAL visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.Fun.Host + CONSTRUCTOR visibility:public <> () returnType:.Fun.Host [primary] + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Host modality:FINAL visibility:public superTypes:[kotlin.Any]' + FUN name:testMembetExt1 visibility:public modality:FINAL <> ($this:.Fun.Host, $receiver:kotlin.String, i:kotlin.Int, j:kotlin.String) returnType:kotlin.Unit + $this: VALUE_PARAMETER name: type:.Fun.Host + $receiver: VALUE_PARAMETER name: type:kotlin.String + VALUE_PARAMETER name:i index:0 type:kotlin.Int + VALUE_PARAMETER name:j index:1 type:kotlin.String + BLOCK_BODY + FUN name:testMembetExt2 visibility:public modality:FINAL ($this:.Fun.Host, $receiver:kotlin.String, i:kotlin.Int, j:T of .Fun.Host.testMembetExt2) returnType:kotlin.Unit + TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?] + $this: VALUE_PARAMETER name: type:.Fun.Host + $receiver: VALUE_PARAMETER name: type:kotlin.String + VALUE_PARAMETER name:i index:0 type:kotlin.Int + VALUE_PARAMETER name:j index:1 type:T of .Fun.Host.testMembetExt2 + BLOCK_BODY + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int + overridden: + public open fun hashCode (): kotlin.Int declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String + overridden: + public open fun toString (): kotlin.String declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + VALUE_PARAMETER INSTANCE_RECEIVER name: type:.Fun diff --git a/compiler/testData/ir/irJsText/scripting/safeCalls.kts b/compiler/testData/ir/irJsText/scripting/safeCalls.kts new file mode 100644 index 00000000000..82943638a94 --- /dev/null +++ b/compiler/testData/ir/irJsText/scripting/safeCalls.kts @@ -0,0 +1,21 @@ +class Ref(var value: Int) + +interface IHost { + fun String.extLength() = length +} + +fun test1(x: String?) = x?.length +fun test2(x: String?) = x?.hashCode() +fun test3(x: String?, y: Any?) = x?.equals(y) + +fun test4(x: Ref?) { + x?.value = 0 +} + +fun IHost.test5(s: String?) = s?.extLength() + +fun Int.foo() = 239 + +fun box() { + 42?.foo() +} diff --git a/compiler/testData/ir/irJsText/scripting/safeCalls.txt b/compiler/testData/ir/irJsText/scripting/safeCalls.txt new file mode 100644 index 00000000000..ead464eacd4 --- /dev/null +++ b/compiler/testData/ir/irJsText/scripting/safeCalls.txt @@ -0,0 +1,183 @@ +FILE fqName: fileName:/safeCalls.kts + SCRIPT + CLASS CLASS name:Ref modality:FINAL visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.SafeCalls.Ref + CONSTRUCTOR visibility:public <> (value:kotlin.Int) returnType:.SafeCalls.Ref [primary] + VALUE_PARAMETER name:value index:0 type:kotlin.Int + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Ref modality:FINAL visibility:public superTypes:[kotlin.Any]' + PROPERTY name:value visibility:public modality:FINAL [var] + FIELD PROPERTY_BACKING_FIELD name:value type:kotlin.Int visibility:private + EXPRESSION_BODY + GET_VAR 'value: kotlin.Int declared in .SafeCalls.Ref.' type=kotlin.Int origin=INITIALIZE_PROPERTY_FROM_PARAMETER + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:.SafeCalls.Ref) returnType:kotlin.Int + correspondingProperty: PROPERTY name:value visibility:public modality:FINAL [var] + $this: VALUE_PARAMETER name: type:.SafeCalls.Ref + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun (): kotlin.Int declared in .SafeCalls.Ref' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:value type:kotlin.Int visibility:private' type=kotlin.Int origin=null + receiver: GET_VAR ': .SafeCalls.Ref declared in .SafeCalls.Ref.' type=.SafeCalls.Ref origin=null + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:.SafeCalls.Ref, :kotlin.Int) returnType:kotlin.Unit + correspondingProperty: PROPERTY name:value visibility:public modality:FINAL [var] + $this: VALUE_PARAMETER name: type:.SafeCalls.Ref + VALUE_PARAMETER name: index:0 type:kotlin.Int + BLOCK_BODY + SET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:value type:kotlin.Int visibility:private' type=kotlin.Unit origin=null + receiver: GET_VAR ': .SafeCalls.Ref declared in .SafeCalls.Ref.' type=.SafeCalls.Ref origin=null + value: GET_VAR ': kotlin.Int declared in .SafeCalls.Ref.' type=kotlin.Int origin=null + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int + overridden: + public open fun hashCode (): kotlin.Int declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String + overridden: + public open fun toString (): kotlin.String declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + CLASS INTERFACE name:IHost modality:ABSTRACT visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.SafeCalls.IHost + FUN name:extLength visibility:public modality:OPEN <> ($this:.SafeCalls.IHost, $receiver:kotlin.String) returnType:kotlin.Int + $this: VALUE_PARAMETER name: type:.SafeCalls.IHost + $receiver: VALUE_PARAMETER name: type:kotlin.String + BLOCK_BODY + RETURN type=kotlin.Nothing from='public open fun extLength (): kotlin.Int declared in .SafeCalls.IHost' + CALL 'public open fun (): kotlin.Int declared in kotlin.String' type=kotlin.Int origin=GET_PROPERTY + $this: GET_VAR ': kotlin.String declared in .SafeCalls.IHost.extLength' type=kotlin.String origin=null + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int + overridden: + public open fun hashCode (): kotlin.Int declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String + overridden: + public open fun toString (): kotlin.String declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN name:test1 visibility:public modality:FINAL <> ($this:.SafeCalls, x:kotlin.String?) returnType:kotlin.Int? + $this: VALUE_PARAMETER name: type:.SafeCalls + VALUE_PARAMETER name:x index:0 type:kotlin.String? + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun test1 (x: kotlin.String?): kotlin.Int? declared in .SafeCalls' + BLOCK type=kotlin.Int? origin=SAFE_CALL + VAR IR_TEMPORARY_VARIABLE name:tmp0_safe_receiver type:kotlin.String? [val] + GET_VAR 'x: kotlin.String? declared in .SafeCalls.test1' type=kotlin.String? origin=null + WHEN type=kotlin.Int? origin=null + BRANCH + if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ + arg0: GET_VAR 'val tmp0_safe_receiver: kotlin.String? [val] declared in .SafeCalls.test1' type=kotlin.String? origin=null + arg1: CONST Null type=kotlin.Nothing? value=null + then: CONST Null type=kotlin.Nothing? value=null + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CALL 'public open fun (): kotlin.Int declared in kotlin.String' type=kotlin.Int origin=GET_PROPERTY + $this: GET_VAR 'val tmp0_safe_receiver: kotlin.String? [val] declared in .SafeCalls.test1' type=kotlin.String? origin=null + FUN name:test2 visibility:public modality:FINAL <> ($this:.SafeCalls, x:kotlin.String?) returnType:kotlin.Int? + $this: VALUE_PARAMETER name: type:.SafeCalls + VALUE_PARAMETER name:x index:0 type:kotlin.String? + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun test2 (x: kotlin.String?): kotlin.Int? declared in .SafeCalls' + BLOCK type=kotlin.Int? origin=SAFE_CALL + VAR IR_TEMPORARY_VARIABLE name:tmp0_safe_receiver type:kotlin.String? [val] + GET_VAR 'x: kotlin.String? declared in .SafeCalls.test2' type=kotlin.String? origin=null + WHEN type=kotlin.Int? origin=null + BRANCH + if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ + arg0: GET_VAR 'val tmp0_safe_receiver: kotlin.String? [val] declared in .SafeCalls.test2' type=kotlin.String? origin=null + arg1: CONST Null type=kotlin.Nothing? value=null + then: CONST Null type=kotlin.Nothing? value=null + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CALL 'public open fun hashCode (): kotlin.Int declared in kotlin.String' type=kotlin.Int origin=null + $this: GET_VAR 'val tmp0_safe_receiver: kotlin.String? [val] declared in .SafeCalls.test2' type=kotlin.String? origin=null + FUN name:test3 visibility:public modality:FINAL <> ($this:.SafeCalls, x:kotlin.String?, y:kotlin.Any?) returnType:kotlin.Boolean? + $this: VALUE_PARAMETER name: type:.SafeCalls + VALUE_PARAMETER name:x index:0 type:kotlin.String? + VALUE_PARAMETER name:y index:1 type:kotlin.Any? + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun test3 (x: kotlin.String?, y: kotlin.Any?): kotlin.Boolean? declared in .SafeCalls' + BLOCK type=kotlin.Boolean? origin=SAFE_CALL + VAR IR_TEMPORARY_VARIABLE name:tmp0_safe_receiver type:kotlin.String? [val] + GET_VAR 'x: kotlin.String? declared in .SafeCalls.test3' type=kotlin.String? origin=null + WHEN type=kotlin.Boolean? origin=null + BRANCH + if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ + arg0: GET_VAR 'val tmp0_safe_receiver: kotlin.String? [val] declared in .SafeCalls.test3' type=kotlin.String? origin=null + arg1: CONST Null type=kotlin.Nothing? value=null + then: CONST Null type=kotlin.Nothing? value=null + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CALL 'public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in kotlin.String' type=kotlin.Boolean origin=null + $this: GET_VAR 'val tmp0_safe_receiver: kotlin.String? [val] declared in .SafeCalls.test3' type=kotlin.String? origin=null + other: GET_VAR 'y: kotlin.Any? declared in .SafeCalls.test3' type=kotlin.Any? origin=null + FUN name:test4 visibility:public modality:FINAL <> ($this:.SafeCalls, x:.SafeCalls.Ref?) returnType:kotlin.Unit + $this: VALUE_PARAMETER name: type:.SafeCalls + VALUE_PARAMETER name:x index:0 type:.SafeCalls.Ref? + BLOCK_BODY + BLOCK type=kotlin.Unit origin=SAFE_CALL + VAR IR_TEMPORARY_VARIABLE name:tmp0_safe_receiver type:.SafeCalls.Ref? [val] + GET_VAR 'x: .SafeCalls.Ref? declared in .SafeCalls.test4' type=.SafeCalls.Ref? origin=null + WHEN type=kotlin.Unit origin=null + BRANCH + if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ + arg0: GET_VAR 'val tmp0_safe_receiver: .SafeCalls.Ref? [val] declared in .SafeCalls.test4' type=.SafeCalls.Ref? origin=null + arg1: CONST Null type=kotlin.Nothing? value=null + then: TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + CONST Null type=kotlin.Nothing? value=null + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CALL 'public final fun (: kotlin.Int): kotlin.Unit declared in .SafeCalls.Ref' type=kotlin.Unit origin=EQ + $this: GET_VAR 'val tmp0_safe_receiver: .SafeCalls.Ref? [val] declared in .SafeCalls.test4' type=.SafeCalls.Ref? origin=null + : CONST Int type=kotlin.Int value=0 + FUN name:test5 visibility:public modality:FINAL <> ($this:.SafeCalls, $receiver:.SafeCalls.IHost, s:kotlin.String?) returnType:kotlin.Int? + $this: VALUE_PARAMETER name: type:.SafeCalls + $receiver: VALUE_PARAMETER name: type:.SafeCalls.IHost + VALUE_PARAMETER name:s index:0 type:kotlin.String? + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun test5 (s: kotlin.String?): kotlin.Int? declared in .SafeCalls' + BLOCK type=kotlin.Int? origin=SAFE_CALL + VAR IR_TEMPORARY_VARIABLE name:tmp0_safe_receiver type:kotlin.String? [val] + GET_VAR 's: kotlin.String? declared in .SafeCalls.test5' type=kotlin.String? origin=null + WHEN type=kotlin.Int? origin=null + BRANCH + if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ + arg0: GET_VAR 'val tmp0_safe_receiver: kotlin.String? [val] declared in .SafeCalls.test5' type=kotlin.String? origin=null + arg1: CONST Null type=kotlin.Nothing? value=null + then: CONST Null type=kotlin.Nothing? value=null + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CALL 'public open fun extLength (): kotlin.Int declared in .SafeCalls.IHost' type=kotlin.Int origin=null + $this: GET_VAR ': .SafeCalls.IHost declared in .SafeCalls.test5' type=.SafeCalls.IHost origin=null + $receiver: GET_VAR 'val tmp0_safe_receiver: kotlin.String? [val] declared in .SafeCalls.test5' type=kotlin.String? origin=null + FUN name:foo visibility:public modality:FINAL <> ($this:.SafeCalls, $receiver:kotlin.Int) returnType:kotlin.Int + $this: VALUE_PARAMETER name: type:.SafeCalls + $receiver: VALUE_PARAMETER name: type:kotlin.Int + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun foo (): kotlin.Int declared in .SafeCalls' + CONST Int type=kotlin.Int value=239 + FUN name:box visibility:public modality:FINAL <> ($this:.SafeCalls) returnType:kotlin.Unit + $this: VALUE_PARAMETER name: type:.SafeCalls + BLOCK_BODY + TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + BLOCK type=kotlin.Int? origin=SAFE_CALL + VAR IR_TEMPORARY_VARIABLE name:tmp0_safe_receiver type:kotlin.Int [val] + CONST Int type=kotlin.Int value=42 + WHEN type=kotlin.Int? origin=null + BRANCH + if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ + arg0: GET_VAR 'val tmp0_safe_receiver: kotlin.Int [val] declared in .SafeCalls.box' type=kotlin.Int origin=null + arg1: CONST Null type=kotlin.Nothing? value=null + then: CONST Null type=kotlin.Nothing? value=null + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CALL 'public final fun foo (): kotlin.Int declared in .SafeCalls' type=kotlin.Int origin=null + $this: GET_VAR ': .SafeCalls declared in .SafeCalls.box' type=.SafeCalls origin=null + $receiver: GET_VAR 'val tmp0_safe_receiver: kotlin.Int [val] declared in .SafeCalls.box' type=kotlin.Int origin=null + VALUE_PARAMETER INSTANCE_RECEIVER name: type:.SafeCalls diff --git a/compiler/tests-common/build.gradle.kts b/compiler/tests-common/build.gradle.kts index aefb4970f33..9cf5d2c27b9 100644 --- a/compiler/tests-common/build.gradle.kts +++ b/compiler/tests-common/build.gradle.kts @@ -5,6 +5,7 @@ plugins { } dependencies { + testCompile(project(":kotlin-scripting-compiler")) testCompile(project(":core:descriptors")) testCompile(project(":core:descriptors.jvm")) testCompile(project(":core:deserialization")) diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/codegen/CodegenTestCase.java b/compiler/tests-common/tests/org/jetbrains/kotlin/codegen/CodegenTestCase.java index 6960cbd9952..a1c1ae21273 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/codegen/CodegenTestCase.java +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/codegen/CodegenTestCase.java @@ -68,6 +68,7 @@ import java.util.regex.Pattern; import static org.jetbrains.kotlin.checkers.CompilerTestLanguageVersionSettingsKt.parseLanguageVersionSettings; import static org.jetbrains.kotlin.cli.common.output.OutputUtilsKt.writeAllTo; +import static org.jetbrains.kotlin.cli.js.K2JsIrCompilerKt.loadPluginsForTests; import static org.jetbrains.kotlin.codegen.CodegenTestUtil.*; import static org.jetbrains.kotlin.codegen.TestUtilsKt.extractUrls; import static org.jetbrains.kotlin.test.KotlinTestUtils.getAnnotationsJar; @@ -130,6 +131,8 @@ public abstract class CodegenTestCase extends KtUsefulTestCase { ); } + protected void configureTestSpecific(@NotNull CompilerConfiguration configuration, @NotNull List testFiles) {} + @NotNull protected CompilerConfiguration createConfiguration( @NotNull ConfigurationKind kind, @@ -144,6 +147,8 @@ public abstract class CodegenTestCase extends KtUsefulTestCase { updateConfiguration(configuration); setCustomDefaultJvmTarget(configuration); + configureTestSpecific(configuration, testFilesWithConfigurationDirectives); + return configuration; } @@ -354,7 +359,7 @@ public abstract class CodegenTestCase extends KtUsefulTestCase { List ktFiles = new ArrayList<>(files.size()); for (TestFile file : files) { - if (file.name.endsWith(".kt")) { + if (file.name.endsWith(".kt") || file.name.endsWith(".kts")) { // `rangesToDiagnosticNames` parameter is not-null only for diagnostic tests, it's using for lazy diagnostics String content = CheckerTestUtil.INSTANCE.parseDiagnosedRanges(file.content, new ArrayList<>(0), null); ktFiles.add(KotlinTestUtils.createFile(file.name, content, project)); diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/ir/AbstractIrTextTestCase.kt b/compiler/tests-common/tests/org/jetbrains/kotlin/ir/AbstractIrTextTestCase.kt index 8dfac0d1360..dc430329bd6 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/ir/AbstractIrTextTestCase.kt +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/ir/AbstractIrTextTestCase.kt @@ -18,6 +18,8 @@ package org.jetbrains.kotlin.ir import com.intellij.openapi.util.text.StringUtil import junit.framework.TestCase +import org.jetbrains.kotlin.cli.js.loadPluginsForTests +import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.languageVersionSettings import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor @@ -31,6 +33,7 @@ import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.scripting.compiler.plugin.loadScriptConfiguration import org.jetbrains.kotlin.test.KotlinTestUtils import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase import org.jetbrains.kotlin.utils.rethrow @@ -48,7 +51,7 @@ abstract class AbstractIrTextTestCase : AbstractIrGeneratorTestCase() { val ignoreErrors = shouldIgnoreErrors(wholeFile) val irModule = generateIrModule(ignoreErrors) - val ktFiles = testFiles.filter { it.name.endsWith(".kt") } + val ktFiles = testFiles.filter { it.name.endsWith(".kt") || it.name.endsWith(".kts") } for ((testFile, irFile) in ktFiles.zip(irModule.files)) { doTestIrFileAgainstExpectations(dir, testFile, irFile) } @@ -88,6 +91,13 @@ abstract class AbstractIrTextTestCase : AbstractIrGeneratorTestCase() { return generateMemberStub(classDescriptor) as IrClass } + override fun configureTestSpecific(configuration: CompilerConfiguration, testFiles: List) { + if (testFiles.any { it.name.endsWith(".kts") }) { + loadScriptConfiguration(configuration) + loadPluginsForTests(configuration) + } + } + private fun doTestIrFileAgainstExpectations(dir: File, testFile: TestFile, irFile: IrFile) { if (testFile.isExternalFile()) return @@ -299,7 +309,9 @@ abstract class AbstractIrTextTestCase : AbstractIrGeneratorTestCase() { internal class IrTreeFileLabel(val expectedTextFile: File, val lineNumber: Int) - protected open fun getExpectedTextFileName(testFile: TestFile, name: String = testFile.name): String = name.replace(".kt", ".txt") + protected open fun getExpectedTextFileName(testFile: TestFile, name: String = testFile.name): String { + return name.replace(".kts", ".txt").replace(".kt", ".txt") + } private fun parseExpectations(dir: File, testFile: TestFile): Expectations { val regexps = diff --git a/compiler/tests/org/jetbrains/kotlin/ir/IrJsTextTestCaseGenerated.java b/compiler/tests/org/jetbrains/kotlin/ir/IrJsTextTestCaseGenerated.java index 63b5503536c..47b87b0930e 100644 --- a/compiler/tests/org/jetbrains/kotlin/ir/IrJsTextTestCaseGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/ir/IrJsTextTestCaseGenerated.java @@ -169,4 +169,32 @@ public class IrJsTextTestCaseGenerated extends AbstractIrJsTextTestCase { runTest("compiler/testData/ir/irJsText/native/nativeNativeKotlin.kt"); } } + + @TestMetadata("compiler/testData/ir/irJsText/scripting") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Scripting extends AbstractIrJsTextTestCase { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath); + } + + public void testAllFilesPresentInScripting() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/ir/irJsText/scripting"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("arrayAssignment.kts") + public void testArrayAssignment() throws Exception { + runTest("compiler/testData/ir/irJsText/scripting/arrayAssignment.kts"); + } + + @TestMetadata("fun.kts") + public void testFun() throws Exception { + runTest("compiler/testData/ir/irJsText/scripting/fun.kts"); + } + + @TestMetadata("safeCalls.kts") + public void testSafeCalls() throws Exception { + runTest("compiler/testData/ir/irJsText/scripting/safeCalls.kts"); + } + } }