From 300e0acd27dae7cdaea9797f8edca85e3f7077c7 Mon Sep 17 00:00:00 2001 From: Nikolay Krasko Date: Thu, 4 Aug 2016 13:29:44 +0300 Subject: [PATCH] Report RETURN_NOT_ALLOWED and RETURN_IN_FUNCTION_WITH_EXPRESSION_BODY only on the return with label (KT-13340) #KT-13340 Fixed --- .../org/jetbrains/kotlin/diagnostics/Errors.java | 4 ++-- .../kotlin/diagnostics/PositioningStrategies.kt | 10 ++++++++++ .../jetbrains/kotlin/psi/KtReturnExpression.java | 14 ++++++++++++++ .../diagnostics/tests/FunctionReturnTypes.kt | 4 ++-- .../tests/ReturnInFunctionWithoutBody.kt | 3 +++ .../tests/ReturnInFunctionWithoutBody.txt | 5 +++++ .../tests/controlFlowAnalysis/kt10823.kt | 8 ++++---- .../diagnostics/tests/controlStructures/kt799.kt | 4 ++-- .../tests/declarationChecks/ScalaLikeNamedFun.kt | 16 ++++++++-------- .../return/AutoLabelsNonLocal.kt | 2 +- .../inline/nonLocalReturns/labeledReturn.kt | 2 +- .../inline/nonLocalReturns/lambdaAsGeneric.kt | 2 +- .../nonLocalReturns/lambdaAsNonFunction.kt | 2 +- .../propertyAccessorsAndConstructor.kt | 2 +- .../testData/diagnostics/tests/labels/kt361.kt | 2 +- .../diagnostics/tests/regressions/kt411.kt | 8 ++++---- .../tests/secondaryConstructors/return.kt | 2 +- .../checkers/DiagnosticsTestGenerated.java | 6 ++++++ idea/testData/checker/FunctionReturnTypes.kt | 2 +- .../codeFragments/startingFromReturn.kt.fragment | 2 +- .../checker/recovery/returnInFileAnnotation.kt | 2 +- 21 files changed, 70 insertions(+), 32 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/ReturnInFunctionWithoutBody.kt create mode 100644 compiler/testData/diagnostics/tests/ReturnInFunctionWithoutBody.txt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index 947ac003265..2e67aeff213 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -774,8 +774,8 @@ public interface Errors { DiagnosticFactory0 EXPRESSION_EXPECTED_PACKAGE_FOUND = DiagnosticFactory0.create(ERROR); - DiagnosticFactory0 RETURN_NOT_ALLOWED = DiagnosticFactory0.create(ERROR); - DiagnosticFactory0 RETURN_IN_FUNCTION_WITH_EXPRESSION_BODY = DiagnosticFactory0.create(ERROR); + DiagnosticFactory0 RETURN_NOT_ALLOWED = DiagnosticFactory0.create(ERROR, PositioningStrategies.RETURN_WITH_LABEL); + DiagnosticFactory0 RETURN_IN_FUNCTION_WITH_EXPRESSION_BODY = DiagnosticFactory0.create(ERROR, PositioningStrategies.RETURN_WITH_LABEL); DiagnosticFactory0 NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY = DiagnosticFactory0.create(ERROR, DECLARATION_WITH_BODY); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt index 19e22b7e2b3..f607fa56037 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt @@ -477,4 +477,14 @@ object PositioningStrategies { } } + @JvmField val RETURN_WITH_LABEL: PositioningStrategy = object: PositioningStrategy() { + override fun mark(element: KtReturnExpression): List { + val labeledExpression = element.labeledExpression + if (labeledExpression != null) { + return markRange(element, labeledExpression) + } + + return markElement(element.returnKeyword) + } + } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtReturnExpression.java b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtReturnExpression.java index f7b6fe78a0b..7063d1eaf02 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtReturnExpression.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtReturnExpression.java @@ -17,8 +17,11 @@ package org.jetbrains.kotlin.psi; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.kotlin.KtNodeTypes; +import org.jetbrains.kotlin.lexer.KtTokens; public class KtReturnExpression extends KtExpressionWithLabel implements KtStatementExpression { public KtReturnExpression(@NotNull ASTNode node) { @@ -34,4 +37,15 @@ public class KtReturnExpression extends KtExpressionWithLabel implements KtState public KtExpression getReturnedExpression() { return findChildByClass(KtExpression.class); } + + @NotNull + public PsiElement getReturnKeyword() { + //noinspection ConstantConditions + return findChildByType(KtTokens.RETURN_KEYWORD); + } + + @Nullable + public PsiElement getLabeledExpression() { + return findChildByType(KtNodeTypes.LABEL_QUALIFIER); + } } diff --git a/compiler/testData/diagnostics/tests/FunctionReturnTypes.kt b/compiler/testData/diagnostics/tests/FunctionReturnTypes.kt index 0b65ed2b5d1..19fd0991854 100644 --- a/compiler/testData/diagnostics/tests/FunctionReturnTypes.kt +++ b/compiler/testData/diagnostics/tests/FunctionReturnTypes.kt @@ -12,7 +12,7 @@ fun test2() : Any = a@ {return@a 1} fun test3() : Any { return } fun test4(): ()-> Unit = { return@test4 } fun test5(): Any = l@{ return@l } -fun test6(): Any = {return 1} +fun test6(): Any = {return 1} fun bbb() { return 1 @@ -136,7 +136,7 @@ fun blockNoReturnIfUnitInOneBranch(): Int { fun nonBlockReturnIfEmptyIf(): Int = if (1 < 2) {} else {} fun nonBlockNoReturnIfUnitInOneBranch(): Int = if (1 < 2) {} else 2 -val a = return 1 +val a = return 1 class A() { } diff --git a/compiler/testData/diagnostics/tests/ReturnInFunctionWithoutBody.kt b/compiler/testData/diagnostics/tests/ReturnInFunctionWithoutBody.kt new file mode 100644 index 00000000000..6df103e6fe1 --- /dev/null +++ b/compiler/testData/diagnostics/tests/ReturnInFunctionWithoutBody.kt @@ -0,0 +1,3 @@ +fun foo1(): () -> String = return { "some long expression "} +fun foo2(): () -> String = return@label { "some long expression "} +fun foo3(): () -> String = return@ { "some long expression "} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/ReturnInFunctionWithoutBody.txt b/compiler/testData/diagnostics/tests/ReturnInFunctionWithoutBody.txt new file mode 100644 index 00000000000..04c8a8d2963 --- /dev/null +++ b/compiler/testData/diagnostics/tests/ReturnInFunctionWithoutBody.txt @@ -0,0 +1,5 @@ +package + +public fun foo1(): () -> kotlin.String +public fun foo2(): () -> kotlin.String +public fun foo3(): () -> kotlin.String diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/kt10823.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/kt10823.kt index d4a1585ebe0..219b9c33f24 100644 --- a/compiler/testData/diagnostics/tests/controlFlowAnalysis/kt10823.kt +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/kt10823.kt @@ -1,6 +1,6 @@ fun find2(): Any? { fun visit(element: Any) { - return@find2 element + return@find2 element } return null } @@ -10,7 +10,7 @@ fun find2(): Any? { fun find(): Any? { object : Any() { fun visit(element: Any) { - return@find element + return@find element } } return null @@ -18,7 +18,7 @@ fun find(): Any? { fun find4(): Any? { inline fun visit(element: Any) { - return@find4 element + return@find4 element } return null } @@ -26,7 +26,7 @@ fun find4(): Any? { fun find3(): Any? { object : Any() { inline fun visit(element: Any) { - return@find3 element + return@find3 element } } return null diff --git a/compiler/testData/diagnostics/tests/controlStructures/kt799.kt b/compiler/testData/diagnostics/tests/controlStructures/kt799.kt index 50a04175f3b..f1aa021f3cb 100644 --- a/compiler/testData/diagnostics/tests/controlStructures/kt799.kt +++ b/compiler/testData/diagnostics/tests/controlStructures/kt799.kt @@ -12,9 +12,9 @@ fun test() { doSmth(if (true) 3 else return, 1) } -val a : Nothing = return 1 +val a : Nothing = return 1 -val b = return 1 +val b = return 1 val c = doSmth(if (true) 3 else return) diff --git a/compiler/testData/diagnostics/tests/declarationChecks/ScalaLikeNamedFun.kt b/compiler/testData/diagnostics/tests/declarationChecks/ScalaLikeNamedFun.kt index 9c8812cb13b..c9774ba93b4 100644 --- a/compiler/testData/diagnostics/tests/declarationChecks/ScalaLikeNamedFun.kt +++ b/compiler/testData/diagnostics/tests/declarationChecks/ScalaLikeNamedFun.kt @@ -1,34 +1,34 @@ // !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE // KT-5068 Add special error for scala-like syntax 'fun foo(): Int = { 1 }' -fun test1(): Int = { return 1 } +fun test1(): Int = { return 1 } fun test2(): Int = { 1 } -val test3: () -> Int = fun (): Int = { return 1 } +val test3: () -> Int = fun (): Int = { return 1 } val test4: () -> Int = fun (): Int = { 1 } fun test5(): Int { return { 1 } } fun test6(): Int = fun (): Int = 1 fun outer() { - fun test1(): Int = { return 1 } + fun test1(): Int = { return 1 } fun test2(): Int = { 1 } - val test3: () -> Int = fun (): Int = { return 1 } + val test3: () -> Int = fun (): Int = { return 1 } val test4: () -> Int = fun (): Int = { 1 } fun test5(): Int { return { 1 } } fun test6(): Int = fun (): Int = 1 } class Outer { - fun test1(): Int = { return 1 } + fun test1(): Int = { return 1 } fun test2(): Int = { 1 } - val test3: () -> Int = fun (): Int = { return 1 } + val test3: () -> Int = fun (): Int = { return 1 } val test4: () -> Int = fun (): Int = { 1 } fun test5(): Int { return { 1 } } fun test6(): Int = fun (): Int = 1 class Nested { - fun test1(): Int = { return 1 } + fun test1(): Int = { return 1 } fun test2(): Int = { 1 } - val test3: () -> Int = fun (): Int = { return 1 } + val test3: () -> Int = fun (): Int = { return 1 } val test4: () -> Int = fun (): Int = { 1 } fun test5(): Int { return { 1 } } fun test6(): Int = fun (): Int = 1 diff --git a/compiler/testData/diagnostics/tests/functionLiterals/return/AutoLabelsNonLocal.kt b/compiler/testData/diagnostics/tests/functionLiterals/return/AutoLabelsNonLocal.kt index 5211601de3c..9bbc015cc52 100644 --- a/compiler/testData/diagnostics/tests/functionLiterals/return/AutoLabelsNonLocal.kt +++ b/compiler/testData/diagnostics/tests/functionLiterals/return/AutoLabelsNonLocal.kt @@ -1,7 +1,7 @@ fun f() { foo { bar { - return@foo 1 + return@foo 1 } return@foo 1 } diff --git a/compiler/testData/diagnostics/tests/inline/nonLocalReturns/labeledReturn.kt b/compiler/testData/diagnostics/tests/inline/nonLocalReturns/labeledReturn.kt index 18631aa12c7..c55fd323b4d 100644 --- a/compiler/testData/diagnostics/tests/inline/nonLocalReturns/labeledReturn.kt +++ b/compiler/testData/diagnostics/tests/inline/nonLocalReturns/labeledReturn.kt @@ -17,7 +17,7 @@ inline fun inlineFun(s: ()->Int) { fun noInlineCall(): String { noInline { if (true) { - return@noInlineCall "" + return@noInlineCall "" } 1 } diff --git a/compiler/testData/diagnostics/tests/inline/nonLocalReturns/lambdaAsGeneric.kt b/compiler/testData/diagnostics/tests/inline/nonLocalReturns/lambdaAsGeneric.kt index ef9a02850f6..241adc0c88a 100644 --- a/compiler/testData/diagnostics/tests/inline/nonLocalReturns/lambdaAsGeneric.kt +++ b/compiler/testData/diagnostics/tests/inline/nonLocalReturns/lambdaAsGeneric.kt @@ -1,6 +1,6 @@ fun box() : String { test { - return@box "123" + return@box "123" } return "OK" diff --git a/compiler/testData/diagnostics/tests/inline/nonLocalReturns/lambdaAsNonFunction.kt b/compiler/testData/diagnostics/tests/inline/nonLocalReturns/lambdaAsNonFunction.kt index 6abdc96f9f0..44118e915a2 100644 --- a/compiler/testData/diagnostics/tests/inline/nonLocalReturns/lambdaAsNonFunction.kt +++ b/compiler/testData/diagnostics/tests/inline/nonLocalReturns/lambdaAsNonFunction.kt @@ -1,6 +1,6 @@ fun box() : String { test { - return@box "123" + return@box "123" } return "OK" diff --git a/compiler/testData/diagnostics/tests/inline/nonLocalReturns/propertyAccessorsAndConstructor.kt b/compiler/testData/diagnostics/tests/inline/nonLocalReturns/propertyAccessorsAndConstructor.kt index b9134143b31..0e91c0c2736 100644 --- a/compiler/testData/diagnostics/tests/inline/nonLocalReturns/propertyAccessorsAndConstructor.kt +++ b/compiler/testData/diagnostics/tests/inline/nonLocalReturns/propertyAccessorsAndConstructor.kt @@ -7,7 +7,7 @@ inline fun doCallInt(p: () -> R): R { } class A { - var result: Int = doCallInt { return this }; + var result: Int = doCallInt { return this }; var field: Int get() { diff --git a/compiler/testData/diagnostics/tests/labels/kt361.kt b/compiler/testData/diagnostics/tests/labels/kt361.kt index 44930c071d0..89911d335f2 100644 --- a/compiler/testData/diagnostics/tests/labels/kt361.kt +++ b/compiler/testData/diagnostics/tests/labels/kt361.kt @@ -2,7 +2,7 @@ fun nonlocals(b : Boolean) { a@{ fun foo() { if (b) { - return@a 1 // The label must be resolved, but an error should be reported for a non-local return + return@a 1 // The label must be resolved, but an error should be reported for a non-local return } } diff --git a/compiler/testData/diagnostics/tests/regressions/kt411.kt b/compiler/testData/diagnostics/tests/regressions/kt411.kt index ae76d1ab5aa..5e030220c35 100644 --- a/compiler/testData/diagnostics/tests/regressions/kt411.kt +++ b/compiler/testData/diagnostics/tests/regressions/kt411.kt @@ -23,7 +23,7 @@ fun t2() : String { if (true) { return@l 1 } - return "s" + return "s" } return "s" } @@ -32,10 +32,10 @@ fun t3() : String { invoker( l@{ if (true) { - return@t3 "1" + return@t3 "1" } else { - return 2 + return 2 } return@l 0 } @@ -47,7 +47,7 @@ fun t3() : String { ) invoker( { - return "0" + return "0" } ) return "2" diff --git a/compiler/testData/diagnostics/tests/secondaryConstructors/return.kt b/compiler/testData/diagnostics/tests/secondaryConstructors/return.kt index 835274867be..e176b17792d 100644 --- a/compiler/testData/diagnostics/tests/secondaryConstructors/return.kt +++ b/compiler/testData/diagnostics/tests/secondaryConstructors/return.kt @@ -1,7 +1,7 @@ class A { init { return - return 1 + return 1 } constructor() { if (1 == 1) { diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 0ad1ee29bdf..fa930f72244 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -589,6 +589,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("ReturnInFunctionWithoutBody.kt") + public void testReturnInFunctionWithoutBody() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/ReturnInFunctionWithoutBody.kt"); + doTest(fileName); + } + @TestMetadata("SafeCallInvoke.kt") public void testSafeCallInvoke() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/SafeCallInvoke.kt"); diff --git a/idea/testData/checker/FunctionReturnTypes.kt b/idea/testData/checker/FunctionReturnTypes.kt index 5f714467e87..d116011232f 100644 --- a/idea/testData/checker/FunctionReturnTypes.kt +++ b/idea/testData/checker/FunctionReturnTypes.kt @@ -131,7 +131,7 @@ fun blockNoReturnIfUnitInOneBranch(): Int { fun nonBlockReturnIfEmptyIf(): Int = if (1 < 2) {} else {} fun nonBlockNoReturnIfUnitInOneBranch(): Int = if (1 < 2) {} else 2 -val a = return 1 +val a = return 1 class A() { } diff --git a/idea/testData/checker/codeFragments/startingFromReturn.kt.fragment b/idea/testData/checker/codeFragments/startingFromReturn.kt.fragment index 98dac6b3e8e..dd23141fd1b 100644 --- a/idea/testData/checker/codeFragments/startingFromReturn.kt.fragment +++ b/idea/testData/checker/codeFragments/startingFromReturn.kt.fragment @@ -1 +1 @@ -return a \ No newline at end of file +return a \ No newline at end of file diff --git a/idea/testData/checker/recovery/returnInFileAnnotation.kt b/idea/testData/checker/recovery/returnInFileAnnotation.kt index 4efd92d81ab..36d8e3fc354 100644 --- a/idea/testData/checker/recovery/returnInFileAnnotation.kt +++ b/idea/testData/checker/recovery/returnInFileAnnotation.kt @@ -1 +1 @@ -@file:suppress(return a) \ No newline at end of file +@file:suppress(return a) \ No newline at end of file