From 26e3d2cf5d272ef883575d43bf0a0d6a60aacd73 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Mon, 5 Jun 2017 14:48:04 +0300 Subject: [PATCH] Use TopLevelDeclarations analysis mode in REPL #KT-12564 Fixed --- .../kotlin/cli/jvm/repl/ReplCodeAnalyzer.kt | 2 +- .../controlFlow/functionWithoutReturn.repl | 4 ++ .../repl/controlFlow/incompleteIf.repl | 6 +++ .../repl/controlFlow/incompleteWhen.repl | 11 +++++ .../repl/controlFlow/loopWithWrongLabel.repl | 4 ++ .../testData/repl/controlFlow/mutateVal.repl | 11 +++++ .../repl/controlFlow/useUninitializedVal.repl | 12 +++++ .../repl/ReplInterpreterTestGenerated.java | 45 +++++++++++++++++++ 8 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 compiler/testData/repl/controlFlow/functionWithoutReturn.repl create mode 100644 compiler/testData/repl/controlFlow/incompleteIf.repl create mode 100644 compiler/testData/repl/controlFlow/incompleteWhen.repl create mode 100644 compiler/testData/repl/controlFlow/loopWithWrongLabel.repl create mode 100644 compiler/testData/repl/controlFlow/mutateVal.repl create mode 100644 compiler/testData/repl/controlFlow/useUninitializedVal.repl diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/ReplCodeAnalyzer.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/ReplCodeAnalyzer.kt index 5484c14a8e3..3d4ad6d5ea3 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/ReplCodeAnalyzer.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/ReplCodeAnalyzer.kt @@ -73,7 +73,7 @@ class ReplCodeAnalyzer(environment: KotlinCoreEnvironment) { this.scriptDeclarationFactory = container.get() this.resolveSession = container.get() this.topDownAnalysisContext = TopDownAnalysisContext( - TopDownAnalysisMode.LocalDeclarations, DataFlowInfoFactory.EMPTY, resolveSession.declarationScopeProvider + TopDownAnalysisMode.TopLevelDeclarations, DataFlowInfoFactory.EMPTY, resolveSession.declarationScopeProvider ) this.topDownAnalyzer = container.get() } diff --git a/compiler/testData/repl/controlFlow/functionWithoutReturn.repl b/compiler/testData/repl/controlFlow/functionWithoutReturn.repl new file mode 100644 index 00000000000..166f203c3e6 --- /dev/null +++ b/compiler/testData/repl/controlFlow/functionWithoutReturn.repl @@ -0,0 +1,4 @@ +>>> fun fn(): Int {} +error: a 'return' expression required in a function with a block body ('{...}') +fun fn(): Int {} + ^ diff --git a/compiler/testData/repl/controlFlow/incompleteIf.repl b/compiler/testData/repl/controlFlow/incompleteIf.repl new file mode 100644 index 00000000000..aa8d137934d --- /dev/null +++ b/compiler/testData/repl/controlFlow/incompleteIf.repl @@ -0,0 +1,6 @@ +>>> if (false) 42 +>>> if (true) 42 +>>> "" + (if (true) 42) +error: 'if' must have both main and 'else' branches if used as an expression +"" + (if (true) 42) + ^ diff --git a/compiler/testData/repl/controlFlow/incompleteWhen.repl b/compiler/testData/repl/controlFlow/incompleteWhen.repl new file mode 100644 index 00000000000..6a40f55fcda --- /dev/null +++ b/compiler/testData/repl/controlFlow/incompleteWhen.repl @@ -0,0 +1,11 @@ +>>> val a = when(null) { } +error: 'when' expression must be exhaustive, add necessary 'else' branch +val a = when(null) { } + ^ +warning: the expression is unused +val a = when(null) { } + ^ +>>> "" + when (true) { true -> 42 } +error: 'when' expression must be exhaustive, add necessary 'false' branch or 'else' branch instead +"" + when (true) { true -> 42 } + ^ diff --git a/compiler/testData/repl/controlFlow/loopWithWrongLabel.repl b/compiler/testData/repl/controlFlow/loopWithWrongLabel.repl new file mode 100644 index 00000000000..f9adb6558a5 --- /dev/null +++ b/compiler/testData/repl/controlFlow/loopWithWrongLabel.repl @@ -0,0 +1,4 @@ +>>> for (n in 1..10) foo@ { break@foo } +error: the label '@foo' does not denote a loop +for (n in 1..10) foo@ { break@foo } + ^ diff --git a/compiler/testData/repl/controlFlow/mutateVal.repl b/compiler/testData/repl/controlFlow/mutateVal.repl new file mode 100644 index 00000000000..d3c50413738 --- /dev/null +++ b/compiler/testData/repl/controlFlow/mutateVal.repl @@ -0,0 +1,11 @@ +>>> val x = 1 +>>> x = 2 +error: val cannot be reassigned +x = 2 +^ +>>> x++ +error: val cannot be reassigned +x++ +^ +>>> x +1 diff --git a/compiler/testData/repl/controlFlow/useUninitializedVal.repl b/compiler/testData/repl/controlFlow/useUninitializedVal.repl new file mode 100644 index 00000000000..d644dedfa21 --- /dev/null +++ b/compiler/testData/repl/controlFlow/useUninitializedVal.repl @@ -0,0 +1,12 @@ +>>> val a: String +error: property must be initialized or be abstract +val a: String +^ +>>> a +error: unresolved reference: a +a +^ +>>> val s: String = s +error: variable 's' must be initialized +val s: String = s + ^ diff --git a/compiler/tests/org/jetbrains/kotlin/repl/ReplInterpreterTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/repl/ReplInterpreterTestGenerated.java index adccff222b1..07606bf6522 100644 --- a/compiler/tests/org/jetbrains/kotlin/repl/ReplInterpreterTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/repl/ReplInterpreterTestGenerated.java @@ -213,6 +213,51 @@ public class ReplInterpreterTestGenerated extends AbstractReplInterpreterTest { } } + @TestMetadata("compiler/testData/repl/controlFlow") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class ControlFlow extends AbstractReplInterpreterTest { + public void testAllFilesPresentInControlFlow() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/repl/controlFlow"), Pattern.compile("^(.+)\\.repl$"), TargetBackend.ANY, true); + } + + @TestMetadata("functionWithoutReturn.repl") + public void testFunctionWithoutReturn() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/repl/controlFlow/functionWithoutReturn.repl"); + doTest(fileName); + } + + @TestMetadata("incompleteIf.repl") + public void testIncompleteIf() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/repl/controlFlow/incompleteIf.repl"); + doTest(fileName); + } + + @TestMetadata("incompleteWhen.repl") + public void testIncompleteWhen() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/repl/controlFlow/incompleteWhen.repl"); + doTest(fileName); + } + + @TestMetadata("loopWithWrongLabel.repl") + public void testLoopWithWrongLabel() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/repl/controlFlow/loopWithWrongLabel.repl"); + doTest(fileName); + } + + @TestMetadata("mutateVal.repl") + public void testMutateVal() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/repl/controlFlow/mutateVal.repl"); + doTest(fileName); + } + + @TestMetadata("useUninitializedVal.repl") + public void testUseUninitializedVal() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/repl/controlFlow/useUninitializedVal.repl"); + doTest(fileName); + } + } + @TestMetadata("compiler/testData/repl/modules") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class)