Use codegen box tests for tail calls as diagnostic tests too

This commit is contained in:
Andrey Breslav
2013-11-26 21:49:17 +04:00
parent bb6ceffbbb
commit 94500bd968
22 changed files with 197 additions and 37 deletions
@@ -1,8 +1,10 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
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")
return <!NON_TAIL_RECURSIVE_CALL!>test<!>(-1, "no tail") ?: <!NON_TAIL_RECURSIVE_CALL!>test<!>(-2, "no tail") ?: test(counter - 1, "tail")
}
fun box() : String =
@@ -1,3 +1,5 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
class B {
inner class C {
tailRecursive fun h(counter : Int, x : Any) {
@@ -6,7 +8,7 @@ class B {
}
}
tailRecursive fun h2(x : Any) {
<!NO_TAIL_CALLS_FOUND!>tailRecursive fun h2(x : Any)<!> {
this@B.h2("no recursion") // keep vigilance
}
@@ -1,10 +1,12 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
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")
<!NON_TAIL_RECURSIVE_CALL!>test<!>(0, "no tail")
z = z - 1
}
@@ -1,10 +1,12 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
tailRecursive fun test(x : Int, a : Any) : Int {
if (x == 1) {
if (x != 1) {
test(0, "no tail")
<!NON_TAIL_RECURSIVE_CALL!>test<!>(0, "no tail")
return test(0, "tail")
} else {
return test(x + test(0, "no tail"), "tail")
return test(x + <!NON_TAIL_RECURSIVE_CALL!>test<!>(0, "no tail"), "tail")
}
} else if (x > 0) {
return test(x - 1, "tail")
@@ -1,6 +1,6 @@
tailRecursive fun String.repeat(num : Int, acc : StringBuilder = StringBuilder()) : String =
if (num == 0) acc.toString()
else repeat(num - 1, acc.append(this)!!)
else repeat(num - 1, acc.append(this))
fun box() : String {
val s = "a".repeat(10000)
@@ -1,3 +1,5 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
fun test() {
[tailRecursive] fun g3(counter : Int, x : Any) {
if (counter > 0) { g3(counter - 1, "tail") }
@@ -1,10 +1,12 @@
tailRecursive fun test(counter : Int, a : Any) : Int {
// !DIAGNOSTICS: -UNUSED_PARAMETER
<!NO_TAIL_CALLS_FOUND!>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")
return <!TAIL_RECURSION_IN_TRY_IS_NOT_SUPPORTED!>test<!>(counter - 1, "no tail")
}
}
@@ -1,10 +1,12 @@
tailRecursive fun test(counter : Int, a : Any) : Int {
// !DIAGNOSTICS: -UNUSED_PARAMETER
<!NO_TAIL_CALLS_FOUND!>tailRecursive fun test(counter : Int, a : Any) : Int<!> {
if (counter == 0) return 0
try {
// do nothing
} finally {
return test(counter - 1, "no tail")
return <!TAIL_RECURSION_IN_TRY_IS_NOT_SUPPORTED!>test<!>(counter - 1, "no tail")
}
}
@@ -1,11 +1,13 @@
tailRecursive fun test(counter : Int, a : Any) : Int {
// !DIAGNOSTICS: -UNUSED_PARAMETER
<!NO_TAIL_CALLS_FOUND!>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 <!TAIL_RECURSION_IN_TRY_IS_NOT_SUPPORTED!>test<!>(counter - 1, "no tail")
}
}
@@ -1,8 +1,10 @@
tailRecursive fun test(counter : Int, a : Any) : Int {
// !DIAGNOSTICS: -UNUSED_PARAMETER
<!NO_TAIL_CALLS_FOUND!>tailRecursive fun test(counter : Int, a : Any) : Int<!> {
if (counter == 0) return 0
try {
return test(counter - 1, "no tail")
return <!TAIL_RECURSION_IN_TRY_IS_NOT_SUPPORTED!>test<!>(counter - 1, "no tail")
} catch (any : Throwable) {
return -1
}
@@ -1,7 +1,9 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
tailRecursive fun test(x : Int, a : Any) : Int =
if (x == 1) {
test(x - 1, "no tail")
1 + test(x - 1, "no tail")
<!NON_TAIL_RECURSIVE_CALL!>test<!>(x - 1, "no tail")
1 + <!NON_TAIL_RECURSIVE_CALL!>test<!>(x - 1, "no tail")
} else if (x > 0) {
test(x - 1, "tail")
} else {
@@ -1,6 +1,8 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
tailRecursive fun test(x : Int, z : Any) : Int {
if (x == 10) {
return 1 + test(x - 1, "no tail")
return 1 + <!NON_TAIL_RECURSIVE_CALL!>test<!>(x - 1, "no tail")
}
if (x > 0) {
return test(x - 1, "tail")
@@ -1,9 +1,11 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
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")
<!NON_TAIL_RECURSIVE_CALL!>test<!>(0, "no tail")
return 1 + <!NON_TAIL_RECURSIVE_CALL!>test<!>(x - 1, "no tail")
} else {
return test(x - 1, "tail")
}
@@ -1,3 +1,5 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
class A {
tailRecursive fun f1(c : Int, x : Any) {
if (c > 0) {
@@ -11,8 +13,8 @@ class A {
}
}
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()
<!NO_TAIL_CALLS_FOUND!>tailRecursive fun f3(a : A, x : Any)<!> {
a.<!NON_TAIL_RECURSIVE_CALL!>f3<!>(a, "no tail") // non-tail recursion, could be potentially resolved by condition if (a == this) f3() else a.f3()
}
}
@@ -1,3 +1,5 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
tailRecursive fun test(x : Int, e : Any) : Unit {
if (x == 1) {
test(x - 1, "tail")
@@ -5,7 +7,7 @@ tailRecursive fun test(x : Int, e : Any) : Unit {
test(x - 1, "tail")
return
} else if (x == 3) {
test(x - 1, "no tail")
<!NON_TAIL_RECURSIVE_CALL!>test<!>(x - 1, "no tail")
if (x == 3) {
test(x - 1, "tail")
}
@@ -1,7 +1,9 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
tailRecursive fun withWhen(counter : Int, x : Any) : Int =
when (counter) {
0 -> counter
50 -> 1 + withWhen(counter - 1, "no tail")
50 -> 1 + <!NON_TAIL_RECURSIVE_CALL!>withWhen<!>(counter - 1, "no tail")
else -> withWhen(counter - 1, "tail")
}
@@ -1,9 +1,11 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
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")
50 -> 1 + <!NON_TAIL_RECURSIVE_CALL!>withWhen<!>(counter - 1, "50", "no tail")
!in 0..50 -> withWhen(counter - 1, "!0..50", "tail")
else -> withWhen(counter - 1, "else", "tail")
}
@@ -1,3 +1,5 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
tailRecursive fun withWhen(counter : Int, d : Any, x : Any) : Int =
if (counter == 0) {
0
@@ -1,8 +1,10 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
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")
counter == 50 -> 1 + <!NON_TAIL_RECURSIVE_CALL!>withWhen2<!>(counter - 1, "no tail")
<!NON_TAIL_RECURSIVE_CALL!>withWhen2<!>(0, "no tail") == 0 -> withWhen2(counter - 1, "tail")
else -> 1
}
@@ -30,7 +30,7 @@ import org.jetbrains.jet.checkers.AbstractDiagnosticsTestWithEagerResolve;
/** This class is generated by {@link org.jetbrains.jet.generators.tests.GenerateTests}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@InnerTestClasses({JetDiagnosticsTestGenerated.Tests.class, JetDiagnosticsTestGenerated.Script.class})
@InnerTestClasses({JetDiagnosticsTestGenerated.Tests.class, JetDiagnosticsTestGenerated.Script.class, JetDiagnosticsTestGenerated.TailRecursion.class})
public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEagerResolve {
@TestMetadata("compiler/testData/diagnostics/tests")
@InnerTestClasses({Tests.Annotations.class, Tests.BackingField.class, Tests.CallableReference.class, Tests.Cast.class, Tests.CheckArguments.class, Tests.ClassObjects.class, Tests.ControlFlowAnalysis.class, Tests.ControlStructures.class, Tests.DataClasses.class, Tests.DataFlow.class, Tests.DataFlowInfoTraversal.class, Tests.DeclarationChecks.class, Tests.DelegatedProperty.class, Tests.Deparenthesize.class, Tests.Enum.class, Tests.Evaluate.class, Tests.Extensions.class, Tests.FunctionLiterals.class, Tests.Generics.class, Tests.IncompleteCode.class, Tests.Inference.class, Tests.Infos.class, Tests.Inline.class, Tests.Inner.class, Tests.J_k.class, Tests.Jdk_annotations.class, Tests.Library.class, Tests.NullabilityAndAutoCasts.class, Tests.NullableTypes.class, Tests.Numbers.class, Tests.Objects.class, Tests.OperatorsOverloading.class, Tests.Overload.class, Tests.Override.class, Tests.Recovery.class, Tests.Redeclarations.class, Tests.Regressions.class, Tests.Resolve.class, Tests.Scopes.class, Tests.SenselessComparison.class, Tests.Shadowing.class, Tests.SmartCasts.class, Tests.Substitutions.class, Tests.Subtyping.class, Tests.Suppress.class, Tests.TailCalls.class, Tests.ThisAndSuper.class, Tests.Varargs.class, Tests.When.class})
@@ -6787,10 +6787,139 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
}
@TestMetadata("compiler/testData/codegen/box/functions/tailRecursion")
public static class TailRecursion extends AbstractDiagnosticsTestWithEagerResolve {
public void testAllFilesPresentInTailRecursion() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/codegen/box/functions/tailRecursion"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("defaultArgs.kt")
public void testDefaultArgs() throws Exception {
doTest("compiler/testData/codegen/box/functions/tailRecursion/defaultArgs.kt");
}
@TestMetadata("infixCall.kt")
public void testInfixCall() throws Exception {
doTest("compiler/testData/codegen/box/functions/tailRecursion/infixCall.kt");
}
@TestMetadata("insideElvis.kt")
public void testInsideElvis() throws Exception {
doTest("compiler/testData/codegen/box/functions/tailRecursion/insideElvis.kt");
}
@TestMetadata("labeledThisReferences.kt")
public void testLabeledThisReferences() throws Exception {
doTest("compiler/testData/codegen/box/functions/tailRecursion/labeledThisReferences.kt");
}
@TestMetadata("loops.kt")
public void testLoops() throws Exception {
doTest("compiler/testData/codegen/box/functions/tailRecursion/loops.kt");
}
@TestMetadata("multilevelBlocks.kt")
public void testMultilevelBlocks() throws Exception {
doTest("compiler/testData/codegen/box/functions/tailRecursion/multilevelBlocks.kt");
}
@TestMetadata("realIteratorFoldl.kt")
public void testRealIteratorFoldl() throws Exception {
doTest("compiler/testData/codegen/box/functions/tailRecursion/realIteratorFoldl.kt");
}
@TestMetadata("realStringEscape.kt")
public void testRealStringEscape() throws Exception {
doTest("compiler/testData/codegen/box/functions/tailRecursion/realStringEscape.kt");
}
@TestMetadata("realStringRepeat.kt")
public void testRealStringRepeat() throws Exception {
doTest("compiler/testData/codegen/box/functions/tailRecursion/realStringRepeat.kt");
}
@TestMetadata("recursiveInnerFunction.kt")
public void testRecursiveInnerFunction() throws Exception {
doTest("compiler/testData/codegen/box/functions/tailRecursion/recursiveInnerFunction.kt");
}
@TestMetadata("returnIf.kt")
public void testReturnIf() throws Exception {
doTest("compiler/testData/codegen/box/functions/tailRecursion/returnIf.kt");
}
@TestMetadata("returnInCatch.kt")
public void testReturnInCatch() throws Exception {
doTest("compiler/testData/codegen/box/functions/tailRecursion/returnInCatch.kt");
}
@TestMetadata("returnInFinally.kt")
public void testReturnInFinally() throws Exception {
doTest("compiler/testData/codegen/box/functions/tailRecursion/returnInFinally.kt");
}
@TestMetadata("returnInIfInFinally.kt")
public void testReturnInIfInFinally() throws Exception {
doTest("compiler/testData/codegen/box/functions/tailRecursion/returnInIfInFinally.kt");
}
@TestMetadata("returnInTry.kt")
public void testReturnInTry() throws Exception {
doTest("compiler/testData/codegen/box/functions/tailRecursion/returnInTry.kt");
}
@TestMetadata("simpleBlock.kt")
public void testSimpleBlock() throws Exception {
doTest("compiler/testData/codegen/box/functions/tailRecursion/simpleBlock.kt");
}
@TestMetadata("simpleReturn.kt")
public void testSimpleReturn() throws Exception {
doTest("compiler/testData/codegen/box/functions/tailRecursion/simpleReturn.kt");
}
@TestMetadata("simpleReturnWithElse.kt")
public void testSimpleReturnWithElse() throws Exception {
doTest("compiler/testData/codegen/box/functions/tailRecursion/simpleReturnWithElse.kt");
}
@TestMetadata("thisReferences.kt")
public void testThisReferences() throws Exception {
doTest("compiler/testData/codegen/box/functions/tailRecursion/thisReferences.kt");
}
@TestMetadata("unitBlocks.kt")
public void testUnitBlocks() throws Exception {
doTest("compiler/testData/codegen/box/functions/tailRecursion/unitBlocks.kt");
}
@TestMetadata("whenWithCondition.kt")
public void testWhenWithCondition() throws Exception {
doTest("compiler/testData/codegen/box/functions/tailRecursion/whenWithCondition.kt");
}
@TestMetadata("whenWithInRange.kt")
public void testWhenWithInRange() throws Exception {
doTest("compiler/testData/codegen/box/functions/tailRecursion/whenWithInRange.kt");
}
@TestMetadata("whenWithIs.kt")
public void testWhenWithIs() throws Exception {
doTest("compiler/testData/codegen/box/functions/tailRecursion/whenWithIs.kt");
}
@TestMetadata("whenWithoutCondition.kt")
public void testWhenWithoutCondition() throws Exception {
doTest("compiler/testData/codegen/box/functions/tailRecursion/whenWithoutCondition.kt");
}
}
public static Test suite() {
TestSuite suite = new TestSuite("JetDiagnosticsTestGenerated");
suite.addTest(Tests.innerSuite());
suite.addTestSuite(Script.class);
suite.addTestSuite(TailRecursion.class);
return suite;
}
}
@@ -22,6 +22,7 @@ import com.intellij.openapi.util.Pair;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.JetTestCaseBuilder;
import org.jetbrains.jet.JetTestUtils;
import org.jetbrains.jet.checkers.CheckerTestUtil;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.AnalyzerScriptParameter;
import org.jetbrains.jet.lang.resolve.name.Name;
@@ -99,7 +100,8 @@ public class CodegenTestFiles {
}
@NotNull
public static CodegenTestFiles create(@NotNull String fileName, @NotNull String content, @NotNull Project project) {
public static CodegenTestFiles create(@NotNull String fileName, @NotNull String contentWithDiagnosticMarkup, @NotNull Project project) {
String content = CheckerTestUtil.parseDiagnosedRanges(contentWithDiagnosticMarkup, new ArrayList<CheckerTestUtil.DiagnosedRange>());
JetFile file = JetTestUtils.createFile(fileName, content, project);
List<Pair<String, String>> expectedValues = Lists.newArrayList();
@@ -22,7 +22,6 @@ 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;
@@ -98,7 +97,8 @@ public class GenerateTests {
"JetDiagnosticsTestGenerated",
AbstractDiagnosticsTestWithEagerResolve.class,
testModel("compiler/testData/diagnostics/tests"),
testModel("compiler/testData/diagnostics/tests/script", true, "ktscript", "doTest")
testModel("compiler/testData/diagnostics/tests/script", true, "ktscript", "doTest"),
testModel("compiler/testData/codegen/box/functions/tailRecursion")
);
generateTest(
@@ -221,13 +221,6 @@ public class GenerateTests {
testModel("compiler/testData/renderer")
);
generateTest(
"compiler/tests",
"TailRecursionDetectorTestGenerated",
AbstractTailRecursionTest.class,
testModel("compiler/testData/codegen/box/functions/tailRecursion")
);
generateTest("compiler/tests",
"LazyResolveTestGenerated",
AbstractLazyResolveTest.class,