Tests for JVM back-end support of tail-call optimization

This commit is contained in:
Sergey Mashkov
2013-11-26 17:33:06 +04:00
committed by Andrey Breslav
parent 9da3d2f051
commit fb0ec573e0
26 changed files with 749 additions and 1 deletions
@@ -0,0 +1,13 @@
tailRecursive fun test(x : Int = 0, e : Any = "a") {
if (!e.equals("a")) {
throw IllegalArgumentException()
}
if (x > 0) {
test(x - 1)
}
}
fun box() : String {
test(100000)
return "OK"
}
@@ -0,0 +1,10 @@
tailRecursive fun test(counter : Int, a : Any) : Int? {
if (counter < 0) return null
if (counter == 0) return 777
return test(-1, "no tail") ?: test(-2, "no tail") ?: test(counter - 1, "tail")
}
fun box() : String =
if (test(100000, "test") == 777) "OK"
else "FAIL"
@@ -0,0 +1,25 @@
class B {
inner class C {
tailRecursive fun h(counter : Int, x : Any) {
if (counter > 0) {
this@C.h(counter - 1, "tail")
}
}
tailRecursive fun h2(x : Any) {
this@B.h2("no recursion") // keep vigilance
}
}
fun makeC() : C = C()
fun h2(x : Any) {
}
}
fun box() : String {
B().makeC().h(1000000, "test")
B().makeC().h2(0)
return "OK"
}
@@ -0,0 +1,14 @@
tailRecursive fun test(x : Int, a : Any) : Int {
var z = if (x > 3) 3 else x
while (z > 0) {
if (z > 10) {
return test(x - 1, "tail")
}
test(0, "no tail")
z = z - 1
}
return 1
}
fun box() : String = if (test(100000, "test") == 1) "OK" else "FAIL"
@@ -0,0 +1,15 @@
tailRecursive fun test(x : Int, a : Any) : Int {
if (x == 1) {
if (x != 1) {
test(0, "no tail")
return test(0, "tail")
} else {
return test(x + test(0, "no tail"), "tail")
}
} else if (x > 0) {
return test(x - 1, "tail")
}
return -1
}
fun box() : String = if (test(1000000, "test") == -1) "OK" else "FAIL"
@@ -0,0 +1,11 @@
tailRecursive fun <T, A> Iterator<T>.foldl(acc : A, foldFunction : (e : T, acc : A) -> A) : A =
if (!hasNext()) acc
else foldl(foldFunction(next(), acc), foldFunction)
fun box() : String {
val sum = (1..1000000).iterator().foldl(0) { (e : Int, acc : Long) ->
acc + e
}
return if (sum == 500000500000) "OK" else "FAIL: $sum"
}
@@ -0,0 +1,16 @@
fun escapeChar(c : Char) : String? = when (c) {
'\\' -> "\\\\"
'\n' -> "\\n"
'"' -> "\\\""
else -> "" + c
}
tailRecursive fun String.escape(i : Int = 0, result : StringBuilder = StringBuilder()) : String =
if (i == length) result.toString()
else escape(i + 1, result.append(escapeChar(get(i))))
fun box() : String {
"test me not \\".escape()
return "OK"
}
@@ -0,0 +1,8 @@
tailRecursive fun String.repeat(num : Int, acc : StringBuilder = StringBuilder()) : String =
if (num == 0) acc.toString()
else repeat(num - 1, acc.append(this)!!)
fun box() : String {
val s = "a".repeat(10000)
return if (s.length == 10000) "OK" else "FAIL: ${s.length}"
}
@@ -0,0 +1,11 @@
fun test() {
[tailRecursive] fun g3(counter : Int, x : Any) {
if (counter > 0) { g3(counter - 1, "tail") }
}
g3(1000000, "test")
}
fun box() : String {
test()
return "OK"
}
@@ -0,0 +1,11 @@
tailRecursive fun test(counter : Int, a : Any) : Int {
if (counter == 0) return 0
try {
throw Exception()
} catch (e : Exception) {
return test(counter - 1, "no tail")
}
}
fun box() : String = if (test(3, "test") == 0) "OK" else "FAIL"
@@ -0,0 +1,11 @@
tailRecursive fun test(counter : Int, a : Any) : Int {
if (counter == 0) return 0
try {
// do nothing
} finally {
return test(counter - 1, "no tail")
}
}
fun box() : String = if (test(3, "test") == 0) "OK" else "FAIL"
@@ -0,0 +1,15 @@
tailRecursive fun test(counter : Int, a : Any) : Int {
if (counter == 0) return 0
try {
// do nothing
} finally {
if (counter > 0) {
return test(counter - 1, "no tail")
}
}
return -1
}
fun box() : String = if (test(3, "test") == 0) "OK" else "FAIL"
@@ -0,0 +1,11 @@
tailRecursive fun test(counter : Int, a : Any) : Int {
if (counter == 0) return 0
try {
return test(counter - 1, "no tail")
} catch (any : Throwable) {
return -1
}
}
fun box() : String = if (test(3, "test") == 0) "OK" else "FAIL"
@@ -0,0 +1,11 @@
tailRecursive fun test(x : Int, a : Any) : Int =
if (x == 1) {
test(x - 1, "no tail")
1 + test(x - 1, "no tail")
} else if (x > 0) {
test(x - 1, "tail")
} else {
0
}
fun box() : String = if (test(1000000, "test") == 1) "OK" else "FAIL"
@@ -0,0 +1,11 @@
tailRecursive fun test(x : Int, z : Any) : Int {
if (x == 10) {
return 1 + test(x - 1, "no tail")
}
if (x > 0) {
return test(x - 1, "tail")
}
return 0
}
fun box() : String = if (test(1000000, "test") == 1) "OK" else "FAIL"
@@ -0,0 +1,12 @@
tailRecursive fun test(x : Int, a : Any) : Int {
if (x == 0) {
return 0
} else if (x == 10) {
test(0, "no tail")
return 1 + test(x - 1, "no tail")
} else {
return test(x - 1, "tail")
}
}
fun box() : String = if (test(1000000, "test") == 1) "OK" else "FAIL"
@@ -0,0 +1,23 @@
class A {
tailRecursive fun f1(c : Int, x : Any) {
if (c > 0) {
this.f1(c - 1, "tail")
}
}
tailRecursive fun f2(c : Int, x : Any) {
if (c > 0) {
f2(c - 1, "tail 108")
}
}
tailRecursive fun f3(a : A, x : Any) {
a.f3(a, "no tail") // non-tail recursion, could be potentially resolved by condition if (a == this) f3() else a.f3()
}
}
fun box() : String {
A().f1(1000000, "test")
A().f2(1000000, "test")
return "OK"
}
@@ -0,0 +1,21 @@
tailRecursive fun test(x : Int, e : Any) : Unit {
if (x == 1) {
test(x - 1, "tail")
} else if (x == 2) {
test(x - 1, "tail")
return
} else if (x == 3) {
test(x - 1, "no tail")
if (x == 3) {
test(x - 1, "tail")
}
return
} else if (x > 0) {
test(x - 1, "tail")
}
}
fun box() : String {
test(1000000, "test")
return "OK"
}
@@ -0,0 +1,8 @@
tailRecursive fun withWhen(counter : Int, x : Any) : Int =
when (counter) {
0 -> counter
50 -> 1 + withWhen(counter - 1, "no tail")
else -> withWhen(counter - 1, "tail")
}
fun box() : String = if (withWhen(100000, "test") == 1) "OK" else "FAIL"
@@ -0,0 +1,11 @@
tailRecursive fun withWhen(counter : Int, d : Any, x : Any) : Int =
when (counter) {
0 -> counter
1, 2 -> withWhen(counter - 1, "1,2", "tail")
in 3..49 -> withWhen(counter - 1, "3..49", "tail")
50 -> 1 + withWhen(counter - 1, "50", "no tail")
!in 0..50 -> withWhen(counter - 1, "!0..50", "tail")
else -> withWhen(counter - 1, "else", "tail")
}
fun box() : String = if (withWhen(100000, "test", "test") == 1) "OK" else "FAIL"
@@ -0,0 +1,15 @@
tailRecursive fun withWhen(counter : Int, d : Any, x : Any) : Int =
if (counter == 0) {
0
}
else if (counter == 5) {
withWhen(counter - 1, 999, "tail")
}
else
when (d) {
is String -> withWhen(counter - 1, "is String", "tail")
is Number -> withWhen(counter, "is Number", "tail")
else -> throw IllegalStateException()
}
fun box() : String = if (withWhen(100000, "test", "test") == 0) "OK" else "FAIL"
@@ -0,0 +1,9 @@
tailRecursive fun withWhen2(counter : Int, x : Any) : Int =
when {
counter == 0 -> counter
counter == 50 -> 1 + withWhen2(counter - 1, "no tail")
withWhen2(0, "no tail") == 0 -> withWhen2(counter - 1, "tail")
else -> 1
}
fun box() : String = if (withWhen2(100000, "test") == 1) "OK" else "FAIL"
@@ -0,0 +1,180 @@
/*
* Copyright 2010-2013 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.jet.checkers;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.Predicates;
import com.google.common.collect.Lists;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.ConfigurationKind;
import org.jetbrains.jet.cli.jvm.compiler.CliLightClassGenerationSupport;
import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment;
import org.jetbrains.jet.lang.resolve.calls.TailRecursionKind;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.AnalyzerScriptParameter;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
import org.jetbrains.jet.lang.resolve.java.AnalyzerFacadeForJVM;
import org.jetbrains.jet.lang.resolve.lazy.KotlinTestWithEnvironment;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public abstract class AbstractTailRecursionTest extends KotlinTestWithEnvironment {
@Override
protected JetCoreEnvironment createEnvironment() {
return createEnvironmentWithMockJdk(ConfigurationKind.JDK_AND_ANNOTATIONS);
}
public void doTest(@NotNull String testFile) throws IOException {
JetFile file = JetPsiFactory.createFile(getProject(), FileUtil.loadFile(new File(testFile), true));
List<JetFile> files = new ArrayList<JetFile>(Collections.singleton(file));
final BindingTrace trace = CliLightClassGenerationSupport.getInstanceForCli(getProject()).getTrace();
assertNotNull("No binding trace found for test", trace);
AnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(
getProject(), files, trace,
Collections.<AnalyzerScriptParameter>emptyList(), Predicates.<PsiFile>alwaysTrue(), false).getBindingContext();
file.acceptChildren(new JetTreeVisitor<Data>() {
@Override
public Void visitNamedFunction(@NotNull JetNamedFunction function, @Nullable Data outerData) {
SimpleFunctionDescriptor descriptor = trace.get(BindingContext.FUNCTION, function);
assert descriptor != null : "can't get function descriptor from binding by function declaration node";
Data data = new Data(descriptor);
super.visitNamedFunction(function, data);
if (data.isTail) {
List<JetCallExpression> calls = trace.get(BindingContext.FUNCTION_RECURSIVE_CALL_EXPRESSIONS, descriptor);
if (calls == null) {
calls = Collections.emptyList();
}
List<JetCallExpression> detectedRecursions = new ArrayList<JetCallExpression>(calls);
List<JetCallExpression> expectedRecursions = new ArrayList<JetCallExpression>(data.visitedCalls);
Collections.sort(detectedRecursions, new CallComparator());
Collections.sort(expectedRecursions, new CallComparator());
assertEquals(
"Bad detected tail recursions list for " + descriptor,
stringListOfCallExpressions(expectedRecursions),
stringListOfCallExpressions(detectedRecursions)
);
}
return null;
}
@Override
public Void visitCallExpression(@NotNull JetCallExpression expression, @Nullable Data data) {
if (data != null && data.isTail) {
ResolvedCall<? extends CallableDescriptor> call =
trace.get(BindingContext.RESOLVED_CALL, expression.getCalleeExpression());
assert call != null : "call node is not yet resolved";
if (data.functionDescriptor.equals(call.getCandidateDescriptor())) {
JetValueArgumentList argumentList = expression.getValueArgumentList();
assert argumentList != null : "function call have no arguments list";
checkCall(data.functionDescriptor, expression, argumentList, trace);
data.visitedCalls.add(expression);
}
}
super.visitCallExpression(expression, data);
return null;
}
}, null);
}
private static String stringListOfCallExpressions(List<JetCallExpression> expectedRecursions) {
return Joiner.on(",\n").skipNulls().join(Lists.transform(expectedRecursions, new CallExpressionToText()));
}
private static class Data {
public final SimpleFunctionDescriptor functionDescriptor;
public final boolean isTail;
public final List<JetCallExpression> visitedCalls = new ArrayList<JetCallExpression>();
private Data(@NotNull SimpleFunctionDescriptor descriptor) {
functionDescriptor = descriptor;
isTail = KotlinBuiltIns.getInstance().isTailRecursive(descriptor);
}
}
private static void checkCall(
SimpleFunctionDescriptor functionDescriptor,
JetCallExpression expression,
JetValueArgumentList argumentList,
BindingTrace trace
) {
int size = argumentList.getArguments().size();
boolean shouldBeTail = size == 0 || isLastArgumentTail(argumentList.getArguments());
TailRecursionKind status = trace.get(BindingContext.TAIL_RECURSION_CALL, expression);
assertNotNull("Call is not checked for tail recursion", status);
assertEquals("Tail-recursion detection failed for " + functionDescriptor.getName().asString() + " at " + expression.getText(),
shouldBeTail, status.isDoGenerateTailRecursion());
}
private static boolean isLastArgumentTail(List<JetValueArgument> arguments) {
JetValueArgument lastArgument = arguments.get(arguments.size() - 1);
JetExpression expression = lastArgument.getArgumentExpression();
if (expression instanceof JetStringTemplateExpression) {
JetStringTemplateEntry[] entries = ((JetStringTemplateExpression) expression).getEntries();
StringBuilder sb = new StringBuilder();
for (JetStringTemplateEntry entry : entries) {
sb.append(entry.getText());
}
return !sb.toString().trim().equals("no tail");
}
return true;
}
private static class CallComparator implements Comparator<JetCallExpression> {
@Override
public int compare(@NotNull JetCallExpression o1, @NotNull JetCallExpression o2) {
return o1.getTextOffset() - o2.getTextOffset();
}
}
private static class CallExpressionToText implements Function<JetCallExpression, String> {
@Override
public String apply(JetCallExpression input) {
if (input == null) return null;
return ("\"" + input.getText().replace("\"", "\\\"").trim() + "\"");
}
}
}
@@ -0,0 +1,149 @@
/*
* Copyright 2010-2013 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.jet.checkers;
import junit.framework.Assert;
import junit.framework.Test;
import junit.framework.TestSuite;
import java.io.File;
import java.util.regex.Pattern;
import org.jetbrains.jet.JetTestUtils;
import org.jetbrains.jet.test.InnerTestClasses;
import org.jetbrains.jet.test.TestMetadata;
import org.jetbrains.jet.checkers.AbstractTailRecursionTest;
/** This class is generated by {@link org.jetbrains.jet.generators.tests.GenerateTests}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("compiler/testData/codegen/box/functions/tail-recursion")
public class TailRecursionDetectorTestGenerated extends AbstractTailRecursionTest {
public void testAllFilesPresentInTail_recursion() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/codegen/box/functions/tail-recursion"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("defaultArgs.kt")
public void testDefaultArgs() throws Exception {
doTest("compiler/testData/codegen/box/functions/tail-recursion/defaultArgs.kt");
}
@TestMetadata("insideElvis.kt")
public void testInsideElvis() throws Exception {
doTest("compiler/testData/codegen/box/functions/tail-recursion/insideElvis.kt");
}
@TestMetadata("labeledThisReferences.kt")
public void testLabeledThisReferences() throws Exception {
doTest("compiler/testData/codegen/box/functions/tail-recursion/labeledThisReferences.kt");
}
@TestMetadata("loops.kt")
public void testLoops() throws Exception {
doTest("compiler/testData/codegen/box/functions/tail-recursion/loops.kt");
}
@TestMetadata("multilevelBlocks.kt")
public void testMultilevelBlocks() throws Exception {
doTest("compiler/testData/codegen/box/functions/tail-recursion/multilevelBlocks.kt");
}
@TestMetadata("realIteratorFoldl.kt")
public void testRealIteratorFoldl() throws Exception {
doTest("compiler/testData/codegen/box/functions/tail-recursion/realIteratorFoldl.kt");
}
@TestMetadata("realStringEscape.kt")
public void testRealStringEscape() throws Exception {
doTest("compiler/testData/codegen/box/functions/tail-recursion/realStringEscape.kt");
}
@TestMetadata("realStringRepeat.kt")
public void testRealStringRepeat() throws Exception {
doTest("compiler/testData/codegen/box/functions/tail-recursion/realStringRepeat.kt");
}
@TestMetadata("recursiveInnerFunction.kt")
public void testRecursiveInnerFunction() throws Exception {
doTest("compiler/testData/codegen/box/functions/tail-recursion/recursiveInnerFunction.kt");
}
@TestMetadata("returnInCatch.kt")
public void testReturnInCatch() throws Exception {
doTest("compiler/testData/codegen/box/functions/tail-recursion/returnInCatch.kt");
}
@TestMetadata("returnInFinally.kt")
public void testReturnInFinally() throws Exception {
doTest("compiler/testData/codegen/box/functions/tail-recursion/returnInFinally.kt");
}
@TestMetadata("returnInIfInFinally.kt")
public void testReturnInIfInFinally() throws Exception {
doTest("compiler/testData/codegen/box/functions/tail-recursion/returnInIfInFinally.kt");
}
@TestMetadata("returnInTry.kt")
public void testReturnInTry() throws Exception {
doTest("compiler/testData/codegen/box/functions/tail-recursion/returnInTry.kt");
}
@TestMetadata("simpleBlock.kt")
public void testSimpleBlock() throws Exception {
doTest("compiler/testData/codegen/box/functions/tail-recursion/simpleBlock.kt");
}
@TestMetadata("simpleReturn.kt")
public void testSimpleReturn() throws Exception {
doTest("compiler/testData/codegen/box/functions/tail-recursion/simpleReturn.kt");
}
@TestMetadata("simpleReturnWithElse.kt")
public void testSimpleReturnWithElse() throws Exception {
doTest("compiler/testData/codegen/box/functions/tail-recursion/simpleReturnWithElse.kt");
}
@TestMetadata("thisReferences.kt")
public void testThisReferences() throws Exception {
doTest("compiler/testData/codegen/box/functions/tail-recursion/thisReferences.kt");
}
@TestMetadata("unitBlocks.kt")
public void testUnitBlocks() throws Exception {
doTest("compiler/testData/codegen/box/functions/tail-recursion/unitBlocks.kt");
}
@TestMetadata("whenWithCondition.kt")
public void testWhenWithCondition() throws Exception {
doTest("compiler/testData/codegen/box/functions/tail-recursion/whenWithCondition.kt");
}
@TestMetadata("whenWithInRange.kt")
public void testWhenWithInRange() throws Exception {
doTest("compiler/testData/codegen/box/functions/tail-recursion/whenWithInRange.kt");
}
@TestMetadata("whenWithIs.kt")
public void testWhenWithIs() throws Exception {
doTest("compiler/testData/codegen/box/functions/tail-recursion/whenWithIs.kt");
}
@TestMetadata("whenWithoutCondition.kt")
public void testWhenWithoutCondition() throws Exception {
doTest("compiler/testData/codegen/box/functions/tail-recursion/whenWithoutCondition.kt");
}
}
@@ -2361,7 +2361,7 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
}
@TestMetadata("compiler/testData/codegen/box/functions")
@InnerTestClasses({Functions.Invoke.class, Functions.LocalFunctions.class})
@InnerTestClasses({Functions.Invoke.class, Functions.LocalFunctions.class, Functions.Tail_recursion.class})
public static class Functions extends AbstractBlackBoxCodegenTest {
public void testAllFilesPresentInFunctions() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/codegen/box/functions"), Pattern.compile("^(.+)\\.kt$"), true);
@@ -2623,11 +2623,130 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
}
@TestMetadata("compiler/testData/codegen/box/functions/tail-recursion")
public static class Tail_recursion extends AbstractBlackBoxCodegenTest {
public void testAllFilesPresentInTail_recursion() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/codegen/box/functions/tail-recursion"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("defaultArgs.kt")
public void testDefaultArgs() throws Exception {
doTest("compiler/testData/codegen/box/functions/tail-recursion/defaultArgs.kt");
}
@TestMetadata("insideElvis.kt")
public void testInsideElvis() throws Exception {
doTest("compiler/testData/codegen/box/functions/tail-recursion/insideElvis.kt");
}
@TestMetadata("labeledThisReferences.kt")
public void testLabeledThisReferences() throws Exception {
doTest("compiler/testData/codegen/box/functions/tail-recursion/labeledThisReferences.kt");
}
@TestMetadata("loops.kt")
public void testLoops() throws Exception {
doTest("compiler/testData/codegen/box/functions/tail-recursion/loops.kt");
}
@TestMetadata("multilevelBlocks.kt")
public void testMultilevelBlocks() throws Exception {
doTest("compiler/testData/codegen/box/functions/tail-recursion/multilevelBlocks.kt");
}
@TestMetadata("realIteratorFoldl.kt")
public void testRealIteratorFoldl() throws Exception {
doTest("compiler/testData/codegen/box/functions/tail-recursion/realIteratorFoldl.kt");
}
@TestMetadata("realStringEscape.kt")
public void testRealStringEscape() throws Exception {
doTest("compiler/testData/codegen/box/functions/tail-recursion/realStringEscape.kt");
}
@TestMetadata("realStringRepeat.kt")
public void testRealStringRepeat() throws Exception {
doTest("compiler/testData/codegen/box/functions/tail-recursion/realStringRepeat.kt");
}
@TestMetadata("recursiveInnerFunction.kt")
public void testRecursiveInnerFunction() throws Exception {
doTest("compiler/testData/codegen/box/functions/tail-recursion/recursiveInnerFunction.kt");
}
@TestMetadata("returnInCatch.kt")
public void testReturnInCatch() throws Exception {
doTest("compiler/testData/codegen/box/functions/tail-recursion/returnInCatch.kt");
}
@TestMetadata("returnInFinally.kt")
public void testReturnInFinally() throws Exception {
doTest("compiler/testData/codegen/box/functions/tail-recursion/returnInFinally.kt");
}
@TestMetadata("returnInIfInFinally.kt")
public void testReturnInIfInFinally() throws Exception {
doTest("compiler/testData/codegen/box/functions/tail-recursion/returnInIfInFinally.kt");
}
@TestMetadata("returnInTry.kt")
public void testReturnInTry() throws Exception {
doTest("compiler/testData/codegen/box/functions/tail-recursion/returnInTry.kt");
}
@TestMetadata("simpleBlock.kt")
public void testSimpleBlock() throws Exception {
doTest("compiler/testData/codegen/box/functions/tail-recursion/simpleBlock.kt");
}
@TestMetadata("simpleReturn.kt")
public void testSimpleReturn() throws Exception {
doTest("compiler/testData/codegen/box/functions/tail-recursion/simpleReturn.kt");
}
@TestMetadata("simpleReturnWithElse.kt")
public void testSimpleReturnWithElse() throws Exception {
doTest("compiler/testData/codegen/box/functions/tail-recursion/simpleReturnWithElse.kt");
}
@TestMetadata("thisReferences.kt")
public void testThisReferences() throws Exception {
doTest("compiler/testData/codegen/box/functions/tail-recursion/thisReferences.kt");
}
@TestMetadata("unitBlocks.kt")
public void testUnitBlocks() throws Exception {
doTest("compiler/testData/codegen/box/functions/tail-recursion/unitBlocks.kt");
}
@TestMetadata("whenWithCondition.kt")
public void testWhenWithCondition() throws Exception {
doTest("compiler/testData/codegen/box/functions/tail-recursion/whenWithCondition.kt");
}
@TestMetadata("whenWithInRange.kt")
public void testWhenWithInRange() throws Exception {
doTest("compiler/testData/codegen/box/functions/tail-recursion/whenWithInRange.kt");
}
@TestMetadata("whenWithIs.kt")
public void testWhenWithIs() throws Exception {
doTest("compiler/testData/codegen/box/functions/tail-recursion/whenWithIs.kt");
}
@TestMetadata("whenWithoutCondition.kt")
public void testWhenWithoutCondition() throws Exception {
doTest("compiler/testData/codegen/box/functions/tail-recursion/whenWithoutCondition.kt");
}
}
public static Test innerSuite() {
TestSuite suite = new TestSuite("Functions");
suite.addTestSuite(Functions.class);
suite.addTestSuite(Invoke.class);
suite.addTestSuite(LocalFunctions.class);
suite.addTestSuite(Tail_recursion.class);
return suite;
}
}
@@ -22,6 +22,7 @@ import org.jetbrains.jet.cfg.AbstractControlFlowTest;
import org.jetbrains.jet.checkers.AbstractDiagnosticsTestWithEagerResolve;
import org.jetbrains.jet.checkers.AbstractJetJsCheckerTest;
import org.jetbrains.jet.checkers.AbstractJetPsiCheckerTest;
import org.jetbrains.jet.checkers.AbstractTailRecursionTest;
import org.jetbrains.jet.cli.AbstractKotlincExecutableTest;
import org.jetbrains.jet.codegen.AbstractBytecodeTextTest;
import org.jetbrains.jet.codegen.AbstractCheckLocalVariablesTableTest;
@@ -220,6 +221,13 @@ public class GenerateTests {
testModel("compiler/testData/renderer")
);
generateTest(
"compiler/tests",
"TailRecursionDetectorTestGenerated",
AbstractTailRecursionTest.class,
testModel("compiler/testData/codegen/box/functions/tail-recursion")
);
generateTest("compiler/tests",
"LazyResolveTestGenerated",
AbstractLazyResolveTest.class,