diff --git a/js/js.tests/test/org/jetbrains/k2js/test/MultipleFilesTranslationTest.java b/js/js.tests/test/org/jetbrains/k2js/test/MultipleFilesTranslationTest.java index 714a06ca16c..0556720d09e 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/MultipleFilesTranslationTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/MultipleFilesTranslationTest.java @@ -55,5 +55,10 @@ public abstract class MultipleFilesTranslationTest extends BasicTest { public void checkFooBoxIsTrue(@NotNull String dirName) throws Exception { runMultiFileTest(dirName, TEST_PACKAGE, TEST_FUNCTION, true); } + + public void checkFooBoxIsOk() throws Exception { + String dir = getTestName(true); + runMultiFileTest(dir, TEST_PACKAGE, TEST_FUNCTION, "OK"); + } } diff --git a/js/js.tests/test/org/jetbrains/k2js/test/semantics/InlineMultiFileTest.java b/js/js.tests/test/org/jetbrains/k2js/test/semantics/InlineMultiFileTest.java new file mode 100644 index 00000000000..e6692d73056 --- /dev/null +++ b/js/js.tests/test/org/jetbrains/k2js/test/semantics/InlineMultiFileTest.java @@ -0,0 +1,180 @@ +/* + * Copyright 2010-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.k2js.test.semantics; + +import com.google.dart.compiler.backend.js.ast.JsNode; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.psi.JetFile; +import org.jetbrains.k2js.config.Config; +import org.jetbrains.k2js.facade.MainCallParameters; +import org.jetbrains.k2js.test.MultipleFilesTranslationTest; +import org.jetbrains.k2js.test.utils.InlineTestUtils; +import org.jetbrains.k2js.test.utils.JsTestUtils; +import org.jetbrains.k2js.test.utils.TranslationUtils; + +import java.io.File; +import java.util.List; + +import static org.jetbrains.k2js.test.utils.JsTestUtils.getAllFilesInDir; + +public final class InlineMultiFileTest extends MultipleFilesTranslationTest { + private JsNode lastJsNode; + + public InlineMultiFileTest() { + super("inlineMultiFile/"); + } + + @Override + public void setUp() throws Exception { + super.setUp(); + lastJsNode = null; + } + + public void testInlineMultiFileSimple() throws Exception { + checkFooBoxIsOk(); + processInlineDirectives(); + } + + public void testBuilders() throws Exception { + checkFooBoxIsOk(); + } + + public void testBuildersAndLambdaCapturing() throws Exception { + checkFooBoxIsOk(); + } + + public void testAnonymousObjectOnCallSite() throws Exception { + checkFooBoxIsOk(); + } + + public void testAnonymousObjectOnCallSiteSuperParams() throws Exception { + checkFooBoxIsOk(); + } + + public void testAnonymousObjectOnDeclarationSite() throws Exception { + checkFooBoxIsOk(); + } + + public void testAnonymousObjectOnDeclarationSiteSuperParams() throws Exception { + checkFooBoxIsOk(); + } + + public void testTrait() throws Exception { + checkFooBoxIsOk(); + processInlineDirectives(); + } + + public void testUse() throws Exception { + checkFooBoxIsOk(); + } + + public void testWith() throws Exception { + checkFooBoxIsOk(); + } + + public void testTryCatch() throws Exception { + checkFooBoxIsOk(); + } + + public void testTryCatch2() throws Exception { + checkFooBoxIsOk(); + } + + public void testTryCatchFinally() throws Exception { + checkFooBoxIsOk(); + } + + public void testLambdaCloning() throws Exception { + checkFooBoxIsOk(); + } + + public void testLambdaInLambda2() throws Exception { + checkFooBoxIsOk(); + } + + public void testLambdaInLambdaNoInline() throws Exception { + checkFooBoxIsOk(); + } + + public void testRegeneratedLambdaName() throws Exception { + checkFooBoxIsOk(); + } + + public void testSameCaptured() throws Exception { + checkFooBoxIsOk(); + } + + public void testClosureChain() throws Exception { + checkFooBoxIsOk(); + } + + public void testInlineInDefaultParameter() throws Exception { + checkFooBoxIsOk(); + } + + public void testDefaultMethod() throws Exception { + checkFooBoxIsOk(); + } + + public void testSimpleDefaultMethod() throws Exception { + checkFooBoxIsOk(); + } + + public void testCaptureInlinable() throws Exception { + checkFooBoxIsOk(); + } + + public void testCaptureInlinableAndOther() throws Exception { + checkFooBoxIsOk(); + } + + public void testCaptureThisAndReceiver() throws Exception { + checkFooBoxIsOk(); + } + + public void testGenerics() throws Exception { + checkFooBoxIsOk(); + } + + public void testSimpleCapturingInClass() throws Exception { + checkFooBoxIsOk(); + } + + public void testSimpleCapturingInPackage() throws Exception { + checkFooBoxIsOk(); + } + + @Override + protected void translateFiles( + @NotNull List jetFiles, + @NotNull File outputFile, + @NotNull MainCallParameters mainCallParameters, + @NotNull Config config + ) throws Exception { + lastJsNode = TranslationUtils.translateFilesAndGetAst(mainCallParameters, jetFiles, outputFile, null, null, config); + } + + private void processInlineDirectives() throws Exception { + String dir = getTestName(true); + List fileNames = getAllFilesInDir(getInputFilePath(dir)); + + for (String fileName : fileNames) { + String fileText = JsTestUtils.readFile(fileName); + InlineTestUtils.processDirectives(lastJsNode, fileText); + } + } +} diff --git a/js/js.tests/test/org/jetbrains/k2js/test/semantics/InlineTest.java b/js/js.tests/test/org/jetbrains/k2js/test/semantics/InlineTest.java index d555fffe261..611f878a6c9 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/semantics/InlineTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/semantics/InlineTest.java @@ -16,10 +16,262 @@ package org.jetbrains.k2js.test.semantics; +import com.google.dart.compiler.backend.js.ast.JsNode; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.psi.JetFile; +import org.jetbrains.k2js.config.Config; +import org.jetbrains.k2js.facade.MainCallParameters; +import org.jetbrains.k2js.inline.exception.InlineRecursionException; import org.jetbrains.k2js.test.SingleFileTranslationTest; +import org.jetbrains.k2js.test.utils.*; + +import java.io.File; +import java.util.List; public final class InlineTest extends SingleFileTranslationTest { + private JsNode lastJsNode; + public InlineTest() { super("inline/"); } + + @Override + public void setUp() throws Exception { + super.setUp(); + lastJsNode = null; + } + + public void testInlineSimpleAssignment() throws Exception { + checkFooBoxIsOkWithInlineDirectives(); + } + + public void testInlineGenericSimple() throws Exception { + checkFooBoxIsOkWithInlineDirectives(); + } + + public void testInlineIntSimple() throws Exception { + checkFooBoxIsOkWithInlineDirectives(); + } + + public void testInlineInc() throws Exception { + checkFooBoxIsOkWithInlineDirectives(); + } + + public void testInlineCallNoInline() throws Exception { + checkFooBoxIsOkWithInlineDirectives(); + } + + public void testInlineFunctionInLambda() throws Exception { + checkFooBoxIsOkWithInlineDirectives(); + } + + public void testInlineLambdaNoCapture() throws Exception { + checkFooBoxIsOkWithInlineDirectives(); + } + + public void testInlineLambdaWithCapture() throws Exception { + checkFooBoxIsOkWithInlineDirectives(); + } + + public void testInlineChain() throws Exception { + checkFooBoxIsOkWithInlineDirectives(); + } + + public void testInlineChainWithFewStatements() throws Exception { + checkFooBoxIsOkWithInlineDirectives(); + } + + public void testCallInlineFunctionOnTopLevelSimple() throws Exception { + checkFooBoxIsOkWithInlineDirectives(); + } + + public void testCallInlineFunctionOnTopLevel() throws Exception { + checkFooBoxIsOkWithInlineDirectives(); + } + + public void testInlineIf() throws Exception { + checkFooBoxIsOkWithInlineDirectives(); + } + + public void testInlineNoReturn() throws Exception { + checkFooBoxIsOkWithInlineDirectives(); + } + + public void testStatementsAfterReturn() throws Exception { + checkFooBoxIsOkWithInlineDirectives(); + } + + public void testLambdaReassignment() throws Exception { + checkFooBoxIsOkWithInlineDirectives(); + } + + public void testLambdaReassignmentWithCapture() throws Exception { + checkFooBoxIsOkWithInlineDirectives(); + } + + public void testInlineMethod() throws Exception { + checkFooBoxIsOkWithInlineDirectives(); + } + + public void testThisImplicitlyCaptured() throws Exception { + checkFooBoxIsOkWithInlineDirectives(); + } + + public void testAstCopy() throws Exception { + checkFooBoxIsOkWithInlineDirectives(); + } + + public void testNoInlineLambda() throws Exception { + checkFooBoxIsOkWithInlineDirectives(); + } + + public void testlambdaInLambda() throws Exception { + checkFooBoxIsOkWithInlineDirectives(); + } + + public void testInlineDefaultArgument() throws Exception { + checkFooBoxIsOkWithInlineDirectives(); + } + + public void testLocalInlineFunction() throws Exception { + checkFooBoxIsOkWithInlineDirectives(); + } + + public void testLocalInlineFunctionDeclaredInLambda() throws Exception { + checkFooBoxIsOkWithInlineDirectives(); + } + + public void testLocalInlineExtensionFunction() throws Exception { + checkFooBoxIsOkWithInlineDirectives(); + } + + public void testLocalInlineFunctionNameClash() throws Exception { + checkFooBoxIsOkWithInlineDirectives(); + } + + public void testLocalInlineFunctionComplex() throws Exception { + checkFooBoxIsOkWithInlineDirectives(); + } + + public void testArrayLiteralAliasing() throws Exception { + checkFooBoxIsOkWithInlineDirectives(); + } + + public void testLocalInlineFunctionReference() throws Exception { + checkFooBoxIsOkWithInlineDirectives(); + } + + public void testThisLiteralAliasing() throws Exception { + checkFooBoxIsOkWithInlineDirectives(); + } + + public void testIdentityEquals() throws Exception { + checkFooBoxIsOkWithInlineDirectives(); + } + + public void testVararg() throws Exception { + checkFooBoxIsOkWithInlineDirectives(); + } + + public void testMutualRecursion() throws Exception { + try { + checkFooBoxIsOkWithInlineDirectives(); + } catch (Exception e) { + assert e.getCause() instanceof InlineRecursionException; + } + } + + public void testInlineOrder() throws Exception { + checkFooBoxIsOkWithInlineDirectives(); + } + + public void testCallableReference() throws Exception { + checkFooBoxIsOkWithInlineDirectives(); + } + + public void testCallableReferenceOfLocalInline() throws Exception { + checkFooBoxIsOkWithInlineDirectives(); + } + + public void testAnonymousObjectInlineMethod() throws Exception { + checkFooBoxIsOkWithInlineDirectives(); + } + + public void testLabelNameClashing() throws Exception { + checkFooBoxIsOkWithInlineDirectives(); + } + + public void testClassObject() throws Exception { + checkFooBoxIsOkWithInlineDirectives(); + } + + public void testExtension() throws Exception { + checkFooBoxIsOkWithInlineDirectives(); + } + + public void testExtensionWithManyArguments() throws Exception { + checkFooBoxIsOkWithInlineDirectives(); + } + + public void testParams() throws Exception { + checkFooBoxIsOkWithInlineDirectives(); + } + + public void testRootConstructor() throws Exception { + checkFooBoxIsOkWithInlineDirectives(); + } + + public void testSeveralClosures() throws Exception { + checkFooBoxIsOkWithInlineDirectives(); + } + + public void testSeveralUsage() throws Exception { + checkFooBoxIsOkWithInlineDirectives(); + } + + public void testSimpleDouble() throws Exception { + checkFooBoxIsOkWithInlineDirectives(); + } + + public void testSimpleInt() throws Exception { + checkFooBoxIsOkWithInlineDirectives(); + } + + public void testSimpleEnum() throws Exception { + checkFooBoxIsOkWithInlineDirectives(); + } + + public void testSimpleLambda() throws Exception { + checkFooBoxIsOkWithInlineDirectives(); + } + + public void testSimpleObject() throws Exception { + checkFooBoxIsOkWithInlineDirectives(); + } + + public void testIncrementProperty() throws Exception { + checkFooBoxIsOkWithInlineDirectives(); + } + + private void checkFooBoxIsOkWithInlineDirectives() throws Exception { + checkFooBoxIsOk(); + processInlineDirectives(); + } + + private void processInlineDirectives() throws Exception { + String fileName = getInputFilePath(getTestName(true) + ".kt"); + String fileText = JsTestUtils.readFile(fileName); + + InlineTestUtils.processDirectives(lastJsNode, fileText); + } + + @Override + protected void translateFiles( + @NotNull List jetFiles, + @NotNull File outputFile, + @NotNull MainCallParameters mainCallParameters, + @NotNull Config config + ) throws Exception { + lastJsNode = TranslationUtils.translateFilesAndGetAst(mainCallParameters, jetFiles, outputFile, null, null, config); + } } diff --git a/js/js.translator/testData/inline/cases/anonymousObjectInlineMethod.kt b/js/js.translator/testData/inline/cases/anonymousObjectInlineMethod.kt new file mode 100644 index 00000000000..0b0d18de5fc --- /dev/null +++ b/js/js.translator/testData/inline/cases/anonymousObjectInlineMethod.kt @@ -0,0 +1,16 @@ +package foo + +fun add(a: Int, b: Int): Int { + val o = object { + [inline] fun add(a: Int, b: Int): Int = a + b + } + + return o.add(a, b) +} + +fun box(): String { + assertEquals(3, add(1, 2)) + assertEquals(5, add(2, 3)) + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inline/cases/arrayLiteralAliasing.kt b/js/js.translator/testData/inline/cases/arrayLiteralAliasing.kt new file mode 100644 index 00000000000..cdfb0b764eb --- /dev/null +++ b/js/js.translator/testData/inline/cases/arrayLiteralAliasing.kt @@ -0,0 +1,27 @@ +package foo + +// CHECK_NOT_CALLED: moveTo + +native fun Array.push(element: Int): Unit = noImpl + +native fun Array.splice(index: Int, howMany: Int): Unit = noImpl + +data class PairArray(val fst: Array, val snd: Array) + +inline fun moveTo(source: Array, sink: Array): PairArray { + val size = source.size + for (i in 1..size) { + val element = source[0] + source.splice(0, 1) + sink.push(element) + } + + return PairArray(source, sink) +} + +fun box(): String { + val expected = PairArray(array(), array(1,2,3,4)) + assertEquals(expected, moveTo(array(3, 4), array(1, 2))) + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inline/cases/astCopy.kt b/js/js.translator/testData/inline/cases/astCopy.kt new file mode 100644 index 00000000000..00ed3897032 --- /dev/null +++ b/js/js.translator/testData/inline/cases/astCopy.kt @@ -0,0 +1,71 @@ +package foo + +// CHECK_FUNCTIONS_HAVE_SAME_LINES: syntaxTestInline syntaxTest + +inline fun syntaxTestInline() { + var result: Int = -0 + + for (i in 1..10) + result += 1 + + for (i in array(10).indices) + result += i + + while (result < 30) + result += 1 + + while (true) + break + + while (false) + continue + + do + result += 1 + while (result < 40) + + if (true) + result += 10 + + if (false) + result += 0 + else + result += 10 + + result += if (true) 10 else 0 + + result += if (false) 0 else 10 + + when (result) { + 0 -> result += 0 + else -> result += 10 + } + + when (result) { + result -> result += 10 + else -> result += 0 + } + + result = result + 10 - 10 * 1 / 1 + + try { + result += 10 + } catch (e: Exception) { + result += 0 + } + + result++ + + --result + + val nullable: String? = null +} + +fun syntaxTest() { + syntaxTestInline() +} + +fun box(): String { + syntaxTest() + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inline/cases/callInlineFunctionOnTopLevel.kt b/js/js.translator/testData/inline/cases/callInlineFunctionOnTopLevel.kt new file mode 100644 index 00000000000..ce5732d35c9 --- /dev/null +++ b/js/js.translator/testData/inline/cases/callInlineFunctionOnTopLevel.kt @@ -0,0 +1,34 @@ +package foo + +// CHECK_NOT_CALLED: inline1 +// CHECK_NOT_CALLED: inline2 +// CHECK_NOT_CALLED: inline3 + +inline fun inline1(a: Int): Int { + return a +} + +inline fun inline2(a: Int): Int { + val a1 = inline1(a) + if (a1 == 0) return 0 + return a1 + inline1(a) +} + +inline fun inline3(a: Int): Int { + val i = inline2(a) + val i1 = inline1(a) * i + if (i == i1) return 0 + return i1 +} + +val r1 = inline3(1) +val r3 = inline3(3) +val r4 = inline3(4) + +fun box(): String { + assertEquals(0, r1) + assertEquals(18, r3) + assertEquals(32, r4) + + return "OK" +} diff --git a/js/js.translator/testData/inline/cases/callInlineFunctionOnTopLevelSimple.kt b/js/js.translator/testData/inline/cases/callInlineFunctionOnTopLevelSimple.kt new file mode 100644 index 00000000000..cb650693195 --- /dev/null +++ b/js/js.translator/testData/inline/cases/callInlineFunctionOnTopLevelSimple.kt @@ -0,0 +1,25 @@ +package foo + +// CHECK_NOT_CALLED: abs + +inline fun abs(a: Int): Int { + if (a < 0) { + return a * -1 + } else { + return a + } +} + +val r1 = abs(1) +val r2 = abs(-2) +val r3 = abs(3) +val r4 = abs(-4) + +fun box(): String { + assertEquals(1, r1) + assertEquals(2, r2) + assertEquals(3, r3) + assertEquals(4, r4) + + return "OK" +} diff --git a/js/js.translator/testData/inline/cases/callableReference.kt b/js/js.translator/testData/inline/cases/callableReference.kt new file mode 100644 index 00000000000..01e9e6e2c92 --- /dev/null +++ b/js/js.translator/testData/inline/cases/callableReference.kt @@ -0,0 +1,23 @@ +package foo + +// CHECK_CONTAINS_NO_CALLS: multiplyInline +// CHECK_NOT_CALLED: runNoinline + +inline fun multiply(a: Int, b: Int) = a * b + +inline fun run(a: Int, b: Int, func: (Int, Int) -> Int) = func(a, b) + +fun multiplyInline(a: Int, b: Int) = run(a, b, ::multiply) + + +inline fun runNoinline(a: Int, b: Int, noinline func: (Int, Int) -> Int) = func(a, b) + +fun multiplyNoinline(a: Int, b: Int) = runNoinline(a, b, ::multiply) + + +fun box(): String { + assertEquals(6, multiplyInline(2, 3)) + assertEquals(6, multiplyNoinline(2, 3)) + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inline/cases/callableReferenceOfLocalInline.kt b/js/js.translator/testData/inline/cases/callableReferenceOfLocalInline.kt new file mode 100644 index 00000000000..8233dab758d --- /dev/null +++ b/js/js.translator/testData/inline/cases/callableReferenceOfLocalInline.kt @@ -0,0 +1,13 @@ +package foo + +fun multiplyBy(x: Int): () -> ((Int) -> Int) { + [inline] fun applyMultiplication(y: Int): Int = x * y + + return { ::applyMultiplication } +} + +fun box(): String { + assertEquals(6, multiplyBy(2)()(3)) + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inline/cases/classObject.kt b/js/js.translator/testData/inline/cases/classObject.kt new file mode 100644 index 00000000000..6e47d22197f --- /dev/null +++ b/js/js.translator/testData/inline/cases/classObject.kt @@ -0,0 +1,43 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/simple/classObject.1.kt + */ + +package foo + +inline fun inline(s: () -> String): String { + return s() +} + +class InlineAll { + + inline fun inline(s: () -> String): String { + return s() + } + + class object { + inline fun inline(s: () -> String): String { + return s() + } + } +} + +fun testClassObjectCall(): String { + return InlineAll.inline({"classobject"}) +} + +fun testInstanceCall(): String { + val inlineX = InlineAll() + return inlineX.inline({"instance"}) +} + +fun testPackageCall(): String { + return inline({"package"}) +} + +fun box(): String { + if (testClassObjectCall() != "classobject") return "test1: ${testClassObjectCall()}" + if (testInstanceCall() != "instance") return "test2: ${testInstanceCall()}" + if (testPackageCall() != "package") return "test3: ${testPackageCall()}" + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inline/cases/extension.kt b/js/js.translator/testData/inline/cases/extension.kt new file mode 100644 index 00000000000..9e9b19d25d1 --- /dev/null +++ b/js/js.translator/testData/inline/cases/extension.kt @@ -0,0 +1,76 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/simple/extension.1.kt + */ + +package foo + +inline fun with(receiver: T, f: T.() -> R): R = receiver.f() + +inline fun Inline.calcExt(s: (Int) -> Int, p: Int) : Int { + return s(p) +} + +inline fun Inline.calcExt2(s: Int.() -> Int, p: Int) : Int { + return p.s() +} + +class InlineX(val value : Int) {} + +class Inline(val res: Int) { + + inline fun InlineX.calcInt(s: (Int, Int) -> Int) : Int { + return s(res, this.value) + } + + inline fun Double.calcDouble(s: (Int, Double) -> Double) : Double { + return s(res, this) + } + + fun doWork(l : InlineX) : Int { + return l.calcInt({(a: Int, b: Int) -> a + b}) + } + + fun doWorkWithDouble(s : Double) : Double { + return s.calcDouble({(a: Int, b: Double) -> a + b}) + } + +} + +fun test1(): Int { + val inlineX = Inline(9) + return inlineX.calcExt({(z: Int) -> z}, 25) +} + +fun test2(): Int { + val inlineX = Inline(9) + return inlineX.calcExt2({Int.() -> this}, 25) +} + +fun test3(): Int { + val inlineX = Inline(9) + return inlineX.doWork(InlineX(11)) +} + +fun test4(): Double { + val inlineX = Inline(9) + return inlineX.doWorkWithDouble(11.0) +} + +fun test5(): Double { + val inlineX = Inline(9) + with(inlineX) { + 11.0.calcDouble{(a: Int, b: Double) -> a + b} + } + return inlineX.doWorkWithDouble(11.0) +} + +fun box(): String { + if (test1() != 25) return "test1: ${test1()}" + if (test2() != 25) return "test2: ${test2()}" + if (test3() != 20) return "test3: ${test3()}" + if (test4() != 20.0) return "test4: ${test4()}" + if (test5() != 20.0) return "test5: ${test5()}" + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inline/cases/extensionWithManyArguments.kt b/js/js.translator/testData/inline/cases/extensionWithManyArguments.kt new file mode 100644 index 00000000000..fe035ccf889 --- /dev/null +++ b/js/js.translator/testData/inline/cases/extensionWithManyArguments.kt @@ -0,0 +1,15 @@ +package foo + +// CHECK_NOT_CALLED_IN_SCOPE: scope=multiply function=multiply$f + +class A(val a: Int) + +inline fun with2(receiver: T, arg1: R, arg2: R, f: T.(R, R) -> R): R = receiver.f(arg1, arg2) + +fun multiply(a: Int, b: Int, c: Int): Int = with2(A(a), b, c) { (x, y) -> a*x*y } + +fun box(): String { + assertEquals(105, multiply(3, 5, 7)) + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inline/cases/identityEquals.kt b/js/js.translator/testData/inline/cases/identityEquals.kt new file mode 100644 index 00000000000..983e683425a --- /dev/null +++ b/js/js.translator/testData/inline/cases/identityEquals.kt @@ -0,0 +1,21 @@ +package foo + +class A + +inline fun compare1(a: A): Boolean { + return a identityEquals a +} + +inline fun compare2(a1: A, a2: A): Boolean { + return a1 identityEquals a2 +} + +fun box(): String { + assertEquals(true, compare1(A()), "compare1(A())") + assertEquals(false, compare2(A(), A()), "compare2(A(), A())") + + val a = A() + assertEquals(true, compare2(a, a), "compare2(a, a)") + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inline/cases/incrementProperty.kt b/js/js.translator/testData/inline/cases/incrementProperty.kt new file mode 100644 index 00000000000..60c88e23e33 --- /dev/null +++ b/js/js.translator/testData/inline/cases/incrementProperty.kt @@ -0,0 +1,23 @@ +package foo + +// CHECK_NOT_CALLED: inc +// CHECK_NOT_CALLED: run + +class Countable { + var count = 0 +} + +inline fun inc(countable: Countable) = countable.count++ + +inline fun run(func: () -> Unit) = func() + +fun incNoInline(countable: Countable) = run { inc(countable) } + +fun box(): String { + val c = Countable() + + incNoInline(c) + assertEquals(1, c.count) + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inline/cases/inlineCallNoInline.kt b/js/js.translator/testData/inline/cases/inlineCallNoInline.kt new file mode 100644 index 00000000000..d6eba0b2196 --- /dev/null +++ b/js/js.translator/testData/inline/cases/inlineCallNoInline.kt @@ -0,0 +1,36 @@ +package foo + +// CHECK_NOT_CALLED: sumEvenInRange + +fun sum(a: Int, b: Int): Int { + return a + b +} + +fun even(a: Int): Boolean { + return a % 2 == 0 +} + +inline fun sumEvenInRange(a: Int, b: Int): Int { + var c = 0 + + for (i in a..b) { + if (even(i)) { + c = sum(c, i) + } + } + + return c +} + +fun box(): String { + val sum6 = sumEvenInRange(1, 5) + assertEquals(6, sum6) + + val sum12 = sumEvenInRange(0, 7) + assertEquals(12, sum12) + + val sum20 = sumEvenInRange(0, 9) + assertEquals(20, sum20) + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inline/cases/inlineChain.kt b/js/js.translator/testData/inline/cases/inlineChain.kt new file mode 100644 index 00000000000..2b7d7c96496 --- /dev/null +++ b/js/js.translator/testData/inline/cases/inlineChain.kt @@ -0,0 +1,27 @@ +package foo + +// CHECK_CONTAINS_NO_CALLS: squareMultipliedByTwo + +inline fun inline1(a: Int): Int { + return a +} + +inline fun inline2(a: Int): Int { + return inline1(a) + inline1(a) +} + +inline fun inline3(a: Int): Int { + return inline1(a) * inline2(a) +} + +fun squareMultipliedByTwo(a: Int): Int { + return inline3(a) +} + +fun box(): String { + assertEquals(2, squareMultipliedByTwo(1)) + assertEquals(18, squareMultipliedByTwo(3)) + assertEquals(32, squareMultipliedByTwo(4)) + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inline/cases/inlineChainWithFewStatements.kt b/js/js.translator/testData/inline/cases/inlineChainWithFewStatements.kt new file mode 100644 index 00000000000..10a73feea22 --- /dev/null +++ b/js/js.translator/testData/inline/cases/inlineChainWithFewStatements.kt @@ -0,0 +1,32 @@ +package foo + +// CHECK_CONTAINS_NO_CALLS: squareMultipliedByTwo + +inline fun inline1(a: Int): Int { + return a +} + +inline fun inline2(a: Int): Int { + val a1 = inline1(a) + if (a1 == 0) return 0 + return a1 + inline1(a) +} + +inline fun inline3(a: Int): Int { + val i = inline2(a) + val i1 = inline1(a) * i + if (i == i1) return 0 + return i1 +} + +fun squareMultipliedByTwo(a: Int): Int { + return inline3(a) +} + +fun box(): String { + assertEquals(0, squareMultipliedByTwo(1)) + assertEquals(18, squareMultipliedByTwo(3)) + assertEquals(32, squareMultipliedByTwo(4)) + + return "OK" +} diff --git a/js/js.translator/testData/inline/cases/inlineDefaultArgument.kt b/js/js.translator/testData/inline/cases/inlineDefaultArgument.kt new file mode 100644 index 00000000000..efa18e307dc --- /dev/null +++ b/js/js.translator/testData/inline/cases/inlineDefaultArgument.kt @@ -0,0 +1,25 @@ +package foo + +// CHECK_CONTAINS_NO_CALLS: identity +// CHECK_CONTAINS_NO_CALLS: sumNoInline + +inline fun sum(a: Int, b: Int = 0): Int { + return a + b +} + +fun identity(a: Int): Int { + return sum(a) +} + +fun sumNoInline(a: Int, b: Int): Int { + return sum(a, b) +} + +fun box(): String { + assertEquals(1, identity(1)) + assertEquals(2, identity(2)) + assertEquals(3, sumNoInline(1, 2)) + assertEquals(5, sumNoInline(2, 3)) + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inline/cases/inlineFunctionInLambda.kt b/js/js.translator/testData/inline/cases/inlineFunctionInLambda.kt new file mode 100644 index 00000000000..69dfa16927c --- /dev/null +++ b/js/js.translator/testData/inline/cases/inlineFunctionInLambda.kt @@ -0,0 +1,23 @@ +package foo + +// CHECK_CONTAINS_NO_CALLS: doNothingNoInline + +inline fun doNothing1(a: T): T { + return a +} + +inline fun doNothing2(a: T, inline f: (T) -> T): T { + return f(a) +} + +fun doNothingNoInline(a: Int): Int { + return doNothing2(a, {(x) -> doNothing1(x)}) +} + +fun box(): String { + assertEquals(1, doNothingNoInline(1)) + assertEquals(12, doNothingNoInline(12)) + assertEquals(12, doNothingNoInline(12)) + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inline/cases/inlineGenericSimple.kt b/js/js.translator/testData/inline/cases/inlineGenericSimple.kt new file mode 100644 index 00000000000..46c1e62c378 --- /dev/null +++ b/js/js.translator/testData/inline/cases/inlineGenericSimple.kt @@ -0,0 +1,25 @@ +package foo + +// CHECK_CONTAINS_NO_CALLS: doNothingInt +// CHECK_CONTAINS_NO_CALLS: doNothingStr + +inline fun doNothing(a: T): T { + return a +} + +fun doNothingInt(a: Int): Int { + return doNothing(a) +} + +fun doNothingStr(a: String): String { + return doNothing(a) +} + +fun box(): String { + assertEquals(1, doNothingInt(1)) + assertEquals(2, doNothingInt(2)) + assertEquals("ab", doNothingStr("ab")) + assertEquals("abc", doNothingStr("abc")) + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inline/cases/inlineIf.kt b/js/js.translator/testData/inline/cases/inlineIf.kt new file mode 100644 index 00000000000..785a1dc5d24 --- /dev/null +++ b/js/js.translator/testData/inline/cases/inlineIf.kt @@ -0,0 +1,69 @@ +package foo + +// CHECK_CONTAINS_NO_CALLS: testIf1 +// CHECK_CONTAINS_NO_CALLS: testIf2 +// CHECK_CONTAINS_NO_CALLS: testIf3 + +inline fun if1(inline f: (Int) -> Int, a: Int, b: Int, c: Int): Int { + val result = f(a) + + if (result == b) { + return f(a) + } + + return f(c) +} + +inline fun if2(inline f: (Int) -> Int, a: Int, b: Int, c: Int): Int { + if (f(a) == b) { + return f(a) + } + + return f(c) +} + +inline fun if3(inline f: (Int) -> Int, a: Int, b: Int, c: Int): Int { + if (f(a) == b) { + return f(a) + } else { + return f(c) + } +} + +fun testIf1(): String { + val test1 = if1({it}, 1, 2, 3) + if (test1 != 3) return "testIf1: test1 fail" + + val test2 = if1({it}, 2, 2, 3) + if (test2 != 2) return "testIf1: test 2 fail" + + return "OK" +} + +fun testIf2(): String { + val test1 = if2({it}, 1, 2, 3) + if (test1 != 3) return "testIf2: test1 fail" + + val test2 = if2({it}, 2, 2, 3) + if (test2 != 2) return "testIf2: test 2 fail" + + return "OK" +} + +fun testIf3(): String { + val test1 = if3({it}, 1, 2, 3) + if (test1 != 3) return "testIf3: test1 fail" + + val test2 = if3({it}, 2, 2, 3) + if (test2 != 2) return "testIf3: test 2 fail" + + return "OK" +} + +fun box(): String { + assertEquals("OK", testIf1()) + assertEquals("OK", testIf2()) + assertEquals("OK", testIf3()) + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inline/cases/inlineInc.kt b/js/js.translator/testData/inline/cases/inlineInc.kt new file mode 100644 index 00000000000..12c37ba1bf3 --- /dev/null +++ b/js/js.translator/testData/inline/cases/inlineInc.kt @@ -0,0 +1,22 @@ +package foo + +// CHECK_CONTAINS_NO_CALLS: multiplyNoInline + +inline fun multiply(a: Int, b: Int): Int { + return a * b +} + +fun multiplyNoInline(a: Int, b: Int): Int { + var c = a - 1 + var d = b - 1 + return (c++) + (d++) + multiply(c, d) - (--c + --d) +} + +fun box(): String { + assertEquals(0, multiplyNoInline(1, 0)) + assertEquals(1, multiplyNoInline(1, 1)) + assertEquals(2, multiplyNoInline(1, 2)) + assertEquals(6, multiplyNoInline(2, 3)) + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inline/cases/inlineIntSimple.kt b/js/js.translator/testData/inline/cases/inlineIntSimple.kt new file mode 100644 index 00000000000..30b1f79c57b --- /dev/null +++ b/js/js.translator/testData/inline/cases/inlineIntSimple.kt @@ -0,0 +1,42 @@ +package foo + +// CHECK_CONTAINS_NO_CALLS: doNothing1 +// CHECK_CONTAINS_NO_CALLS: doNothing2 +// CHECK_CONTAINS_NO_CALLS: doNothing3 + +class Inline { + public inline fun identity1 (x: T): T { + return x + } + + public inline fun identity2 (x: T, inline f: (T) -> T): T { + return f(x) + } + + public inline fun identity3 (inline f: () -> T): T { + return f() + } +} + +fun doNothing1 (inline1: Inline, a: Int): Int { + return inline1.identity1(a) +} + +fun doNothing2 (inline2: Inline, a: Int): Int { + return inline2.identity2(a, {it}) +} + +fun doNothing3 (inline3: Inline): Int { + return inline3.identity3({11}) +} + +fun box(): String { + val inline = Inline() + assertEquals(1, doNothing1(inline, 1)) + assertEquals(2, doNothing1(inline, 2)) + assertEquals(3, doNothing2(inline, 3)) + assertEquals(4, doNothing2(inline, 4)) + assertEquals(11, doNothing3(inline)) + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inline/cases/inlineLambdaNoCapture.kt b/js/js.translator/testData/inline/cases/inlineLambdaNoCapture.kt new file mode 100644 index 00000000000..072f0800632 --- /dev/null +++ b/js/js.translator/testData/inline/cases/inlineLambdaNoCapture.kt @@ -0,0 +1,28 @@ +package foo + +// CHECK_CONTAINS_NO_CALLS: sumEven + +inline fun filteredReduce(a: Array, inline predicate: (Int) -> Boolean, inline reduceFun: (Int, Int) -> Int): Int { + var result = 0 + + for (element in a) { + val satisfyPred = predicate(element) + if (satisfyPred) { + result = reduceFun(result, element) + } + } + + return result +} + +fun sumEven(a: Array): Int { + return filteredReduce(a, {(x) -> x % 2 == 0}, {(x, y) -> x + y}) +} + +fun box(): String { + assertEquals(0, sumEven(array())) + assertEquals(6, sumEven(array(1,2,3,4))) + assertEquals(12, sumEven(array(1,2,3,4,6,7,9))) + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inline/cases/inlineLambdaWithCapture.kt b/js/js.translator/testData/inline/cases/inlineLambdaWithCapture.kt new file mode 100644 index 00000000000..2f9048889b4 --- /dev/null +++ b/js/js.translator/testData/inline/cases/inlineLambdaWithCapture.kt @@ -0,0 +1,41 @@ +package foo + +// CHECK_CONTAINS_NO_CALLS: maxBySquare + +data class Result(var value: Int = 0, var invocationCount: Int = 0) + +inline fun maxBy(a: Array, inline keyFun: (Int) -> Int): Int { + var maxVal = a[0] + var maxKey = keyFun(maxVal) + + for (element in a) { + val key = keyFun(element) + + if (key > maxKey) { + maxVal = element + maxKey = key + } + } + + return maxVal +} + +fun maxBySquare(a: Array, r: Result): Result { + var invocationCount = 0 + val maxVal = maxBy(a, {(x) -> invocationCount++; x * x;}) + + r.value = maxVal + r.invocationCount = invocationCount + + return r +} + +fun box(): String { + var r1 = maxBySquare(array(1,2,3,4,5), Result()) + assertEquals(Result(5, 6), r1) + + var r2 = maxBySquare(array(-5,1,2,3,4), Result()) + assertEquals(Result(-5, 6), r2) + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inline/cases/inlineMethod.kt b/js/js.translator/testData/inline/cases/inlineMethod.kt new file mode 100644 index 00000000000..b25c76327e4 --- /dev/null +++ b/js/js.translator/testData/inline/cases/inlineMethod.kt @@ -0,0 +1,27 @@ +package foo + +// CHECK_CONTAINS_NO_CALLS: add + +data class IntPair(public var fst: Int, public var snd: Int) { + inline public fun getFst(): Int { return fst } + inline public fun setFst(v: Int) { fst = v } + + inline public fun getSnd(): Int { return this.snd } + inline public fun setSnd(v: Int) { this.snd = v } +} + +fun add(p: IntPair, toFst: Int, toSnd: Int) { + val fst = p.getFst() + p.setFst(fst + toFst) + + val snd = p.getSnd() + p.setSnd(snd + toSnd) +} + +fun box(): String { + val p = IntPair(0, 0) + add(p, 1, 2) + assertEquals(IntPair(1, 2), p) + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inline/cases/inlineNoReturn.kt b/js/js.translator/testData/inline/cases/inlineNoReturn.kt new file mode 100644 index 00000000000..293c5e062fb --- /dev/null +++ b/js/js.translator/testData/inline/cases/inlineNoReturn.kt @@ -0,0 +1,52 @@ +package foo + +// CHECK_CONTAINS_NO_CALLS: factAbsNoInline1 + +class State(value: Int) { + public var value: Int = value +} + +inline fun multiply(state: State, factor: Int) { + state.value *= factor +} + +inline fun abs(state: State) { + val value = state.value + if (value < 0) { + multiply(state, -1) + } +} + +inline fun factAbs(state: State) { + abs(state) + + if (state.value == 0) { + state.value = 1 + return + } + + var n = state.value + while (n > 1) { + n-- + multiply(state, n) + } +} + +fun factAbsNoInline1(state: State): Int { + factAbs(state) + return state.value +} + +fun factAbsNoInline2(n: Int): Int { + return factAbsNoInline1(State(n)) +} + +fun box(): String { + assertEquals(1, factAbsNoInline2(0)) + assertEquals(2, factAbsNoInline2(2)) + assertEquals(6, factAbsNoInline2(-3)) + assertEquals(120, factAbsNoInline2(5)) + assertEquals(720, factAbsNoInline2(-6)) + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inline/cases/inlineOrder.kt b/js/js.translator/testData/inline/cases/inlineOrder.kt new file mode 100644 index 00000000000..deff662bfd1 --- /dev/null +++ b/js/js.translator/testData/inline/cases/inlineOrder.kt @@ -0,0 +1,39 @@ +package foo + +// CHECK_FUNCTIONS_HAVE_SAME_LINES: declaredBefore declaredAfter match=(h|g)1 replace=$1 + +fun declaredBefore(): Int { + val a = g() + h() + return a +} + +inline fun g(): Int { + val a = h() + return a +} + +inline fun h(): Int { + val a = 1 + return a +} + +inline fun g1(): Int { + val a = h1() + return a +} + +inline fun h1(): Int { + val a = 1 + return a +} + +fun declaredAfter(): Int { + val a = g1() + h1() + return a +} + +fun box(): String { + assertEquals(declaredBefore(), declaredAfter()) + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inline/cases/inlineSimpleAssignment.kt b/js/js.translator/testData/inline/cases/inlineSimpleAssignment.kt new file mode 100644 index 00000000000..3edcb78f789 --- /dev/null +++ b/js/js.translator/testData/inline/cases/inlineSimpleAssignment.kt @@ -0,0 +1,17 @@ +package foo + +// CHECK_NOT_CALLED: sum + +inline fun sum(a: Int, b: Int): Int { + return a + b +} + +fun box(): String { + val sum3 = sum(1, 2) + assertEquals(3, sum3) + + val sum6 = sum(sum3, 3) + assertEquals(6, sum6) + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inline/cases/labelNameClashing.kt b/js/js.translator/testData/inline/cases/labelNameClashing.kt new file mode 100644 index 00000000000..26ee0a1273a --- /dev/null +++ b/js/js.translator/testData/inline/cases/labelNameClashing.kt @@ -0,0 +1,45 @@ +package foo + +inline fun testLabelInline(): Int { + var a = 0 + + @loop for (i in 1..10) { + if (i == 1) continue@loop + + a += i + + if (i == 2) break@loop + } + + @loop for (i in 1..10) { + if (i == 1) continue@loop + + a += i + + if (i == 2) break@loop + } + + return a +} + +fun testLabel(): String { + var a = 0 + + @loop for (i in 1..10) { + if (i == 1) continue@loop + + a += testLabelInline() + + if (i == 2) break@loop + } + + if (a != 4) return a.toString() + + return "OK" +} + +fun box(): String { + assertEquals("OK", testLabel()) + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inline/cases/lambdaInLambda.kt b/js/js.translator/testData/inline/cases/lambdaInLambda.kt new file mode 100644 index 00000000000..45f4b5acc39 --- /dev/null +++ b/js/js.translator/testData/inline/cases/lambdaInLambda.kt @@ -0,0 +1,21 @@ +package foo + +// CHECK_CALLED_IN_SCOPE: scope=multiplyBy2 function=multiplyBy2$f +// CHECK_NOT_CALLED_IN_SCOPE: scope=multiplyBy2 function=multiplyBy2$f_0 +// CHECK_NOT_CALLED_IN_SCOPE: scope=multiplyBy2 function=run + +inline fun runLambdaInLambda(noinline inner: (T) -> T, outer: ((T) -> T, T) -> T, arg: T): T { + return outer(inner, arg) +} + +fun multiplyBy2(x: Int): Int { + return runLambdaInLambda({ it * 2 }, { f, x -> f(x) }, x) +} + +fun box(): String { + assertEquals(0, multiplyBy2(0)) + assertEquals(4, multiplyBy2(2)) + assertEquals(8, multiplyBy2(4)) + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inline/cases/lambdaReassignment.kt b/js/js.translator/testData/inline/cases/lambdaReassignment.kt new file mode 100644 index 00000000000..12e58d03b27 --- /dev/null +++ b/js/js.translator/testData/inline/cases/lambdaReassignment.kt @@ -0,0 +1,25 @@ +package foo + +inline fun run(func: () -> Int): Int { + return func() +} + +fun bar(): Int { + var f = { () -> 0 } + var get0 = f + + f = { () -> 1 } + var get1 = f + + var get2 = get1 + f = { () -> 2 } + get2 = f + + return run(get0) + run(get1) + run(get2) +} + +fun box(): String { + assertEquals(3, bar()) + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inline/cases/lambdaReassignmentWithCapture.kt b/js/js.translator/testData/inline/cases/lambdaReassignmentWithCapture.kt new file mode 100644 index 00000000000..06caa58d5a9 --- /dev/null +++ b/js/js.translator/testData/inline/cases/lambdaReassignmentWithCapture.kt @@ -0,0 +1,29 @@ +package foo + +data class IntPair(public var fst: Int, public var snd: Int) + +inline fun run(func: () -> Int): Int { + return func() +} + +fun bar(p: IntPair): Int { + var f = { () -> p.fst++ } + var get0 = f + + f = { () -> ++p.snd } + var get1 = f + + var get2 = get1 + f = { () -> ++p.fst } + get2 = f + + return run(get0) + run(get1) + run(get2) +} + +fun box(): String { + val p = IntPair(0, 0) + assertEquals(3, bar(p)) + assertEquals(IntPair(2, 1), p) + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inline/cases/localInlineExtensionFunction.kt b/js/js.translator/testData/inline/cases/localInlineExtensionFunction.kt new file mode 100644 index 00000000000..eb1e2868626 --- /dev/null +++ b/js/js.translator/testData/inline/cases/localInlineExtensionFunction.kt @@ -0,0 +1,50 @@ +package foo + +// CHECK_CONTAINS_NO_CALLS: capturedInLambda +// CHECK_CONTAINS_NO_CALLS: declaredInLambda + +data class State(var count: Int = 0) + +inline fun repeat(times: Int, action: () -> Unit) { + for (i in 1..times) { + action() + } +} + +fun capturedInLambda(state: State, a: Int, b: Int): Int { + [inline] fun State.inc() { + count++ + } + + repeat(a + b) { + state.inc() + } + + return state.count +} + + +fun declaredInLambda(state: State, a: Int, b: Int): Int { + repeat(a) { + [inline] fun State.inc() { + count++ + } + + repeat(b) { + state.inc() + } + } + + return state.count +} + + +fun box(): String { + assertEquals(3, capturedInLambda(State(), 1, 2), "capturedInLambda") + assertEquals(9, capturedInLambda(State(), 4, 5), "capturedInLambda") + + assertEquals(2, declaredInLambda(State(), 1, 2), "declaredInLambda") + assertEquals(20, declaredInLambda(State(), 4, 5), "declaredInLambda") + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inline/cases/localInlineFunction.kt b/js/js.translator/testData/inline/cases/localInlineFunction.kt new file mode 100644 index 00000000000..4070e7ef197 --- /dev/null +++ b/js/js.translator/testData/inline/cases/localInlineFunction.kt @@ -0,0 +1,48 @@ +package foo + +// CHECK_CONTAINS_NO_CALLS: localWithCapture +// CHECK_CONTAINS_NO_CALLS: localWithoutCapture + +inline fun repeat(times: Int, action: () -> Unit) { + for (i in 1..times) { + action() + } +} + +fun localWithoutCapture(a: Int, b: Int): Int { + var sum = 0 + + [inline] fun inc(x: Int): Int { + return x + 1 + } + + repeat(a + b) { + sum = inc(sum) + } + + return sum +} + +fun localWithCapture(a: Int, b: Int): Int { + var sum = 0 + + [inline] fun inc() { + sum++ + } + + repeat(a + b) { + inc() + } + + return sum +} + +fun box(): String { + assertEquals(3, localWithoutCapture(1, 2), "localWithoutCapture") + assertEquals(9, localWithoutCapture(4, 5), "localWithoutCapture") + + assertEquals(3, localWithCapture(1, 2), "localWithCapture") + assertEquals(9, localWithCapture(4, 5), "localWithCapture") + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inline/cases/localInlineFunctionComplex.kt b/js/js.translator/testData/inline/cases/localInlineFunctionComplex.kt new file mode 100644 index 00000000000..e807e5955fc --- /dev/null +++ b/js/js.translator/testData/inline/cases/localInlineFunctionComplex.kt @@ -0,0 +1,43 @@ +package foo + +// CHECK_CONTAINS_NO_CALLS: add + +data class State(var count: Int = 0) + +inline fun repeat(times: Int, action: () -> Unit) { + for (i in 1..times) { + action() + } +} + +fun add(state: State, a: Int, b: Int): Int { + [inline] fun inc(a: Int): Int { + return a + 1 + } + + [inline] fun inc1(a: Int): Int { + return inc(a) + } + + repeat(a) { + [inline] fun inc2(a: Int): Int { + return inc1(a) + } + + repeat(b) { + [inline] fun State.inc() { + count = inc2(count) + } + + state.inc() + } + } + + return state.count +} + +fun box(): String { + assertEquals(20, add(State(), 4, 5)) + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inline/cases/localInlineFunctionDeclaredInLambda.kt b/js/js.translator/testData/inline/cases/localInlineFunctionDeclaredInLambda.kt new file mode 100644 index 00000000000..89a874f48bf --- /dev/null +++ b/js/js.translator/testData/inline/cases/localInlineFunctionDeclaredInLambda.kt @@ -0,0 +1,52 @@ +package foo + +// CHECK_CONTAINS_NO_CALLS: localWithCapture +// CHECK_CONTAINS_NO_CALLS: localWithoutCapture + +inline fun repeat(times: Int, action: () -> Unit) { + for (i in 1..times) { + action() + } +} + +fun localWithoutCapture(a: Int, b: Int): Int { + var mult = 0 + + repeat(a) { + [inline] fun inc(x: Int): Int { + return x + 1 + } + + repeat(b) { + mult = inc(mult) + } + } + + return mult +} + +fun localWithCapture(a: Int, b: Int): Int { + var mult = 0 + + repeat(a) { + [inline] fun inc() { + mult++ + } + + repeat(b) { + inc() + } + } + + return mult +} + +fun box(): String { + assertEquals(2, localWithoutCapture(1, 2), "localWithoutCapture") + assertEquals(20, localWithoutCapture(4, 5), "localWithoutCapture") + + assertEquals(2, localWithCapture(1, 2), "localWithCapture") + assertEquals(20, localWithCapture(4, 5), "localWithCapture") + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inline/cases/localInlineFunctionNameClash.kt b/js/js.translator/testData/inline/cases/localInlineFunctionNameClash.kt new file mode 100644 index 00000000000..7ff7d639955 --- /dev/null +++ b/js/js.translator/testData/inline/cases/localInlineFunctionNameClash.kt @@ -0,0 +1,30 @@ +package foo + +// CHECK_CONTAINS_NO_CALLS: add + +inline fun run(action: () -> Int): Int { + return action() +} + +fun add(a: Int, b: Int): Int { + var sum = a + b + + [inline] fun getSum(): Int { + return sum + } + + return run { + var sum = 0 + + run { + sum = -1 + getSum() + } + } +} + +fun box(): String { + assertEquals(3, add(1, 2)) + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inline/cases/localInlineFunctionReference.kt b/js/js.translator/testData/inline/cases/localInlineFunctionReference.kt new file mode 100644 index 00000000000..3a49398941f --- /dev/null +++ b/js/js.translator/testData/inline/cases/localInlineFunctionReference.kt @@ -0,0 +1,13 @@ +package foo + +fun multiplyBy(a: Int): (Int) -> Int { + [inline] fun multiply(b: Int): Int = a * b + + return ::multiply +} + +fun box(): String { + assertEquals(6, multiplyBy(2)(3)) + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inline/cases/mutualRecursion.kt b/js/js.translator/testData/inline/cases/mutualRecursion.kt new file mode 100644 index 00000000000..78d76a82c97 --- /dev/null +++ b/js/js.translator/testData/inline/cases/mutualRecursion.kt @@ -0,0 +1,13 @@ +package foo + +inline fun f() { g() } + +inline fun g() { h() } + +inline fun h() { f() } + +fun box(): String { + f() + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inline/cases/noInlineLambda.kt b/js/js.translator/testData/inline/cases/noInlineLambda.kt new file mode 100644 index 00000000000..a7d7d538ba2 --- /dev/null +++ b/js/js.translator/testData/inline/cases/noInlineLambda.kt @@ -0,0 +1,20 @@ +package foo + +// CHECK_CALLED_IN_SCOPE: scope=multiplyBy2 function=multiplyBy2$f +// CHECK_NOT_CALLED_IN_SCOPE: scope=multiplyBy2 function=run + +inline fun run(noinline func: (T) -> T, arg: T): T { + return func(arg) +} + +fun multiplyBy2(x: Int): Int { + return run({ it * 2 }, x) +} + +fun box(): String { + assertEquals(0, multiplyBy2(0)) + assertEquals(4, multiplyBy2(2)) + assertEquals(8, multiplyBy2(4)) + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inline/cases/params.kt b/js/js.translator/testData/inline/cases/params.kt new file mode 100644 index 00000000000..71e8ac9d686 --- /dev/null +++ b/js/js.translator/testData/inline/cases/params.kt @@ -0,0 +1,53 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/simple/params.1.kt + */ + +package foo + +class Inline() { + + inline fun foo1Int(s : (l: Int) -> Int, param: Int) : Int { + return s(param) + } + + inline fun foo1Double(param: Double, s : (l: Double) -> Double) : Double { + return s(param) + } + + inline fun foo2Param(param1: Double, s : (i: Int, l: Double) -> Double, param2: Int) : Double { + return s(param2, param1) + } +} + +fun test1(): Int { + val inlineX = Inline() + return inlineX.foo1Int({(z: Int) -> z}, 25) +} + +fun test2(): Double { + val inlineX = Inline() + return inlineX.foo1Double(25.0, {(z: Double) -> z}) +} + +fun test3(): Double { + val inlineX = Inline() + return inlineX.foo2Param(15.0, {(z1: Int, z2: Double) -> z1 + z2}, 10) +} + +fun test3WithCaptured(): Double { + val inlineX = Inline() + var c = 11.0; + return inlineX.foo2Param(15.0, {(z1: Int, z2: Double) -> z1 + z2 + c}, 10) +} + + +fun box(): String { + if (test1() != 25) return "test1: ${test1()}" + if (test2() != 25.0) return "test2: ${test2()}" + if (test3() != 25.0) return "test3: ${test3()}" + if (test3WithCaptured() != 36.0) return "test3WithCaptured: ${test3WithCaptured()}" + + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inline/cases/rootConstructor.kt b/js/js.translator/testData/inline/cases/rootConstructor.kt new file mode 100644 index 00000000000..361b297b1c3 --- /dev/null +++ b/js/js.translator/testData/inline/cases/rootConstructor.kt @@ -0,0 +1,24 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/simple/rootConstructor.1.kt + */ + +package foo + +import kotlin.InlineOption.* + +inline fun doWork(inlineOptions(ONLY_LOCAL_RETURN) job: ()-> R) : R { + return notInline({job()}) +} + +fun notInline(job: ()-> R) : R { + return job() +} + +val s = doWork({11}) + +fun box(): String { + if (s != 11) return "test1: ${s}" + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inline/cases/severalClosures.kt b/js/js.translator/testData/inline/cases/severalClosures.kt new file mode 100644 index 00000000000..ce5361f200e --- /dev/null +++ b/js/js.translator/testData/inline/cases/severalClosures.kt @@ -0,0 +1,41 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/simple/severalClosures.1.kt + */ + +package foo + +class Inline() { + + inline fun foo1(closure1 : (l: Int) -> Int, param1: Int, closure2 : (l: Double) -> Double, param2: Double) : Double { + return closure1(param1) + closure2(param2) + } + + inline fun foo2(closure1 : (Int, Int) -> Int, param1: Int, closure2 : (Double, Int, Int) -> Double, param2: Double, param3: Int) : Double { + return closure1(param1, param3) + closure2(param2, param1, param3) + } +} + +fun test1(): Double { + val inlineX = Inline() + return inlineX.foo1({(z: Int) -> z}, 25, {(z: Double) -> z}, 11.5) +} + +fun test1WithCaptured(): Double { + val inlineX = Inline() + var d = 0.0; + return inlineX.foo1({(z: Int) -> d = 1.0; z}, 25, {(z: Double) -> z + d}, 11.5) +} + +fun test2(): Double { + val inlineX = Inline() + return inlineX.foo2({(z: Int, p: Int) -> z + p}, 25, {(x: Double, y: Int, z: Int) -> z + x + y}, 11.5, 2) +} + +fun box(): String { + if (test1() != 36.5) return "test1: ${test1()}" + if (test1WithCaptured() != 37.5) return "test1WithCaptured: ${test1WithCaptured()}" + if (test2() != 65.5) return "test2: ${test2()}" + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inline/cases/severalUsage.kt b/js/js.translator/testData/inline/cases/severalUsage.kt new file mode 100644 index 00000000000..9533606b243 --- /dev/null +++ b/js/js.translator/testData/inline/cases/severalUsage.kt @@ -0,0 +1,24 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/simple/severalUsage.1.kt + */ + +package foo + +public inline fun runTest(f: () -> R): R { + return f() +} + +public inline fun minByTest(f: (Int) -> R): R { + var minValue = f(1) + val v = f(1) + return v +} + +fun box(): String { + val result = runTest{minByTest { it }} + + if (result != 1) return "test1: ${result}" + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inline/cases/simpleDouble.kt b/js/js.translator/testData/inline/cases/simpleDouble.kt new file mode 100644 index 00000000000..b21b43a35d4 --- /dev/null +++ b/js/js.translator/testData/inline/cases/simpleDouble.kt @@ -0,0 +1,79 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/simple/simpleDouble.1.kt + */ + +package foo + +class InlineDouble(val res : Double) { + + inline fun foo(s : () -> Double) : Double { + val f = "fooStart" + val z = s() + return z + } + + inline fun foo11(s : (l: Double) -> Double) : Double { + return s(11.0) + } + + inline fun fooRes(s : (l: Double) -> Double) : Double { + val z = s(res) + return z + } + + inline fun fooRes2(s : (l: Double, t: Double) -> Double) : Double { + val f = "fooRes2Start" + val z = s(1.0, 11.0) + return z + } +} + +fun test0Param(): Double { + val inlineX = InlineDouble(10.0) + return inlineX.foo({() -> 1.0}) +} + +fun test1Param(): Double { + val inlineX = InlineDouble(10.0) + return inlineX.foo11({(z: Double) -> z}) +} + +fun test1ParamCaptured(): Double { + val s = 100.0 + val inlineX = InlineDouble(10.0) + return inlineX.foo11({(z: Double) -> s}) +} + +fun test1ParamMissed() : Double { + val inlineX = InlineDouble(10.0) + return inlineX.foo11({(z: Double) -> 111.0}) +} + +fun test1ParamFromCallContext() : Double { + val inlineX = InlineDouble(1000.0) + return inlineX.fooRes({(z: Double) -> z}) +} + +fun test2Params() : Double { + val inlineX = InlineDouble(1000.0) + return inlineX.fooRes2({(y: Double, z: Double) -> 2.0 * y + 3.0 * z}) +} + +fun test2ParamsWithCaptured() : Double { + val inlineX = InlineDouble(1000.0) + val s = 9.0 + var t = 1.0 + return inlineX.fooRes2({(y: Double, z: Double) -> 2.0 * s + t}) +} + +fun box(): String { + if (test0Param() != 1.0) return "test0Param" + if (test1Param() != 11.0) return "test1Param()" + if (test1ParamCaptured() != 100.0) return "testtest1ParamCaptured()" + if (test1ParamMissed() != 111.0) return "test1ParamMissed()" + if (test1ParamFromCallContext() != 1000.0) return "test1ParamFromCallContext()" + if (test2Params() != 35.0) return "test2Params()" + if (test2ParamsWithCaptured() != 19.0) return "test2ParamsWithCaptured()" + return "OK" +} diff --git a/js/js.translator/testData/inline/cases/simpleEnum.kt b/js/js.translator/testData/inline/cases/simpleEnum.kt new file mode 100644 index 00000000000..4a0ffdbac81 --- /dev/null +++ b/js/js.translator/testData/inline/cases/simpleEnum.kt @@ -0,0 +1,26 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/simple/simpleEnum.1.kt + */ + +package foo + +enum class MyEnum { + K; + + //TODO: KT-4693 + [inline] fun doSmth(a: T) : String { + return a.toString() + K.name() + } +} + +fun test1(): String { + return MyEnum.K.doSmth("O") +} + +fun box(): String { + val result = test1() + if (result != "OK") return "fail1: ${result}" + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inline/cases/simpleInt.kt b/js/js.translator/testData/inline/cases/simpleInt.kt new file mode 100644 index 00000000000..872b868df2a --- /dev/null +++ b/js/js.translator/testData/inline/cases/simpleInt.kt @@ -0,0 +1,79 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/simple/simpleInt.1.kt + */ + +package foo + +class Inline(val res : Int) { + + inline fun foo(s : () -> Int) : Int { + val f = "fooStart" + val z = s() + return z + } + + inline fun foo11(s : (l: Int) -> Int) : Int { + return s(11) + } + + inline fun fooRes(s : (l: Int) -> Int) : Int { + val z = s(res) + return z + } + + inline fun fooRes2(s : (l: Int, t: Int) -> Int) : Int { + val f = "fooRes2Start" + val z = s(1, 11) + return z + } +} + +fun test0Param(): Int { + val inlineX = Inline(10) + return inlineX.foo({() -> 1}) +} + +fun test1Param(): Int { + val inlineX = Inline(10) + return inlineX.foo11({(z: Int) -> z}) +} + +fun test1ParamCaptured(): Int { + val s = 100 + val inlineX = Inline(10) + return inlineX.foo11({(z: Int) -> s}) +} + +fun test1ParamMissed() : Int { + val inlineX = Inline(10) + return inlineX.foo11({(z: Int) -> 111}) +} + +fun test1ParamFromCallContext() : Int { + val inlineX = Inline(1000) + return inlineX.fooRes({(z: Int) -> z}) +} + +fun test2Params() : Int { + val inlineX = Inline(1000) + return inlineX.fooRes2({(y: Int, z: Int) -> 2 * y + 3 * z}) +} + +fun test2ParamsWithCaptured() : Int { + val inlineX = Inline(1000) + val s = 9 + var t = 1 + return inlineX.fooRes2({(y: Int, z: Int) -> 2 * s + t}) +} + +fun box(): String { + if (test0Param() != 1) return "test0Param: ${test0Param()}" + if (test1Param() != 11) return "test1Param: ${test1Param()}" + if (test1ParamCaptured() != 100) return "test1ParamCaptured: ${test1ParamCaptured()}" + if (test1ParamMissed() != 111) return "test1ParamMissed: ${test1ParamMissed()}" + if (test1ParamFromCallContext() != 1000) return "test1ParamFromCallContext: ${test1ParamFromCallContext()}" + if (test2Params() != 35) return "test2Params: ${test2Params()}" + if (test2ParamsWithCaptured() != 19) return "test2ParamsWithCaptured: ${test2ParamsWithCaptured()}" + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inline/cases/simpleLambda.kt b/js/js.translator/testData/inline/cases/simpleLambda.kt new file mode 100644 index 00000000000..1d7c9f31a08 --- /dev/null +++ b/js/js.translator/testData/inline/cases/simpleLambda.kt @@ -0,0 +1,39 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/simple/simpleLambda.1.kt + */ + +package foo + +public class Data() + +public inline fun T.use(block: (T)-> R) : R { + return block(this) +} + +public inline fun use2() : Int { + val s = 100 + return s +} + +class Z {} + +fun test1() : Int { + val input = Z() + return input.use{ + 100 + } +} + +fun test2() : Int { + val x = 1000 + return use2() + x +} + + +fun box(): String { + if (test1() != 100) return "test1: ${test1()}" + if (test2() != 1100) return "test1: ${test2()}" + + return "OK" +} diff --git a/js/js.translator/testData/inline/cases/simpleObject.kt b/js/js.translator/testData/inline/cases/simpleObject.kt new file mode 100644 index 00000000000..56888308178 --- /dev/null +++ b/js/js.translator/testData/inline/cases/simpleObject.kt @@ -0,0 +1,80 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/simple/simpleObject.1.kt + */ + +package foo + +class InlineString(val res : String) { + + inline fun foo(s : () -> String) : String { + val f = "fooStart" + val z = s() + return z + } + + inline fun foo11(s : (l: String) -> String) : String { + return s("11") + } + + inline fun fooRes(s : (l: String) -> String) : String { + val z = s(res) + return z + } + + inline fun fooRes2(s : (l: String, t: String) -> String) : String { + val f = "fooRes2Start" + val z = s("1", "11") + return z + } +} + +fun test0Param(): String { + val inlineX = InlineString("10") + return inlineX.foo({() -> "1"}) +} + +fun test1Param(): String { + val inlineX = InlineString("10") + return inlineX.foo11({(z: String) -> z}) +} + +fun test1ParamCaptured(): String { + val s = "100" + val inlineX = InlineString("10") + return inlineX.foo11({(z: String) -> s}) +} + +fun test1ParamMissed() : String { + val inlineX = InlineString("10") + return inlineX.foo11({(z: String) -> "111"}) +} + +fun test1ParamFromCallContext() : String { + val inlineX = InlineString("1000") + return inlineX.fooRes({(z: String) -> z}) +} + +fun test2Params() : String { + val inlineX = InlineString("1000") + return inlineX.fooRes2({(y: String, z: String) -> y + "0" + z}) +} + +fun test2ParamsWithCaptured() : String { + val inlineX = InlineString("1000") + val s = "9" + var t = "1" + return inlineX.fooRes2({(y: String, z: String) -> s + t}) +} + +fun box(): String { + if (test0Param() != "1") return "test0Param: ${test0Param()}" + if (test1Param() != "11") return "test1Param: ${test1Param()}" + if (test1ParamCaptured() != "100") return "test1ParamCaptured: ${test1ParamCaptured()}" + if (test1ParamMissed() != "111") return "test1ParamMissed: ${test1ParamMissed()}" + if (test1ParamFromCallContext() != "1000") return "test1ParamFromCallContext: ${test1ParamFromCallContext()}" + if (test2Params() != "1011") return "test2Params: ${test2Params()}" + if (test2ParamsWithCaptured() != "91") return "test2ParamsWithCaptured: ${test2ParamsWithCaptured()}" + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inline/cases/statementsAfterReturn.kt b/js/js.translator/testData/inline/cases/statementsAfterReturn.kt new file mode 100644 index 00000000000..8420613da11 --- /dev/null +++ b/js/js.translator/testData/inline/cases/statementsAfterReturn.kt @@ -0,0 +1,21 @@ +package foo + +data class State(public var value: Int = 10) + +inline fun withState(state: State, ext: State.() -> Unit) { + state.ext() + return + state.value = 0 +} + +fun box(): String { + val state = State() + + withState(state) { + value = 111 + } + + assertEquals(111, state.value) + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inline/cases/thisImplicitlyCaptured.kt b/js/js.translator/testData/inline/cases/thisImplicitlyCaptured.kt new file mode 100644 index 00000000000..8e721c806f1 --- /dev/null +++ b/js/js.translator/testData/inline/cases/thisImplicitlyCaptured.kt @@ -0,0 +1,36 @@ +package foo + +class Runner { + public fun run(f: () -> Unit): Unit = f() +} + +class Counter() { + var count = 0 + val runner = Runner() + + public fun count(n: Int) { + for (i in 1..n) { + tick() + } + } + + public fun getCount(): Int = count + + private inline fun tick() { + runner.run { count++ } + } +} + +fun add(a: Int, b: Int): Int { + val counter = Counter() + counter.count(a) + counter.count(b) + return counter.getCount() +} + +fun box(): String { + assertEquals(3, add(1, 2)) + assertEquals(7, add(3, 4)) + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inline/cases/thisLiteralAliasing.kt b/js/js.translator/testData/inline/cases/thisLiteralAliasing.kt new file mode 100644 index 00000000000..0a06d8bcf90 --- /dev/null +++ b/js/js.translator/testData/inline/cases/thisLiteralAliasing.kt @@ -0,0 +1,24 @@ +package foo + +class A() { + public var param: Int = 0 + + inline public fun setParam(value: Int) { + val b = B(value) + b.setParam(this) + } +} + +class B(val value: Int) { + inline fun setParam(a: A) { + a.param = this.value + } +} + +public fun box(): String { + val a = A() + a.setParam(10) + assertEquals(10, a.param) + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inline/cases/vararg.kt b/js/js.translator/testData/inline/cases/vararg.kt new file mode 100644 index 00000000000..5def6aad0cd --- /dev/null +++ b/js/js.translator/testData/inline/cases/vararg.kt @@ -0,0 +1,30 @@ +package foo + + +// CHECK_CONTAINS_NO_CALLS: test1 +// CHECK_CONTAINS_NO_CALLS: test2 + +inline fun sum(vararg nums: Int): Int { + var result = 0 + + for (num in nums) { + result += num + } + + return result +} + +fun test1(): Int { + return sum() +} + +fun test2(): Int { + return sum(1,2,3) +} + +fun box(): String { + assertEquals(0, test1()) + assertEquals(6, test2()) + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inlineMultiFile/_commonFiles/core.kt b/js/js.translator/testData/inlineMultiFile/_commonFiles/core.kt new file mode 100644 index 00000000000..f1b3b34a6be --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/_commonFiles/core.kt @@ -0,0 +1 @@ +native public fun parseInt(s: String, radix: Int = 10): Int = js.noImpl \ No newline at end of file diff --git a/js/js.translator/testData/inlineMultiFile/cases/anonymousObjectOnCallSite/anonymousObjectOnCallSite.1.kt b/js/js.translator/testData/inlineMultiFile/cases/anonymousObjectOnCallSite/anonymousObjectOnCallSite.1.kt new file mode 100644 index 00000000000..f86d886a47b --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/anonymousObjectOnCallSite/anonymousObjectOnCallSite.1.kt @@ -0,0 +1,35 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/anonymousObject/anonymousObjectOnCallSite.1.kt + */ + +package foo + +import test.* + +fun box() : String { + val o = "O" + val p = "GOOD" + val result = doWork { + val k = "K" + val s = object : A() { + + val param = p; + + override fun getO(): String { + return o; + } + + override fun getK(): String { + return k; + } + } + + s.getO() + s.getK() + s.param + } + + if (result != "OKGOOD") return "fail $result" + + return "OK" +} + diff --git a/js/js.translator/testData/inlineMultiFile/cases/anonymousObjectOnCallSite/anonymousObjectOnCallSite.2.kt b/js/js.translator/testData/inlineMultiFile/cases/anonymousObjectOnCallSite/anonymousObjectOnCallSite.2.kt new file mode 100644 index 00000000000..6d1a1876cca --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/anonymousObjectOnCallSite/anonymousObjectOnCallSite.2.kt @@ -0,0 +1,17 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/anonymousObject/anonymousObjectOnCallSite.2.kt + */ + +package test + +abstract class A { + abstract fun getO() : R + + abstract fun getK() : R +} + + +inline fun doWork(job: ()-> R) : R { + return job() +} \ No newline at end of file diff --git a/js/js.translator/testData/inlineMultiFile/cases/anonymousObjectOnCallSiteSuperParams/anonymousObjectOnCallSiteSuperParams.1.kt b/js/js.translator/testData/inlineMultiFile/cases/anonymousObjectOnCallSiteSuperParams/anonymousObjectOnCallSiteSuperParams.1.kt new file mode 100644 index 00000000000..8212c05d56c --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/anonymousObjectOnCallSiteSuperParams/anonymousObjectOnCallSiteSuperParams.1.kt @@ -0,0 +1,31 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/anonymousObject/anonymousObjectOnCallSiteSuperParams.1.kt + */ + +package foo + +import test.* + +fun box() : String { + val o = "O" + val result = doWork { + val k = "K" + val s = object : A("11") { + override fun getO(): String { + return o; + } + + override fun getK(): String { + return k; + } + } + + s.getO() + s.getK() + s.param + } + + if (result != "OK11") return "fail $result" + + return "OK" +} + diff --git a/js/js.translator/testData/inlineMultiFile/cases/anonymousObjectOnCallSiteSuperParams/anonymousObjectOnCallSiteSuperParams.2.kt b/js/js.translator/testData/inlineMultiFile/cases/anonymousObjectOnCallSiteSuperParams/anonymousObjectOnCallSiteSuperParams.2.kt new file mode 100644 index 00000000000..9a504f139b9 --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/anonymousObjectOnCallSiteSuperParams/anonymousObjectOnCallSiteSuperParams.2.kt @@ -0,0 +1,17 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/anonymousObject/anonymousObjectOnCallSiteSuperParams.2.kt + */ + +package test + +abstract class A(val param: R) { + abstract fun getO() : R + + abstract fun getK() : R +} + + +inline fun doWork(job: ()-> R) : R { + return job() +} \ No newline at end of file diff --git a/js/js.translator/testData/inlineMultiFile/cases/anonymousObjectOnDeclarationSite/anonymousObjectOnDeclarationSite.1.kt b/js/js.translator/testData/inlineMultiFile/cases/anonymousObjectOnDeclarationSite/anonymousObjectOnDeclarationSite.1.kt new file mode 100644 index 00000000000..176a50729c5 --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/anonymousObjectOnDeclarationSite/anonymousObjectOnDeclarationSite.1.kt @@ -0,0 +1,37 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/anonymousObject/anonymousObjectOnDeclarationSite.1.kt + */ + +package foo + +import test.* + +fun test1(): String { + val o = "O" + + val result = doWork ({o}, {"K"}, "GOOD") + + return result.getO() + result.getK() + result.getParam() +} + +fun test2() : String { + //same names as in object + val o1 = "O" + val k1 = "K" + + val result = doWorkInConstructor ({o1}, {k1}, "GOOD") + + return result.getO() + result.getK() + result.getParam() +} + +fun box() : String { + val result1 = test1(); + if (result1 != "OKGOOD") return "fail1 $result1" + + val result2 = test2(); + if (result2 != "OKGOOD") return "fail2 $result2" + + return "OK" +} + diff --git a/js/js.translator/testData/inlineMultiFile/cases/anonymousObjectOnDeclarationSite/anonymousObjectOnDeclarationSite.2.kt b/js/js.translator/testData/inlineMultiFile/cases/anonymousObjectOnDeclarationSite/anonymousObjectOnDeclarationSite.2.kt new file mode 100644 index 00000000000..2ee07235f07 --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/anonymousObjectOnDeclarationSite/anonymousObjectOnDeclarationSite.2.kt @@ -0,0 +1,57 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/anonymousObject/anonymousObjectOnDeclarationSite.2.kt + */ + + +package test + +import kotlin.InlineOption.* + +abstract class A { + abstract fun getO() : R + + abstract fun getK() : R + + abstract fun getParam() : R +} + +inline fun doWork(inlineOptions(ONLY_LOCAL_RETURN) jobO: ()-> R, inlineOptions(ONLY_LOCAL_RETURN) jobK: ()-> R, param: R) : A { + val s = object : A() { + + override fun getO(): R { + return jobO() + } + override fun getK(): R { + return jobK() + } + + override fun getParam(): R { + return param + } + } + return s; +} + +inline fun doWorkInConstructor(inlineOptions(ONLY_LOCAL_RETURN) jobO: ()-> R, inlineOptions(ONLY_LOCAL_RETURN) jobK: ()-> R, param: R) : A { + val s = object : A() { + + val p = param; + + val o1 = jobO() + + val k1 = jobK() + + override fun getO(): R { + return o1 + } + override fun getK(): R { + return k1 + } + + override fun getParam(): R { + return p + } + } + return s; +} \ No newline at end of file diff --git a/js/js.translator/testData/inlineMultiFile/cases/anonymousObjectOnDeclarationSiteSuperParams/anonymousObjectOnDeclarationSiteSuperParams.1.kt b/js/js.translator/testData/inlineMultiFile/cases/anonymousObjectOnDeclarationSiteSuperParams/anonymousObjectOnDeclarationSiteSuperParams.1.kt new file mode 100644 index 00000000000..3e32c1e1761 --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/anonymousObjectOnDeclarationSiteSuperParams/anonymousObjectOnDeclarationSiteSuperParams.1.kt @@ -0,0 +1,37 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/anonymousObject/anonymousObjectOnDeclarationSiteSuperParams.1.kt + */ + +package foo + +import test.* + +fun test1(): String { + val o = "O" + + val result = doWork ({o}, {"K"}, "11") + + return result.getO() + result.getK() + result.param +} + +fun test2() : String { + //same names as in object + val o1 = "O" + val k1 = "K" + val param = "11" + val result = doWorkInConstructor ({o1}, {k1}, {param}) + + return result.getO() + result.getK() + result.param +} + +fun box() : String { + val result1 = test1(); + if (result1 != "OK11") return "fail1 $result1" + + val result2 = test2(); + if (result2 != "OK11") return "fail2 $result2" + + return "OK" +} + diff --git a/js/js.translator/testData/inlineMultiFile/cases/anonymousObjectOnDeclarationSiteSuperParams/anonymousObjectOnDeclarationSiteSuperParams.2.kt b/js/js.translator/testData/inlineMultiFile/cases/anonymousObjectOnDeclarationSiteSuperParams/anonymousObjectOnDeclarationSiteSuperParams.2.kt new file mode 100644 index 00000000000..ace213046b8 --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/anonymousObjectOnDeclarationSiteSuperParams/anonymousObjectOnDeclarationSiteSuperParams.2.kt @@ -0,0 +1,43 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/anonymousObject/anonymousObjectOnDeclarationSiteSuperParams.1.kt + */ + +package test + +import kotlin.InlineOption.* + +abstract class A(val param : R) { + abstract fun getO() : R + + abstract fun getK() : R +} + +inline fun doWork(inlineOptions(ONLY_LOCAL_RETURN) jobO: ()-> R, inlineOptions(ONLY_LOCAL_RETURN) jobK: ()-> R, param: R) : A { + val s = object : A(param) { + + override fun getO(): R { + return jobO() + } + override fun getK(): R { + return jobK() + } + } + return s; +} + +inline fun doWorkInConstructor(inlineOptions(ONLY_LOCAL_RETURN) jobO: ()-> R, inlineOptions(ONLY_LOCAL_RETURN) jobK: ()-> R, inlineOptions(ONLY_LOCAL_RETURN) param: () -> R) : A { + val s = object : A(param()) { + val o1 = jobO() + + val k1 = jobK() + + override fun getO(): R { + return o1 + } + override fun getK(): R { + return k1 + } + } + return s; +} \ No newline at end of file diff --git a/js/js.translator/testData/inlineMultiFile/cases/builders/builders.1.kt b/js/js.translator/testData/inlineMultiFile/cases/builders/builders.1.kt new file mode 100644 index 00000000000..e1322bf481b --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/builders/builders.1.kt @@ -0,0 +1,178 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/builders/builders.1.kt + */ + +package foo + +fun testAllInline() : String { + val args = array("1", "2", "3") + val result = + html { + val htmlVal = 0 + head { + title { +"XML encoding with Kotlin" } + } + body { + var bodyVar = 1 + h1 { +"XML encoding with Kotlin" } + p { +"this format can be used as an alternative markup to XML" } + + // an element with attributes and text content + a(href = "http://jetbrains.com/kotlin") { +"Kotlin" } + + // mixed content + p { + +"This is some" + b { +"mixed" } + +"text. For more see the" + a(href = "http://jetbrains.com/kotlin") { +"Kotlin" } + +"project" + } + p { +"some text" } + + // content generated from command-line arguments + p { + +"Command line arguments were:" + ul { + for (arg in args) + li { +arg; +"$htmlVal"; +"$bodyVar" } + } + } + } + } + + return result.toString()!! +} + +fun testHtmlNoInline() : String { + val args = array("1", "2", "3") + val result = + htmlNoInline() { + val htmlVal = 0 + head { + title { +"XML encoding with Kotlin" } + } + body { + var bodyVar = 1 + h1 { +"XML encoding with Kotlin" } + p { +"this format can be used as an alternative markup to XML" } + + // an element with attributes and text content + a(href = "http://jetbrains.com/kotlin") { +"Kotlin" } + + // mixed content + p { + +"This is some" + b { +"mixed" } + +"text. For more see the" + a(href = "http://jetbrains.com/kotlin") { +"Kotlin" } + +"project" + } + p { +"some text" } + + // content generated from command-line arguments + p { + +"Command line arguments were:" + ul { + for (arg in args) + li { +arg; +"$htmlVal"; +"$bodyVar" } + } + } + } + } + + return result.toString()!! +} + +fun testBodyNoInline() : String { + val args = array("1", "2", "3") + val result = + html { + val htmlVal = 0 + head { + title { +"XML encoding with Kotlin" } + } + bodyNoInline { + var bodyVar = 1 + h1 { +"XML encoding with Kotlin" } + p { +"this format can be used as an alternative markup to XML" } + + // an element with attributes and text content + a(href = "http://jetbrains.com/kotlin") { +"Kotlin" } + + // mixed content + p { + +"This is some" + b { +"mixed" } + +"text. For more see the" + a(href = "http://jetbrains.com/kotlin") { +"Kotlin" } + +"project" + } + p { +"some text" } + + // content generated from command-line arguments + p { + +"Command line arguments were:" + ul { + for (arg in args) + li { +arg; +"$htmlVal"; +"$bodyVar" } + } + } + } + } + + return result.toString()!! +} + +fun testBodyHtmlNoInline() : String { + val args = array("1", "2", "3") + val result = + htmlNoInline { + val htmlVal = 0 + head { + title { +"XML encoding with Kotlin" } + } + bodyNoInline { + var bodyVar = 1 + h1 { +"XML encoding with Kotlin" } + p { +"this format can be used as an alternative markup to XML" } + + // an element with attributes and text content + a(href = "http://jetbrains.com/kotlin") { +"Kotlin" } + + // mixed content + p { + +"This is some" + b { +"mixed" } + +"text. For more see the" + a(href = "http://jetbrains.com/kotlin") { +"Kotlin" } + +"project" + } + p { +"some text" } + + // content generated from command-line arguments + p { + +"Command line arguments were:" + ul { + for (arg in args) + li { +arg; +"$htmlVal"; +"$bodyVar" } + } + } + } + } + + return result.toString()!! +} + +fun box(): String { + var expected = testAllInline(); + + if (expected != testHtmlNoInline()) return "fail 1: ${testHtmlNoInline()}\nbut expected\n${expected} " + + if (expected != testBodyNoInline()) return "fail 2: ${testBodyNoInline()}\nbut expected\n${expected} " + + if (expected != testBodyHtmlNoInline()) return "fail 3: ${testBodyHtmlNoInline()}\nbut expected\n${expected} " + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inlineMultiFile/cases/builders/builders.2.kt b/js/js.translator/testData/inlineMultiFile/cases/builders/builders.2.kt new file mode 100644 index 00000000000..d88d5581a52 --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/builders/builders.2.kt @@ -0,0 +1,113 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/builders/builders.2.kt + */ + +package foo + +import java.util.ArrayList +import java.util.HashMap + +trait Element { + fun render(builder: StringBuilder, indent: String) + + override fun toString(): String { + val builder = StringBuilder() + render(builder, "") + return builder.toString() + } +} + +class TextElement(val text: String) : Element { + override fun render(builder: StringBuilder, indent: String) { + builder.append("$indent$text\n") + } +} + +abstract class Tag(val name: String) : Element { + val children = ArrayList() + val attributes = HashMap() + + inline protected fun initTag(tag: T, init: T.() -> Unit): T { + tag.init() + children.add(tag) + return tag + } + + override fun render(builder: StringBuilder, indent: String) { + builder.append("$indent<$name${renderAttributes()}>\n") + for (c in children) { + c.render(builder, indent + " ") + } + builder.append("$indent\n") + } + + private fun renderAttributes(): String? { + val builder = StringBuilder() + for (a in attributes.keySet()) { + builder.append(" $a=\"${attributes[a]}\"") + } + return builder.toString() + } +} + +abstract class TagWithText(name: String) : Tag(name) { + fun String.plus() { + children.add(TextElement(this)) + } +} + +class HTML() : TagWithText("html") { + inline fun head(init: Head.() -> Unit) = initTag(Head(), init) + + inline fun body(init: Body.() -> Unit) = initTag(Body(), init) + + fun bodyNoInline(init: Body.() -> Unit) = initTag(Body(), init) +} + +class Head() : TagWithText("head") { + inline fun title(init: Title.() -> Unit) = initTag(Title(), init) +} + +class Title() : TagWithText("title") + +abstract class BodyTag(name: String) : TagWithText(name) { + inline fun b(init: B.() -> Unit) = initTag(B(), init) + inline fun p(init: P.() -> Unit) = initTag(P(), init) + inline fun pNoInline(init: P.() -> Unit) = initTag(P(), init) + inline fun h1(init: H1.() -> Unit) = initTag(H1(), init) + inline fun ul(init: UL.() -> Unit) = initTag(UL(), init) + inline fun a(href: String, init: A.() -> Unit) { + val a = initTag(A(), init) + a.href = href + } +} + +class Body() : BodyTag("body") +class UL() : BodyTag("ul") { + inline fun li(init: LI.() -> Unit) = initTag(LI(), init) +} + +class B() : BodyTag("b") +class LI() : BodyTag("li") +class P() : BodyTag("p") +class H1() : BodyTag("h1") +class A() : BodyTag("a") { + public var href: String + get() = attributes["href"]!! + set(value) { + attributes["href"] = value + } +} + +inline fun html(init: HTML.() -> Unit): HTML { + val html = HTML() + html.init() + return html +} + +fun htmlNoInline(init: HTML.() -> Unit): HTML { + val html = HTML() + html.init() + return html +} \ No newline at end of file diff --git a/js/js.translator/testData/inlineMultiFile/cases/buildersAndLambdaCapturing/buildersAndLambdaCapturing.1.kt b/js/js.translator/testData/inlineMultiFile/cases/buildersAndLambdaCapturing/buildersAndLambdaCapturing.1.kt new file mode 100644 index 00000000000..7e3acc8b833 --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/buildersAndLambdaCapturing/buildersAndLambdaCapturing.1.kt @@ -0,0 +1,184 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/builders/buildersAndLambdaCapturing.1.kt + */ + +package foo + +import kotlin.InlineOption.* + +inline fun testAllInline(f: () -> String) : String { + val args = array("1", "2", "3") + val result = + html { + val htmlVal = 0 + head { + title { +"XML encoding with Kotlin" } + } + body { + var bodyVar = 1 + h1 { +"XML encoding with Kotlin" } + p { +"this format can be used as an alternative markup to XML" } + + // an element with attributes and text content + a(href = "http://jetbrains.com/kotlin") { +"Kotlin" } + + // mixed content + p { + +"This is some" + b { +"mixed" } + +"text. For more see the" + a(href = "http://jetbrains.com/kotlin") { +"Kotlin" } + +"project" + } + p { +"some text" } + + // content generated from command-line arguments + p { + +"Command line arguments were:" + ul { + for (arg in args) + li { +arg; +"$htmlVal"; +"$bodyVar"; +"${f()}" } + } + } + } + } + + return result.toString()!! +} + +inline fun testHtmlNoInline(inlineOptions(ONLY_LOCAL_RETURN) f: () -> String) : String { + val args = array("1", "2", "3") + val result = + htmlNoInline() { + val htmlVal = 0 + head { + title { +"XML encoding with Kotlin" } + } + body { + var bodyVar = 1 + h1 { +"XML encoding with Kotlin" } + p { +"this format can be used as an alternative markup to XML" } + + // an element with attributes and text content + a(href = "http://jetbrains.com/kotlin") { +"Kotlin" } + + // mixed content + p { + +"This is some" + b { +"mixed" } + +"text. For more see the" + a(href = "http://jetbrains.com/kotlin") { +"Kotlin" } + +"project" + } + p { +"some text" } + + // content generated from command-line arguments + p { + +"Command line arguments were:" + ul { + for (arg in args) + li { +arg; +"$htmlVal"; +"$bodyVar"; +"${f()}" } + } + } + } + } + + return result.toString()!! +} + +inline fun testBodyNoInline(inlineOptions(ONLY_LOCAL_RETURN) f: () -> String) : String { + val args = array("1", "2", "3") + val result = + html { + val htmlVal = 0 + head { + title { +"XML encoding with Kotlin" } + } + bodyNoInline { + var bodyVar = 1 + h1 { +"XML encoding with Kotlin" } + p { +"this format can be used as an alternative markup to XML" } + + // an element with attributes and text content + a(href = "http://jetbrains.com/kotlin") { +"Kotlin" } + + // mixed content + p { + +"This is some" + b { +"mixed" } + +"text. For more see the" + a(href = "http://jetbrains.com/kotlin") { +"Kotlin" } + +"project" + } + p { +"some text" } + + // content generated from command-line arguments + p { + +"Command line arguments were:" + ul { + for (arg in args) + li { +arg; +"$htmlVal"; +"$bodyVar"; +"${f()}" } + } + } + } + } + + return result.toString()!! +} + +inline fun testBodyHtmlNoInline(inlineOptions(ONLY_LOCAL_RETURN) f: () -> String) : String { + val args = array("1", "2", "3") + val result = + htmlNoInline { + val htmlVal = 0 + head { + title { +"XML encoding with Kotlin" } + } + bodyNoInline { + var bodyVar = 1 + h1 { +"XML encoding with Kotlin" } + p { +"this format can be used as an alternative markup to XML" } + + // an element with attributes and text content + a(href = "http://jetbrains.com/kotlin") { +"Kotlin" } + + // mixed content + p { + +"This is some" + b { +"mixed" } + +"text. For more see the" + a(href = "http://jetbrains.com/kotlin") { +"Kotlin" } + +"project" + } + p { +"some text" } + + // content generated from command-line arguments + p { + +"Command line arguments were:" + ul { + for (arg in args) + li { +arg; +"$htmlVal"; +"$bodyVar"; +"${f()}" } + } + } + } + } + + return result.toString()!! +} + +fun box(): String { + var expected = testAllInline({"x"}); + print(expected + " " + testHtmlNoInline({"x"})) + + if (expected != testHtmlNoInline({"x"})) return "fail 1: ${testHtmlNoInline({"x"})}\nbut expected\n${expected} " + if (expected != testBodyNoInline({"x"})) return "fail 2: ${testBodyNoInline({"x"})}\nbut expected\n${expected} " + if (expected != testBodyHtmlNoInline({"x"})) return "fail 3: ${testBodyHtmlNoInline({"x"})}\nbut expected\n${expected} " + + var captured = "x" + if (expected != testHtmlNoInline({captured})) return "fail 4: ${testHtmlNoInline({captured})}\nbut expected\n${expected} " + if (expected != testBodyNoInline({captured})) return "fail 5: ${testBodyNoInline({captured})}\nbut expected\n${expected} " + if (expected != testBodyHtmlNoInline({captured})) return "fail 6: ${testBodyHtmlNoInline({captured})}\nbut expected\n${expected} " + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inlineMultiFile/cases/buildersAndLambdaCapturing/buildersAndLambdaCapturing.2.kt b/js/js.translator/testData/inlineMultiFile/cases/buildersAndLambdaCapturing/buildersAndLambdaCapturing.2.kt new file mode 100644 index 00000000000..53181d20959 --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/buildersAndLambdaCapturing/buildersAndLambdaCapturing.2.kt @@ -0,0 +1,113 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/builders/buildersAndLambdaCapturing.2.kt + */ + +package foo + +import java.util.ArrayList +import java.util.HashMap + +trait Element { + fun render(builder: StringBuilder, indent: String) + + override fun toString(): String { + val builder = StringBuilder() + render(builder, "") + return builder.toString() + } +} + +class TextElement(val text: String) : Element { + override fun render(builder: StringBuilder, indent: String) { + builder.append("$indent$text\n") + } +} + +abstract class Tag(val name: String) : Element { + val children = ArrayList() + val attributes = HashMap() + + inline protected fun initTag(tag: T, init: T.() -> Unit): T { + tag.init() + children.add(tag) + return tag + } + + override fun render(builder: StringBuilder, indent: String) { + builder.append("$indent<$name${renderAttributes()}>\n") + for (c in children) { + c.render(builder, indent + " ") + } + builder.append("$indent\n") + } + + private fun renderAttributes(): String? { + val builder = StringBuilder() + for (a in attributes.keySet()) { + builder.append(" $a=\"${attributes[a]}\"") + } + return builder.toString() + } +} + +abstract class TagWithText(name: String) : Tag(name) { + fun String.plus() { + children.add(TextElement(this)) + } +} + +class HTML() : TagWithText("html") { + inline fun head(init: Head.() -> Unit) = initTag(Head(), init) + + inline fun body(init: Body.() -> Unit) = initTag(Body(), init) + + fun bodyNoInline(init: Body.() -> Unit) = initTag(Body(), init) +} + +class Head() : TagWithText("head") { + inline fun title(init: Title.() -> Unit) = initTag(Title(), init) +} + +class Title() : TagWithText("title") + +abstract class BodyTag(name: String) : TagWithText(name) { + inline fun b(init: B.() -> Unit) = initTag(B(), init) + inline fun p(init: P.() -> Unit) = initTag(P(), init) + fun pNoInline(init: P.() -> Unit) = initTag(P(), init) + inline fun h1(init: H1.() -> Unit) = initTag(H1(), init) + inline fun ul(init: UL.() -> Unit) = initTag(UL(), init) + inline fun a(href: String, init: A.() -> Unit) { + val a = initTag(A(), init) + a.href = href + } +} + +class Body() : BodyTag("body") +class UL() : BodyTag("ul") { + inline fun li(init: LI.() -> Unit) = initTag(LI(), init) +} + +class B() : BodyTag("b") +class LI() : BodyTag("li") +class P() : BodyTag("p") +class H1() : BodyTag("h1") +class A() : BodyTag("a") { + public var href: String + get() = attributes["href"]!! + set(value) { + attributes["href"] = value + } +} + +inline fun html(init: HTML.() -> Unit): HTML { + val html = HTML() + html.init() + return html +} + +fun htmlNoInline(init: HTML.() -> Unit): HTML { + val html = HTML() + html.init() + return html +} \ No newline at end of file diff --git a/js/js.translator/testData/inlineMultiFile/cases/captureInlinable/captureInlinable.1.kt b/js/js.translator/testData/inlineMultiFile/cases/captureInlinable/captureInlinable.1.kt new file mode 100644 index 00000000000..a5f4a0d3391 --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/captureInlinable/captureInlinable.1.kt @@ -0,0 +1,18 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/capture/captureInlinable.1.kt + */ + +package foo + +import test.* + +fun box(): String { + val result = doWork({11}) + if (result != 11) return "test1: ${result}" + + val result2 = doWork({12; result+1}) + if (result2 != 12) return "test2: ${result2}" + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inlineMultiFile/cases/captureInlinable/captureInlinable.2.kt b/js/js.translator/testData/inlineMultiFile/cases/captureInlinable/captureInlinable.2.kt new file mode 100644 index 00000000000..4851b30e986 --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/captureInlinable/captureInlinable.2.kt @@ -0,0 +1,17 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/capture/captureInlinable.2.kt + */ + +package test + +import kotlin.InlineOption.* + +inline fun doWork(inlineOptions(ONLY_LOCAL_RETURN) job: ()-> R) : R { + return notInline({job()}) +} + +fun notInline(job: ()-> R) : R { + return job() +} + diff --git a/js/js.translator/testData/inlineMultiFile/cases/captureInlinableAndOther/captureInlinableAndOther.1.kt b/js/js.translator/testData/inlineMultiFile/cases/captureInlinableAndOther/captureInlinableAndOther.1.kt new file mode 100644 index 00000000000..ec0fa2186b3 --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/captureInlinableAndOther/captureInlinableAndOther.1.kt @@ -0,0 +1,18 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/capture/captureInlinableAndOther.1.kt + */ + +package foo + +import test.* + +fun box(): String { + val result = doWork({11}) + if (result != 11) return "test1: ${result}" + + val result2 = doWork({12; result+1}) + if (result2 != 12) return "test2: ${result2}" + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inlineMultiFile/cases/captureInlinableAndOther/captureInlinableAndOther.2.kt b/js/js.translator/testData/inlineMultiFile/cases/captureInlinableAndOther/captureInlinableAndOther.2.kt new file mode 100644 index 00000000000..50128bae9c6 --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/captureInlinableAndOther/captureInlinableAndOther.2.kt @@ -0,0 +1,18 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/capture/captureInlinableAndOther.2.kt + */ + +package test + +import kotlin.InlineOption.* + +inline fun doWork(inlineOptions(ONLY_LOCAL_RETURN) job: ()-> R) : R { + val k = 10; + return notInline({k; job()}) +} + +fun notInline(job: ()-> R) : R { + return job() +} + diff --git a/js/js.translator/testData/inlineMultiFile/cases/captureThisAndReceiver/captureThisAndReceiver.1.kt b/js/js.translator/testData/inlineMultiFile/cases/captureThisAndReceiver/captureThisAndReceiver.1.kt new file mode 100644 index 00000000000..226cfc4082f --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/captureThisAndReceiver/captureThisAndReceiver.1.kt @@ -0,0 +1,35 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/capture/captureThisAndReceiver.1.kt + */ + +package foo + +fun test1() : Int { + val inlineX = My(111) + + return inlineX.perform{ + + val outX = My(1111111) + outX.perform( + {inlineX.value} + ) + } +} + +inline fun My.execute(): Int { + return perform { this.value } +} + +fun test2(): Int { + val inlineX = My(11) + + return inlineX.execute() +} + +fun box(): String { + if (test1() != 111) return "test1: ${test1()}" + if (test2() != 11) return "test2: ${test2()}" + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inlineMultiFile/cases/captureThisAndReceiver/captureThisAndReceiver.2.kt b/js/js.translator/testData/inlineMultiFile/cases/captureThisAndReceiver/captureThisAndReceiver.2.kt new file mode 100644 index 00000000000..7f777963454 --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/captureThisAndReceiver/captureThisAndReceiver.2.kt @@ -0,0 +1,13 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/capture/captureThisAndReceiver.2.kt + */ + +package foo + +class My(val value: Int) + +inline fun T.perform(job: (T)-> R) : R { + return job(this) +} + diff --git a/js/js.translator/testData/inlineMultiFile/cases/closureChain/closureChain.1.kt b/js/js.translator/testData/inlineMultiFile/cases/closureChain/closureChain.1.kt new file mode 100644 index 00000000000..2bd6ccc4165 --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/closureChain/closureChain.1.kt @@ -0,0 +1,17 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/complex/closureChain.1.kt + */ + +package foo + +fun test1(): Int { + val inlineX = Inline() + return inlineX.foo({(z: Int) -> "" + z}, 25, {String.() -> this.length}) +} + +fun box(): String { + if (test1() != 2) return "test1: ${test1()}" + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inlineMultiFile/cases/closureChain/closureChain.2.kt b/js/js.translator/testData/inlineMultiFile/cases/closureChain/closureChain.2.kt new file mode 100644 index 00000000000..6c6fca3800f --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/closureChain/closureChain.2.kt @@ -0,0 +1,14 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/complex/closureChain.2.kt + */ + +package foo + +class Inline() { + + inline fun foo(closure1 : (l: Int) -> String, param: Int, closure2: String.() -> Int) : Int { + return closure1(param).closure2() + } +} + diff --git a/js/js.translator/testData/inlineMultiFile/cases/defaultMethod/defaultMethod.1.kt b/js/js.translator/testData/inlineMultiFile/cases/defaultMethod/defaultMethod.1.kt new file mode 100644 index 00000000000..1a16cf10345 --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/defaultMethod/defaultMethod.1.kt @@ -0,0 +1,29 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/defaultValues/defaultMethod.1.kt + */ + +package foo + +import test.* + +fun simple(): String { + val k = "K" + return simpleFun(lambda = {it + "O"}) + simpleFun("K", {k + it}) +} + +fun simpleR(): String { + val k = "K" + return simpleFunR({it + "O"}) + simpleFunR({k + it}, "K") +} + +fun box(): String { + + var result = simple() + if (result != "OOKK") return "fail1: ${result}" + + result = simpleR() + if (result != "OOKK") return "fail2: ${result}" + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inlineMultiFile/cases/defaultMethod/defaultMethod.2.kt b/js/js.translator/testData/inlineMultiFile/cases/defaultMethod/defaultMethod.2.kt new file mode 100644 index 00000000000..671259224db --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/defaultMethod/defaultMethod.2.kt @@ -0,0 +1,15 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/defaultValues/defaultMethod.2.kt + */ + +package test + +inline fun simpleFun(arg: String = "O", lambda: (String) -> T): T { + return lambda(arg) +} + +inline fun simpleFunR(lambda: (String) -> T, arg: String = "O"): T { + return lambda(arg) +} + diff --git a/js/js.translator/testData/inlineMultiFile/cases/generics/generics.1.kt b/js/js.translator/testData/inlineMultiFile/cases/generics/generics.1.kt new file mode 100644 index 00000000000..a1a1fbf9e37 --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/generics/generics.1.kt @@ -0,0 +1,24 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/capture/generics.1.kt + */ + +package foo + +import test.* + +fun test1(s: Int): String { + var result = "OK" + result = mfun(s) { a -> + result + doSmth(s) + doSmth(a) + } + + return result +} + +fun box(): String { + val result = test1(11) + if (result != "OK1111") return "fail1: ${result}" + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inlineMultiFile/cases/generics/generics.2.kt b/js/js.translator/testData/inlineMultiFile/cases/generics/generics.2.kt new file mode 100644 index 00000000000..decfa1b70ac --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/generics/generics.2.kt @@ -0,0 +1,14 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/capture/generics.2.kt + */ + +package test + +inline fun mfun(arg: T, f: (T) -> R) : R { + return f(arg) +} + +inline fun doSmth(a: T): String { + return a.toString() +} \ No newline at end of file diff --git a/js/js.translator/testData/inlineMultiFile/cases/inlineInDefaultParameter/inlineInDefaultParameter.1.kt b/js/js.translator/testData/inlineMultiFile/cases/inlineInDefaultParameter/inlineInDefaultParameter.1.kt new file mode 100644 index 00000000000..cc660bfa229 --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/inlineInDefaultParameter/inlineInDefaultParameter.1.kt @@ -0,0 +1,33 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/defaultValues/inlineInDefaultParameter.1.kt + */ + +package foo + +import test.* + +fun testCompilation(arg: String = getStringInline()): String { + return arg +} + +inline fun testCompilationInline(arg: String = getStringInline()): String { + return arg +} + +fun box(): String { + var result = testCompilation() + if (result != "OK") return "fail1: ${result}" + + result = testCompilation("OKOK") + if (result != "OKOK") return "fail2: ${result}" + + + result = testCompilationInline() + if (result != "OK") return "fail3: ${result}" + + result = testCompilationInline("OKOK") + if (result != "OKOK") return "fail4: ${result}" + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inlineMultiFile/cases/inlineInDefaultParameter/inlineInDefaultParameter.2.kt b/js/js.translator/testData/inlineMultiFile/cases/inlineInDefaultParameter/inlineInDefaultParameter.2.kt new file mode 100644 index 00000000000..497ba36fe0d --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/inlineInDefaultParameter/inlineInDefaultParameter.2.kt @@ -0,0 +1,10 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/defaultValues/inlineInDefaultParameter.2.kt + */ + +package test + +inline fun getStringInline(): String { + return "OK" +} diff --git a/js/js.translator/testData/inlineMultiFile/cases/inlineMultiFileSimple/inlineMultiFileSimple.1.kt b/js/js.translator/testData/inlineMultiFile/cases/inlineMultiFileSimple/inlineMultiFileSimple.1.kt new file mode 100644 index 00000000000..5e3f196a89b --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/inlineMultiFileSimple/inlineMultiFileSimple.1.kt @@ -0,0 +1,5 @@ +package foo + +inline fun sum(a: Int, b: Int): Int { + return a + b +} \ No newline at end of file diff --git a/js/js.translator/testData/inlineMultiFile/cases/inlineMultiFileSimple/inlineMultiFileSimple.2.kt b/js/js.translator/testData/inlineMultiFile/cases/inlineMultiFileSimple/inlineMultiFileSimple.2.kt new file mode 100644 index 00000000000..f8d08c07031 --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/inlineMultiFileSimple/inlineMultiFileSimple.2.kt @@ -0,0 +1,10 @@ +package foo + +// CHECK_NOT_CALLED: sum + +fun box(): String { + val sum3 = sum(1, 2) + assertEquals(3, sum3) + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inlineMultiFile/cases/lambdaCloning/lambdaCloning.1.kt b/js/js.translator/testData/inlineMultiFile/cases/lambdaCloning/lambdaCloning.1.kt new file mode 100644 index 00000000000..47e25b318d2 --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/lambdaCloning/lambdaCloning.1.kt @@ -0,0 +1,26 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/lambdaTransformation/lambdaCloning.1.kt + */ + +package foo + +import test.* + +fun test1(s: Long): String { + return doSmth(s) +} + +fun test2(s: Int): String { + return doSmth2(s) +} + +fun box(): String { + var result = test1(11) + if (result != "11") return "fail1: ${result}" + + result = test2(11) + if (result != "11") return "fail2: ${result}" + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inlineMultiFile/cases/lambdaCloning/lambdaCloning.2.kt b/js/js.translator/testData/inlineMultiFile/cases/lambdaCloning/lambdaCloning.2.kt new file mode 100644 index 00000000000..173256cea35 --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/lambdaCloning/lambdaCloning.2.kt @@ -0,0 +1,14 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/lambdaTransformation/lambdaCloning.2.kt + */ + +package test + +inline fun doSmth(a: T) : String { + return {a.toString()}() +} + +inline fun doSmth2(a: T) : String { + return {{a.toString()}()}() +} \ No newline at end of file diff --git a/js/js.translator/testData/inlineMultiFile/cases/lambdaInLambda2/lambdaInLambda2.1.kt b/js/js.translator/testData/inlineMultiFile/cases/lambdaInLambda2/lambdaInLambda2.1.kt new file mode 100644 index 00000000000..b4e2980d313 --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/lambdaInLambda2/lambdaInLambda2.1.kt @@ -0,0 +1,28 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/lambdaTransformation/lambdaInLambda2.1.kt + */ + +package foo + +import test.* + +fun test1(prefix: String): String { + var result = "fail" + mfun { + concat("start") { + if (it.startsWith(prefix)) { + result = "OK" + } + } + } + + return result +} + +fun box(): String { + if (test1("start") != "OK") return "fail1" + if (test1("nostart") != "fail") return "fail2" + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inlineMultiFile/cases/lambdaInLambda2/lambdaInLambda2.2.kt b/js/js.translator/testData/inlineMultiFile/cases/lambdaInLambda2/lambdaInLambda2.2.kt new file mode 100644 index 00000000000..4baeb7d41ef --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/lambdaInLambda2/lambdaInLambda2.2.kt @@ -0,0 +1,14 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/lambdaTransformation/lambdaInLambda2.2.kt + */ + +package test + +inline fun mfun(f: () -> R) { + f() +} + +fun concat(suffix: String, l: (s: String) -> Unit) { + l(suffix) +} \ No newline at end of file diff --git a/js/js.translator/testData/inlineMultiFile/cases/lambdaInLambdaNoInline/lambdaInLambdaNoInline.1.kt b/js/js.translator/testData/inlineMultiFile/cases/lambdaInLambdaNoInline/lambdaInLambdaNoInline.1.kt new file mode 100644 index 00000000000..e250835183c --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/lambdaInLambdaNoInline/lambdaInLambdaNoInline.1.kt @@ -0,0 +1,61 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/lambdaTransformation/lambdaInLambdaNoInline.1.kt + */ + +package foo + +import test.* +import kotlin.InlineOption.* + +fun test1(param: String): String { + var result = "fail1" + noInlineFun(param) { a -> + concat("start") { + result = doSmth(a).toString() + } + } + + return result +} + +fun test11(param: String): String { + var result = "fail1" + noInlineFun("stub") { a -> + concat("start") { + result = doSmth(param).toString() + } + } + + return result +} + +inline fun test2(inlineOptions(ONLY_LOCAL_RETURN) param: () -> String): String { + var result = "fail1" + noInlineFun("stub") { a -> + concat(param()) { + result = doSmth(param()).toString() + } + } + + return result +} + +inline fun test22(inlineOptions(ONLY_LOCAL_RETURN) param: () -> String): String { + var result = "fail1" + {{result = param()}()}() + + return result +} + + +fun box(): String { + if (test1("start") != "start") return "fail1: ${test1("start")}" + if (test1("nostart") != "nostart") return "fail2: ${test1("nostart")}" + if (test11("start") != "start") return "fail3: ${test11("start")}" + + if (test2({"start"}) != "start") return "fail4: ${test2({"start"})}" + if (test22({"start"}) != "start") return "fail5: ${test22({"start"})}" + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inlineMultiFile/cases/lambdaInLambdaNoInline/lambdaInLambdaNoInline.2.kt b/js/js.translator/testData/inlineMultiFile/cases/lambdaInLambdaNoInline/lambdaInLambdaNoInline.2.kt new file mode 100644 index 00000000000..ac30fb5f8a4 --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/lambdaInLambdaNoInline/lambdaInLambdaNoInline.2.kt @@ -0,0 +1,18 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/lambdaTransformation/lambdaInLambdaNoInline.2.kt + */ + +package test + +fun concat(suffix: String, l: (s: String) -> Unit) { + l(suffix) +} + +fun noInlineFun(arg: T, f: (T) -> Unit) { + f(arg) +} + +inline fun doSmth(a: String): String { + return a.toString() +} diff --git a/js/js.translator/testData/inlineMultiFile/cases/regeneratedLambdaName/regeneratedLambdaName.1.kt b/js/js.translator/testData/inlineMultiFile/cases/regeneratedLambdaName/regeneratedLambdaName.1.kt new file mode 100644 index 00000000000..ec992aa3bad --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/regeneratedLambdaName/regeneratedLambdaName.1.kt @@ -0,0 +1,30 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/lambdaTransformation/regeneratedLambdaName.1.kt + */ + +package foo + +import test.* + +fun sameName(s: Long): Long { + return call { + s + } +} + +fun sameName(s: Int): Int { + return call { + s + } +} + +fun box(): String { + val result = sameName(1) + if (result != 1) return "fail1: ${result}" + + val result2 = sameName(2) + if (result2 != 2) return "fail2: ${result2}" + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inlineMultiFile/cases/regeneratedLambdaName/regeneratedLambdaName.2.kt b/js/js.translator/testData/inlineMultiFile/cases/regeneratedLambdaName/regeneratedLambdaName.2.kt new file mode 100644 index 00000000000..b69e784594f --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/regeneratedLambdaName/regeneratedLambdaName.2.kt @@ -0,0 +1,12 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/lambdaTransformation/regeneratedLambdaName.2.kt + */ + +package test + +import kotlin.InlineOption.* + +inline fun call(inlineOptions(ONLY_LOCAL_RETURN) f: () -> R) : R { + return {f()} () +} diff --git a/js/js.translator/testData/inlineMultiFile/cases/sameCaptured/sameCaptured.1.kt b/js/js.translator/testData/inlineMultiFile/cases/sameCaptured/sameCaptured.1.kt new file mode 100644 index 00000000000..8591e98ec9f --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/sameCaptured/sameCaptured.1.kt @@ -0,0 +1,30 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/lambdaTransformation/sameCaptured.1.kt + */ + +package foo + +import test.* +import kotlin.InlineOption.* + +fun testSameCaptured() : String { + var result = 0; + result = doWork({result+=1; result}, {result += 11; result}) + return if (result == 12) "OK" else "fail ${result}" +} + +inline fun testSameCaptured(inlineOptions(ONLY_LOCAL_RETURN) lambdaWithResultCaptured: () -> Unit) : String { + var result = 1; + result = doWork({result+=11; lambdaWithResultCaptured(); result}) + return if (result == 12) "OK" else "fail ${result}" +} + +fun box(): String { + if (testSameCaptured() != "OK") return "test1 : ${testSameCaptured()}" + + var result = 0; + if (testSameCaptured{result += 1111} != "OK") return "test2 : ${testSameCaptured{result = 1111}}" + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inlineMultiFile/cases/sameCaptured/sameCaptured.2.kt b/js/js.translator/testData/inlineMultiFile/cases/sameCaptured/sameCaptured.2.kt new file mode 100644 index 00000000000..20031727211 --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/sameCaptured/sameCaptured.2.kt @@ -0,0 +1,23 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/lambdaTransformation/sameCaptured.2.kt + */ + +package test + +import kotlin.InlineOption.* + +inline fun doWork(inlineOptions(ONLY_LOCAL_RETURN) job: ()-> R) : R { + val k = 10; + return notInline({k; job()}) +} + +inline fun doWork(inlineOptions(ONLY_LOCAL_RETURN) job: ()-> R, inlineOptions(ONLY_LOCAL_RETURN) job2: () -> R) : R { + val k = 10; + return notInline({k; job(); job2()}) +} + +fun notInline(job: ()-> R) : R { + return job() +} + diff --git a/js/js.translator/testData/inlineMultiFile/cases/simpleCapturingInClass/simpleCapturingInClass.1.kt b/js/js.translator/testData/inlineMultiFile/cases/simpleCapturingInClass/simpleCapturingInClass.1.kt new file mode 100644 index 00000000000..c186499db43 --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/simpleCapturingInClass/simpleCapturingInClass.1.kt @@ -0,0 +1,77 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/capture/simpleCapturingInClass.1.kt + */ + +package foo + +fun testAll(): String { + val inlineX = InlineAll() + + return inlineX.inline({(a1: Int, a2: Double, a3: Double, a4: String, a5: Long) -> + "" + a1 + a2 + a3 + a4 + a5}, + 1, 12.5, 13.5, "14", 15) +} + +fun testAllWithCapturedVal(): String { + val inlineX = InlineAll() + + val c1 = 21 + val c2 = 22.5 + val c3 = 23.5 + val c4 = "24" + val c5 = 25 + val c6 = 'H' + val c7 = 26 + val c8 = 27 + val c9 = 28.5 + + return inlineX.inline({(a1: Int, a2: Double, a3: Double, a4: String, a5: Long) -> + "" + a1 + a2 + a3 + a4 + a5 + c1 + c2 + c3 + c4 + c5 + c6 + c7 + c8 + c9}, + 1, 12.5, 13.5, "14", 15) +} + +fun testAllWithCapturedVar(): String { + val inlineX = InlineAll() + + var c1 = 21 + var c2 = 22.5 + var c3 = 23.5 + var c4 = "24" + var c5 = 25 + var c6 = 'H' + var c7 = 26 + var c8 = 27 + val c9 = 28.5 + + return inlineX.inline({(a1: Int, a2: Double, a3: Double, a4: String, a5: Long) -> + "" + a1 + a2 + a3 + a4 + a5 + c1 + c2 + c3 + c4 + c5 + c6 + c7 + c8 + c9}, + 1, 12.5, 13.5, "14", 15) +} + +fun testAllWithCapturedValAndVar(): String { + val inlineX = InlineAll() + + var c1 = 21 + var c2 = 22.5 + val c3 = 23.5 + val c4 = "24" + var c5 = 25 + val c6 = 'H' + var c7 = 26 + var c8 = 27 + val c9 = 28.5 + + return inlineX.inline({(a1: Int, a2: Double, a3: Double, a4: String, a5: Long) -> + "" + a1 + a2 + a3 + a4 + a5 + c1 + c2 + c3 + c4 + c5 + c6 + c7 + c8 + c9}, + 1, 12.5, 13.5, "14", 15) +} + + +fun box(): String { + if (testAll() != "112.513.51415") return "testAll: ${testAll()}" + if (testAllWithCapturedVal() != "112.513.514152122.523.52425H262728.5") return "testAllWithCapturedVal: ${testAllWithCapturedVal()}" + if (testAllWithCapturedVar() != "112.513.514152122.523.52425H262728.5") return "testAllWithCapturedVar: ${testAllWithCapturedVar()}" + if (testAllWithCapturedValAndVar() != "112.513.514152122.523.52425H262728.5") return "testAllWithCapturedVal: ${testAllWithCapturedValAndVar()}" + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inlineMultiFile/cases/simpleCapturingInClass/simpleCapturingInClass.2.kt b/js/js.translator/testData/inlineMultiFile/cases/simpleCapturingInClass/simpleCapturingInClass.2.kt new file mode 100644 index 00000000000..d1132045ff5 --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/simpleCapturingInClass/simpleCapturingInClass.2.kt @@ -0,0 +1,14 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/capture/simpleCapturingInClass.2.kt + */ + +package foo + +class InlineAll { + + inline fun inline(s: (Int, Double, Double, String, Long) -> String, + a1: Int, a2: Double, a3: Double, a4: String, a5: Long): String { + return s(a1, a2, a3, a4, a5) + } +} \ No newline at end of file diff --git a/js/js.translator/testData/inlineMultiFile/cases/simpleCapturingInPackage/simpleCapturingInPackage.1.kt b/js/js.translator/testData/inlineMultiFile/cases/simpleCapturingInPackage/simpleCapturingInPackage.1.kt new file mode 100644 index 00000000000..75ced4a06d3 --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/simpleCapturingInPackage/simpleCapturingInPackage.1.kt @@ -0,0 +1,69 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/capture/simpleCapturingInPackage.1.kt + */ + +package foo + +fun testAll(): String { + return inline({(a1: Int, a2: Double, a3: Double, a4: String, a5: Long) -> + "" + a1 + a2 + a3 + a4 + a5}, + 1, 12.5, 13.5, "14", 15) +} + +fun testAllWithCapturedVal(): String { + val c1 = 21 + val c2 = 22.5 + val c3 = 23.5 + val c4 = "24" + val c5 = 25 + val c6 = 'H' + val c7 = 26 + val c8 = 27 + val c9 = 28.5 + + return inline({(a1: Int, a2: Double, a3: Double, a4: String, a5: Long) -> + "" + a1 + a2 + a3 + a4 + a5 + c1 + c2 + c3 + c4 + c5 + c6 + c7 + c8 + c9}, + 1, 12.5, 13.5, "14", 15) +} + +fun testAllWithCapturedVar(): String { + var c1 = 21 + var c2 = 22.5 + var c3 = 23.5 + var c4 = "24" + var c5 = 25 + var c6 = 'H' + var c7 = 26 + var c8 = 27 + val c9 = 28.5 + + return inline({(a1: Int, a2: Double, a3: Double, a4: String, a5: Long) -> + "" + a1 + a2 + a3 + a4 + a5 + c1 + c2 + c3 + c4 + c5 + c6 + c7 + c8 + c9}, + 1, 12.5, 13.5, "14", 15) +} + +fun testAllWithCapturedValAndVar(): String { + var c1 = 21 + var c2 = 22.5 + val c3 = 23.5 + val c4 = "24" + var c5 = 25 + val c6 = 'H' + var c7 = 26 + var c8 = 27 + val c9 = 28.5 + + return inline({(a1: Int, a2: Double, a3: Double, a4: String, a5: Long) -> + "" + a1 + a2 + a3 + a4 + a5 + c1 + c2 + c3 + c4 + c5 + c6 + c7 + c8 + c9}, + 1, 12.5, 13.5, "14", 15) +} + + +fun box(): String { + if (testAll() != "112.513.51415") return "testAll: ${testAll()}" + if (testAllWithCapturedVal() != "112.513.514152122.523.52425H262728.5") return "testAllWithCapturedVal: ${testAllWithCapturedVal()}" + if (testAllWithCapturedVar() != "112.513.514152122.523.52425H262728.5") return "testAllWithCapturedVar: ${testAllWithCapturedVar()}" + if (testAllWithCapturedValAndVar() != "112.513.514152122.523.52425H262728.5") return "testAllWithCapturedVal: ${testAllWithCapturedValAndVar()}" + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inlineMultiFile/cases/simpleCapturingInPackage/simpleCapturingInPackage.2.kt b/js/js.translator/testData/inlineMultiFile/cases/simpleCapturingInPackage/simpleCapturingInPackage.2.kt new file mode 100644 index 00000000000..bd4ce0ac63a --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/simpleCapturingInPackage/simpleCapturingInPackage.2.kt @@ -0,0 +1,11 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/capture/simpleCapturingInPackage.2.kt + */ + +package foo + +inline fun inline(s: (Int, Double, Double, String, Long) -> String, + a1: Int, a2: Double, a3: Double, a4: String, a5: Long): String { + return s(a1, a2, a3, a4, a5) +} diff --git a/js/js.translator/testData/inlineMultiFile/cases/simpleDefaultMethod/simpleDefaultMethod.1.kt b/js/js.translator/testData/inlineMultiFile/cases/simpleDefaultMethod/simpleDefaultMethod.1.kt new file mode 100644 index 00000000000..5cc579821ee --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/simpleDefaultMethod/simpleDefaultMethod.1.kt @@ -0,0 +1,29 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/defaultValues/simpleDefaultMethod.1.kt + */ + +package foo + +import test.* + +fun testCompilation(): String { + emptyFun() + emptyFun("K") + + return "OK" +} + +fun simple(): String { + return simpleFun() + simpleFun("K") +} + +fun box(): String { + var result = testCompilation() + if (result != "OK") return "fail1: ${result}" + + result = simple() + if (result != "OK") return "fail2: ${result}" + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inlineMultiFile/cases/simpleDefaultMethod/simpleDefaultMethod.2.kt b/js/js.translator/testData/inlineMultiFile/cases/simpleDefaultMethod/simpleDefaultMethod.2.kt new file mode 100644 index 00000000000..594a6bca219 --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/simpleDefaultMethod/simpleDefaultMethod.2.kt @@ -0,0 +1,16 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/defaultValues/simpleDefaultMethod.2.kt + */ + +package test + +inline fun emptyFun(arg: String = "O") { + +} + +inline fun simpleFun(arg: String = "O"): String { + val r = arg; + return r; +} + diff --git a/js/js.translator/testData/inlineMultiFile/cases/trait/trait.1.kt b/js/js.translator/testData/inlineMultiFile/cases/trait/trait.1.kt new file mode 100644 index 00000000000..a5328c83b8a --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/trait/trait.1.kt @@ -0,0 +1,32 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/trait/trait.1.kt + */ + +package foo + +import test.* + +// CHECK_CONTAINS_NO_CALLS: testFinalInline +// CHECK_CONTAINS_NO_CALLS: testFinalInline2 +// CHECK_CONTAINS_NO_CALLS: testClassObject + +fun testFinalInline(): String { + return Z().finalInline({"final"}) +} + +fun testFinalInline2(instance: InlineTrait): String { + return instance.finalInline({"final2"}) +} + +fun testClassObject(): String { + return InlineTrait.finalInline({"classobject"}) +} + +fun box(): String { + if (testFinalInline() != "final") return "test1: ${testFinalInline()}" + if (testFinalInline2(Z()) != "final2") return "test2: ${testFinalInline2(Z())}" + if (testClassObject() != "classobject") return "test3: ${testClassObject()}" + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inlineMultiFile/cases/trait/trait.2.kt b/js/js.translator/testData/inlineMultiFile/cases/trait/trait.2.kt new file mode 100644 index 00000000000..08a8ecdd25c --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/trait/trait.2.kt @@ -0,0 +1,23 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/trait/trait.2.kt + */ + +package test + +trait InlineTrait { + + inline final fun finalInline(s: () -> String): String { + return s() + } + + class object { + inline final fun finalInline(s: () -> String): String { + return s() + } + } +} + +class Z: InlineTrait { + +} \ No newline at end of file diff --git a/js/js.translator/testData/inlineMultiFile/cases/tryCatch/tryCatch.1.kt b/js/js.translator/testData/inlineMultiFile/cases/tryCatch/tryCatch.1.kt new file mode 100644 index 00000000000..e9e702deab2 --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/tryCatch/tryCatch.1.kt @@ -0,0 +1,60 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/tryCatchFinally/tryCatch.1.kt + */ + +package foo + +fun test1() : Int { + val inlineX = My(111) + var result = 0 + val res = inlineX.perform{ + + try { + throw RuntimeException() + } catch (e: RuntimeException) { + result = -1 + } + result + } + + return result +} + +fun test11() : Int { + val inlineX = My(111) + val res = inlineX.perform{ + try { + throw RuntimeException() + } catch (e: RuntimeException) { + -1 + } + } + + return res +} + +fun test2() : Int { + try { + val inlineX = My(111) + var result = 0 + val res = inlineX.perform{ + try { + throw RuntimeExceptionWithValue("-1") + } catch (e: RuntimeException) { + throw RuntimeExceptionWithValue("-2") + } + } + return result + } catch (e: RuntimeExceptionWithValue) { + return e.value.toInt2()!! + } +} + +fun box(): String { + if (test1() != -1) return "test1: ${test1()}" + if (test11() != -1) return "test11: ${test11()}" + if (test2() != -2) return "test2: ${test2()}" + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inlineMultiFile/cases/tryCatch/tryCatch.2.kt b/js/js.translator/testData/inlineMultiFile/cases/tryCatch/tryCatch.2.kt new file mode 100644 index 00000000000..cddd8dec7af --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/tryCatch/tryCatch.2.kt @@ -0,0 +1,16 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/tryCatchFinally/tryCatch.2.kt + */ + +package foo + +class My(val value: Int) + +inline fun T.perform(job: (T)-> R) : R { + return job(this) +} + +inline fun String.toInt2() : Int = parseInt(this) + +class RuntimeExceptionWithValue(val value: String) : RuntimeException() \ No newline at end of file diff --git a/js/js.translator/testData/inlineMultiFile/cases/tryCatch2/tryCatch2.1.kt b/js/js.translator/testData/inlineMultiFile/cases/tryCatch2/tryCatch2.1.kt new file mode 100644 index 00000000000..084d7644d2f --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/tryCatch2/tryCatch2.1.kt @@ -0,0 +1,114 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/tryCatchFinally/tryCatch2.1.kt + */ + +package foo + +fun test1(): Int { + val res = My(111).performWithFail( + { + throw RuntimeExceptionWithValue() + }, { + it.value + }) + return res +} + +fun test11(): Int { + val res = My(111).performWithFail2( + { + try { + throw RuntimeExceptionWithValue("1") + } catch (e: RuntimeExceptionWithValue) { + throw RuntimeExceptionWithValue("2") + } + }, + {(ex, thizz) -> + if (ex.value == "2") { + thizz.value + } else { + -11111 + } + }) + return res +} + +fun test2(): Int { + val res = My(111).performWithFail( + { + it.value + }, + { + it.value + 1 + }) + return res +} + +fun test22(): Int { + val res = My(111).performWithFail2( + { + try { + throw RuntimeExceptionWithValue("1") + } catch (e: RuntimeExceptionWithValue) { + it.value + 111 + } + }, + {(ex, thizz) -> + -11111 + }) + + return res +} + + +fun test3(): Int { + try { + val res = My(111).performWithFail( + { + throw RuntimeExceptionWithValue("-1") + }, { + throw RuntimeExceptionWithValue("-2") + }) + return res + } catch (e: RuntimeExceptionWithValue) { + return e.value.toInt2()!! + } +} + +fun test33(): Int { + try { + val res = My(111).performWithFail2( + { + try { + throw RuntimeExceptionWithValue("-1") + } catch (e: RuntimeExceptionWithValue) { + throw RuntimeExceptionWithValue("-2") + } + }, + {(ex, thizz) -> + if (ex.value == "-2") { + throw RuntimeExceptionWithValue("-3") + } else { + -11111 + } + }) + return res + } catch (e: RuntimeExceptionWithValue) { + return e.value.toInt2()!! + } +} + +fun box(): String { + if (test1() != 111) return "test1: ${test1()}" + if (test11() != 111) return "test11: ${test11()}" + + if (test2() != 111) return "test2: ${test2()}" + if (test22() != 111) return "test22: ${test22()}" + + if (test3() != -2) return "test3: ${test3()}" + if (test33() != -3) return "test33: ${test33()}" + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inlineMultiFile/cases/tryCatch2/tryCatch2.2.kt b/js/js.translator/testData/inlineMultiFile/cases/tryCatch2/tryCatch2.2.kt new file mode 100644 index 00000000000..ad1968fb0b3 --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/tryCatch2/tryCatch2.2.kt @@ -0,0 +1,32 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/tryCatchFinally/tryCatch2.2.kt + */ + +package foo + +class My(val value: Int) + +inline fun T.performWithFail(job: (T)-> R, failJob: (T) -> R): R { + try { + return job(this) + } catch (e: RuntimeExceptionWithValue) { + return failJob(this) + } +} + +inline fun T.performWithFail2(job: (T)-> R, failJob: (e: RuntimeExceptionWithValue, T) -> R): R { + try { + return job(this) + } catch (e: RuntimeExceptionWithValue) { + return failJob(e, this) + } +} + +native object Number { + fun parseInt(str: String): Int = noImpl +} + +inline fun String.toInt2(): Int = parseInt(this) + +class RuntimeExceptionWithValue(val value: String = "") : RuntimeException() \ No newline at end of file diff --git a/js/js.translator/testData/inlineMultiFile/cases/tryCatchFinally/tryCatchFinally.1.kt b/js/js.translator/testData/inlineMultiFile/cases/tryCatchFinally/tryCatchFinally.1.kt new file mode 100644 index 00000000000..ac8d9766fde --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/tryCatchFinally/tryCatchFinally.1.kt @@ -0,0 +1,80 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/tryCatchFinally/tryCatchFinally.1.kt + */ + +package foo + +fun test1(): Int { + + var res = My(111).performWithFinally( + { + 1 + }, { + it.value + }) + return res +} + +fun test11(): Int { + var result = -1; + val res = My(111).performWithFinally( + { + try { + result = it.value + throw RuntimeException("1") + } catch (e: RuntimeException) { + ++result + throw RuntimeException("2") + } + }, + { + ++result + }) + return res +} + +fun test2(): Int { + var res = My(111).performWithFinally( + { + throw RuntimeException("1") + }, + { + it.value + }) + + + return res +} + +fun test3(): Int { + try { + var result = -1; + val res = My(111).performWithFailFinally( + { + result = it.value; + throw RuntimeException("-1") + }, + { (e, z)-> + ++result + throw RuntimeException("-2") + }, + { + ++result + }) + return res + } catch (e: RuntimeException) { + return e.getMessage()?.toInt2()!! + } +} + +fun box(): String { + if (test1() != 111) return "test1: ${test1()}" + if (test11() != 113) return "test11: ${test11()}" + + if (test2() != 111) return "test2: ${test2()}" + + if (test3() != 113) return "test3: ${test3()}" + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inlineMultiFile/cases/tryCatchFinally/tryCatchFinally.2.kt b/js/js.translator/testData/inlineMultiFile/cases/tryCatchFinally/tryCatchFinally.2.kt new file mode 100644 index 00000000000..e2a10bc78da --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/tryCatchFinally/tryCatchFinally.2.kt @@ -0,0 +1,25 @@ + + +package foo + +class My(val value: Int) + +inline fun T.performWithFinally(job: (T)-> R, finallyFun: (T) -> R) : R { + try { + return job(this) + } finally { + return finallyFun(this) + } +} + +inline fun T.performWithFailFinally(job: (T)-> R, failJob : (e: RuntimeException, T) -> R, finallyFun: (T) -> R) : R { + try { + return job(this) + } catch (e: RuntimeException) { + return failJob(e, this) + } finally { + return finallyFun(this) + } +} + +inline fun String.toInt2() : Int = parseInt(this) \ No newline at end of file diff --git a/js/js.translator/testData/inlineMultiFile/cases/use/use.1.kt b/js/js.translator/testData/inlineMultiFile/cases/use/use.1.kt new file mode 100644 index 00000000000..24495802fa1 --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/use/use.1.kt @@ -0,0 +1,28 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/complex/use.1.kt + */ + +package foo + +import test.* + +fun Data.test1(d: Data) : Int { + val input2 = Input(this) + val input = Input(this) + return input.use{ + val output = Output(d) + output.use{ + input.copyTo(output, 10) + } + } +} + + +fun box(): String { + + val result = Data().test1(Data()) + if (result != 100) return "test1: ${result}" + + return "OK" +} diff --git a/js/js.translator/testData/inlineMultiFile/cases/use/use.2.kt b/js/js.translator/testData/inlineMultiFile/cases/use/use.2.kt new file mode 100644 index 00000000000..35715359e72 --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/use/use.2.kt @@ -0,0 +1,46 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/complex/use.2.kt + */ + +package test + +public class Data() + +public data class Input(val d: Data) : Closeable { + public fun data() : Int = 100 +} + +public class Output(val d: Data) : Closeable { + public fun doOutput(data: Int): Int = data +} + +public open trait Closeable { + open public fun close() {} +} + +public fun Input.copyTo(output: Output, size: Int): Int { + return output.doOutput(this.data()) +} + +public inline fun T.use(block: (T)-> R) : R { + var closed = false + try { + return block(this) + } catch (e: Exception) { + closed = true + try { + this.close() + } catch (closeException: Exception) { + + } + throw e + } finally { + if (!closed) { + this.close() + } + } +} + + + diff --git a/js/js.translator/testData/inlineMultiFile/cases/with/with.1.kt b/js/js.translator/testData/inlineMultiFile/cases/with/with.1.kt new file mode 100644 index 00000000000..31db0e5e534 --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/with/with.1.kt @@ -0,0 +1,49 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/complex/with.1.kt + */ + +package foo + +import test.* + +fun Data.test1(d: Data) : Int { + val input = Input(this) + var result = 10 + with(input) { + result = use{ + val output = Output(d) + use{ + data() + copyTo(output, 10) + } + } + } + return result +} + +fun Data.test2(d: Data) : Int { + val input = Input(this) + var result = 10 + with2(input) { + result = use{ + val output = Output(d) + useNoInline{ + data() + copyTo(output, 10) + } + } + } + return result +} + +fun box(): String { + + val result = Data().test1(Data()) + if (result != 100) return "test1: ${result}" + + val result2 = Data().test2(Data()) + if (result2 != 100) return "test2: ${result2}" + + return "OK" +} diff --git a/js/js.translator/testData/inlineMultiFile/cases/with/with.2.kt b/js/js.translator/testData/inlineMultiFile/cases/with/with.2.kt new file mode 100644 index 00000000000..f70ef2700fd --- /dev/null +++ b/js/js.translator/testData/inlineMultiFile/cases/with/with.2.kt @@ -0,0 +1,38 @@ +/* + * Copy of JVM-backend test + * Found at: compiler/testData/codegen/boxInline/complex/with.2.kt + */ + +package test + +import kotlin.InlineOption.* + +public class Data() + +public class Input(val d: Data) : Closeable { + public fun data() : Int = 100 +} +public class Output(val d: Data) : Closeable { + public fun doOutput(data: Int): Int = data +} + +public open trait Closeable { + open public fun close() {} +} + +public inline fun use(block: ()-> R) : R { + return block() +} + +public fun useNoInline(block: ()-> R) : R { + return block() +} + + +public fun Input.copyTo(output: Output, size: Int): Int { + return output.doOutput(this.data()) +} + +public inline fun with(receiver: T, f: T.() -> R): R = receiver.f() + +public inline fun with2(receiver : T, inlineOptions(ONLY_LOCAL_RETURN) body : T.() -> Unit) : Unit = {receiver.body()}()