From d4d7946e6a995291c4f61530ebad6dd44e9f87f2 Mon Sep 17 00:00:00 2001 From: Dmitry Savvinov Date: Tue, 3 Oct 2017 17:06:44 +0300 Subject: [PATCH] Effects: add diagnostic tests on functions from stdlib ========== Introduction of EffectSystem: 18/18 --- .../contracts/fromStdlib/check.kt | 28 +++++ .../contracts/fromStdlib/check.txt | 7 ++ .../contracts/fromStdlib/fromStandardKt.kt | 110 ++++++++++++++++++ .../contracts/fromStdlib/fromStandardKt.txt | 15 +++ .../contracts/fromStdlib/isNullOrBlank.kt | 20 ++++ .../contracts/fromStdlib/isNullOrBlank.txt | 4 + .../contracts/fromStdlib/isNullOrEmpty.kt | 20 ++++ .../contracts/fromStdlib/isNullOrEmpty.txt | 4 + .../contracts/fromStdlib/require.kt | 27 +++++ .../contracts/fromStdlib/require.txt | 7 ++ .../DiagnosticsTestWithStdLibGenerated.java | 39 +++++++ ...ticsTestWithStdLibUsingJavacGenerated.java | 39 +++++++ 12 files changed, 320 insertions(+) create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/check.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/check.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/fromStandardKt.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/fromStandardKt.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/isNullOrBlank.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/isNullOrBlank.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/isNullOrEmpty.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/isNullOrEmpty.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/require.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/require.txt diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/check.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/check.kt new file mode 100644 index 00000000000..afe41b0b24e --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/check.kt @@ -0,0 +1,28 @@ +// !LANGUAGE: +ReturnsEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +fun testCheckSmartcast(x: Any?) { + check(x is String) + x.length +} + +fun testCheckUnreachableCode() { + check(false) + // Can't be reported without notion of 'iff' + println("Can't get here!") +} + +fun testCheckWithMessage(x: Any?) { + check(x is String) { "x is not String!" } + x.length +} + +fun testCheckWithFailingMessage(x: Any?) { + check(x is String) { throw kotlin.IllegalStateException("What a strange idea") } + x.length +} + +fun tesCheckNotNullWithMessage(x: Int?) { + checkNotNull(x) { "x is null!"} + x.inc() +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/check.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/check.txt new file mode 100644 index 00000000000..e62fe7822c1 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/check.txt @@ -0,0 +1,7 @@ +package + +public fun tesCheckNotNullWithMessage(/*0*/ x: kotlin.Int?): kotlin.Unit +public fun testCheckSmartcast(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun testCheckUnreachableCode(): kotlin.Unit +public fun testCheckWithFailingMessage(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun testCheckWithMessage(/*0*/ x: kotlin.Any?): kotlin.Unit diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/fromStandardKt.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/fromStandardKt.kt new file mode 100644 index 00000000000..727286e3f73 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/fromStandardKt.kt @@ -0,0 +1,110 @@ +// !LANGUAGE: +CallsInPlaceEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +fun testRunWithUnitReturn() { + val x: Int + run { x = 42 } + println(x) +} + +fun testRunWithReturnValue() { + val x: Int + val y = run { + x = 42 + "hello" + } + println(x) + println(y) +} + +fun testRunWithCoercionToUnit() { + val x: Int + run { + x = 42 + "hello" + } +} + +fun testRunWithReceiver(x: Int) { + val s: String + x.run { + s = this.toString() + } + println(s) +} + +fun testWith(x: Int) { + val s: String + with(x) { + s = toString() + } + println(s) +} + +fun testApply(x: Int) { + val y: Int + val z: Int = x.apply { y = 42 } + println(y) + println(z) +} + +fun testAlso(x: Int) { + val y: Int + x.also { y = it + 1 } + println(y) +} + +fun testLet(x: Int) { + val z: Int + val y: String = x.let { + z = 42 + (it + 1).toString() + } + println(z) + println(y) +} + +fun testTakeIf(x: Int?) { + val y: Int + x.takeIf { + y = 42 + it != null + } + println(y) +} + +fun testTakeUnless(x: Int?) { + val y: Int + x.takeIf { + y = 42 + it != null + } + println(y) +} + +fun testRepeatOnVal(x: Int) { + val y: Int + repeat(x) { + // reassignment instead of captured val initalization + y = 42 + } + println(y) +} + +fun testRepeatOnVar(x: Int) { + var y: Int + repeat(x) { + // no reassignment reported + y = 42 + } + // but here we still unsure if 'y' was initialized + println(y) +} + +fun testRepeatOnInitializedVar(x: Int) { + var y: Int = 24 + repeat(x) { + y = 42 + } + println(y) +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/fromStandardKt.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/fromStandardKt.txt new file mode 100644 index 00000000000..dde2e87d18e --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/fromStandardKt.txt @@ -0,0 +1,15 @@ +package + +public fun testAlso(/*0*/ x: kotlin.Int): kotlin.Unit +public fun testApply(/*0*/ x: kotlin.Int): kotlin.Unit +public fun testLet(/*0*/ x: kotlin.Int): kotlin.Unit +public fun testRepeatOnInitializedVar(/*0*/ x: kotlin.Int): kotlin.Unit +public fun testRepeatOnVal(/*0*/ x: kotlin.Int): kotlin.Unit +public fun testRepeatOnVar(/*0*/ x: kotlin.Int): kotlin.Unit +public fun testRunWithCoercionToUnit(): kotlin.Unit +public fun testRunWithReceiver(/*0*/ x: kotlin.Int): kotlin.Unit +public fun testRunWithReturnValue(): kotlin.Unit +public fun testRunWithUnitReturn(): kotlin.Unit +public fun testTakeIf(/*0*/ x: kotlin.Int?): kotlin.Unit +public fun testTakeUnless(/*0*/ x: kotlin.Int?): kotlin.Unit +public fun testWith(/*0*/ x: kotlin.Int): kotlin.Unit diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/isNullOrBlank.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/isNullOrBlank.kt new file mode 100644 index 00000000000..ce5331bcaee --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/isNullOrBlank.kt @@ -0,0 +1,20 @@ +// !LANGUAGE: +ReturnsEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +fun testIsNullOrBlank(x: String?) { + if (x.isNullOrBlank()) { + x.length + } + else { + x.length + } +} + +fun testIsNotNullOrBlank(x: String?) { + if (!x.isNullOrBlank()) { + x.length + } + + x.length +} + diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/isNullOrBlank.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/isNullOrBlank.txt new file mode 100644 index 00000000000..e8a2ae9c591 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/isNullOrBlank.txt @@ -0,0 +1,4 @@ +package + +public fun testIsNotNullOrBlank(/*0*/ x: kotlin.String?): kotlin.Unit +public fun testIsNullOrBlank(/*0*/ x: kotlin.String?): kotlin.Unit diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/isNullOrEmpty.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/isNullOrEmpty.kt new file mode 100644 index 00000000000..000877237eb --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/isNullOrEmpty.kt @@ -0,0 +1,20 @@ +// !LANGUAGE: +ReturnsEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +fun testIsNullOrEmpty(x: String?) { + if (x.isNullOrEmpty()) { + x.length + } + else { + x.length + } +} + +fun testIsNotNullOrEmpty(x: String?) { + if (!x.isNullOrEmpty()) { + x.length + } + + x.length +} + diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/isNullOrEmpty.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/isNullOrEmpty.txt new file mode 100644 index 00000000000..5ed028df738 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/isNullOrEmpty.txt @@ -0,0 +1,4 @@ +package + +public fun testIsNotNullOrEmpty(/*0*/ x: kotlin.String?): kotlin.Unit +public fun testIsNullOrEmpty(/*0*/ x: kotlin.String?): kotlin.Unit diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/require.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/require.kt new file mode 100644 index 00000000000..535eed3b5ec --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/require.kt @@ -0,0 +1,27 @@ +// !LANGUAGE: +ReturnsEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +fun testRequireSmartcast(x: Any?) { + require(x is String) + x.length +} + +fun testRequireUnreachableCode() { + require(false) + println("Can't get here!") +} + +fun testRequireWithMessage(x: Any?) { + require(x is String) { "x is not String!" } + x.length +} + +fun testRequireWithFailingMessage(x: Any?) { + require(x is String) { throw kotlin.IllegalStateException("What a strange idea") } + x.length +} + +fun tesRequireNotNullWithMessage(x: Int?) { + requireNotNull(x) { "x is null!"} + x.inc() +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/require.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/require.txt new file mode 100644 index 00000000000..9bdc1eca469 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/require.txt @@ -0,0 +1,7 @@ +package + +public fun tesRequireNotNullWithMessage(/*0*/ x: kotlin.Int?): kotlin.Unit +public fun testRequireSmartcast(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun testRequireUnreachableCode(): kotlin.Unit +public fun testRequireWithFailingMessage(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun testRequireWithMessage(/*0*/ x: kotlin.Any?): kotlin.Unit diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java index 7f275c2bca0..a80b82aa4f1 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java @@ -1031,6 +1031,45 @@ public class DiagnosticsTestWithStdLibGenerated extends AbstractDiagnosticsTestW } } + @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class FromStdlib extends AbstractDiagnosticsTestWithStdLib { + public void testAllFilesPresentInFromStdlib() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("check.kt") + public void testCheck() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/check.kt"); + doTest(fileName); + } + + @TestMetadata("fromStandardKt.kt") + public void testFromStandardKt() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/fromStandardKt.kt"); + doTest(fileName); + } + + @TestMetadata("isNullOrBlank.kt") + public void testIsNullOrBlank() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/isNullOrBlank.kt"); + doTest(fileName); + } + + @TestMetadata("isNullOrEmpty.kt") + public void testIsNullOrEmpty() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/isNullOrEmpty.kt"); + doTest(fileName); + } + + @TestMetadata("require.kt") + public void testRequire() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/require.kt"); + doTest(fileName); + } + } + @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java index f85a3050eb4..bd877dbe129 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java @@ -1031,6 +1031,45 @@ public class DiagnosticsTestWithStdLibUsingJavacGenerated extends AbstractDiagno } } + @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class FromStdlib extends AbstractDiagnosticsTestWithStdLibUsingJavac { + public void testAllFilesPresentInFromStdlib() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("check.kt") + public void testCheck() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/check.kt"); + doTest(fileName); + } + + @TestMetadata("fromStandardKt.kt") + public void testFromStandardKt() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/fromStandardKt.kt"); + doTest(fileName); + } + + @TestMetadata("isNullOrBlank.kt") + public void testIsNullOrBlank() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/isNullOrBlank.kt"); + doTest(fileName); + } + + @TestMetadata("isNullOrEmpty.kt") + public void testIsNullOrEmpty() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/isNullOrEmpty.kt"); + doTest(fileName); + } + + @TestMetadata("require.kt") + public void testRequire() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/require.kt"); + doTest(fileName); + } + } + @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class)