From 6cd13341ee9cd24b2243d0a11257d18dccb7dd48 Mon Sep 17 00:00:00 2001 From: Toshiaki Kameyama Date: Fri, 31 Aug 2018 12:43:06 +0300 Subject: [PATCH] Add inspection for unlabeled return inside lambda #KT-26511 Fixed --- .../UnlabeledReturnInsideLambda.html | 5 ++++ idea/src/META-INF/plugin.xml | 9 ++++++ idea/src/META-INF/plugin.xml.173 | 9 ++++++ idea/src/META-INF/plugin.xml.181 | 9 ++++++ idea/src/META-INF/plugin.xml.183 | 9 ++++++ idea/src/META-INF/plugin.xml.as31 | 9 ++++++ idea/src/META-INF/plugin.xml.as32 | 9 ++++++ idea/src/META-INF/plugin.xml.as33 | 9 ++++++ .../UnlabeledReturnInsideLambdaInspection.kt | 28 +++++++++++++++++++ .../unlabeledReturnInsideLambda/.inspection | 1 + .../labeledReturn.kt | 7 +++++ .../unlabeledReturnInsideLambda/return.kt | 7 +++++ .../returnInFunction.kt | 9 ++++++ .../LocalInspectionTestGenerated.java | 28 +++++++++++++++++++ 14 files changed, 148 insertions(+) create mode 100644 idea/resources/inspectionDescriptions/UnlabeledReturnInsideLambda.html create mode 100644 idea/src/org/jetbrains/kotlin/idea/inspections/UnlabeledReturnInsideLambdaInspection.kt create mode 100644 idea/testData/inspectionsLocal/unlabeledReturnInsideLambda/.inspection create mode 100644 idea/testData/inspectionsLocal/unlabeledReturnInsideLambda/labeledReturn.kt create mode 100644 idea/testData/inspectionsLocal/unlabeledReturnInsideLambda/return.kt create mode 100644 idea/testData/inspectionsLocal/unlabeledReturnInsideLambda/returnInFunction.kt diff --git a/idea/resources/inspectionDescriptions/UnlabeledReturnInsideLambda.html b/idea/resources/inspectionDescriptions/UnlabeledReturnInsideLambda.html new file mode 100644 index 00000000000..a4d95e92792 --- /dev/null +++ b/idea/resources/inspectionDescriptions/UnlabeledReturnInsideLambda.html @@ -0,0 +1,5 @@ + + +This inspection reports unlabeled return inside lambda. + + diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index 86927718b71..e4adcf6a73e 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -3066,6 +3066,15 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio. language="kotlin" /> + + diff --git a/idea/src/META-INF/plugin.xml.173 b/idea/src/META-INF/plugin.xml.173 index a755fe93430..ef57f167363 100644 --- a/idea/src/META-INF/plugin.xml.173 +++ b/idea/src/META-INF/plugin.xml.173 @@ -3064,6 +3064,15 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio. language="kotlin" /> + + diff --git a/idea/src/META-INF/plugin.xml.181 b/idea/src/META-INF/plugin.xml.181 index 2ff37439e7b..f233c1519be 100644 --- a/idea/src/META-INF/plugin.xml.181 +++ b/idea/src/META-INF/plugin.xml.181 @@ -3065,6 +3065,15 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio. language="kotlin" /> + + diff --git a/idea/src/META-INF/plugin.xml.183 b/idea/src/META-INF/plugin.xml.183 index 03f0108f2c9..ab9c2b9beba 100644 --- a/idea/src/META-INF/plugin.xml.183 +++ b/idea/src/META-INF/plugin.xml.183 @@ -3066,6 +3066,15 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio. language="kotlin" /> + + diff --git a/idea/src/META-INF/plugin.xml.as31 b/idea/src/META-INF/plugin.xml.as31 index 253c63ebf43..93293e4ee17 100644 --- a/idea/src/META-INF/plugin.xml.as31 +++ b/idea/src/META-INF/plugin.xml.as31 @@ -3064,6 +3064,15 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio. language="kotlin" /> + + diff --git a/idea/src/META-INF/plugin.xml.as32 b/idea/src/META-INF/plugin.xml.as32 index 9c40e075ea5..675727a34de 100644 --- a/idea/src/META-INF/plugin.xml.as32 +++ b/idea/src/META-INF/plugin.xml.as32 @@ -3064,6 +3064,15 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio. language="kotlin" /> + + diff --git a/idea/src/META-INF/plugin.xml.as33 b/idea/src/META-INF/plugin.xml.as33 index feddde2262f..8d8356d75e7 100644 --- a/idea/src/META-INF/plugin.xml.as33 +++ b/idea/src/META-INF/plugin.xml.as33 @@ -3066,6 +3066,15 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio. language="kotlin" /> + + diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/UnlabeledReturnInsideLambdaInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/UnlabeledReturnInsideLambdaInspection.kt new file mode 100644 index 00000000000..ae43551ce73 --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/UnlabeledReturnInsideLambdaInspection.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.idea.inspections + +import com.intellij.codeInspection.ProblemHighlightType +import com.intellij.codeInspection.ProblemsHolder +import com.intellij.psi.PsiElementVisitor +import org.jetbrains.kotlin.psi.KtLambdaExpression +import org.jetbrains.kotlin.psi.KtNamedFunction +import org.jetbrains.kotlin.psi.KtReturnExpression +import org.jetbrains.kotlin.psi.psiUtil.getParentOfType +import org.jetbrains.kotlin.psi.returnExpressionVisitor + +class UnlabeledReturnInsideLambdaInspection : AbstractKotlinInspection() { + override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor = + returnExpressionVisitor(fun(returnExpression: KtReturnExpression) { + if (returnExpression.labelQualifier != null) return + if (returnExpression.getParentOfType(true, KtNamedFunction::class.java) == null) return + holder.registerProblem( + returnExpression, + "Unlabeled return inside lambda", + ProblemHighlightType.GENERIC_ERROR_OR_WARNING + ) + }) +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/unlabeledReturnInsideLambda/.inspection b/idea/testData/inspectionsLocal/unlabeledReturnInsideLambda/.inspection new file mode 100644 index 00000000000..985a755d1e0 --- /dev/null +++ b/idea/testData/inspectionsLocal/unlabeledReturnInsideLambda/.inspection @@ -0,0 +1 @@ +org.jetbrains.kotlin.idea.inspections.UnlabeledReturnInsideLambdaInspection \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/unlabeledReturnInsideLambda/labeledReturn.kt b/idea/testData/inspectionsLocal/unlabeledReturnInsideLambda/labeledReturn.kt new file mode 100644 index 00000000000..6f980912e08 --- /dev/null +++ b/idea/testData/inspectionsLocal/unlabeledReturnInsideLambda/labeledReturn.kt @@ -0,0 +1,7 @@ +// PROBLEM: none +// WITH_RUNTIME +fun test() { + listOf(1).forEach { + if (it == 10) return@forEach + } +} diff --git a/idea/testData/inspectionsLocal/unlabeledReturnInsideLambda/return.kt b/idea/testData/inspectionsLocal/unlabeledReturnInsideLambda/return.kt new file mode 100644 index 00000000000..e905b43109b --- /dev/null +++ b/idea/testData/inspectionsLocal/unlabeledReturnInsideLambda/return.kt @@ -0,0 +1,7 @@ +// FIX: none +// WITH_RUNTIME +fun test() { + listOf(1).forEach { + if (it == 10) return + } +} diff --git a/idea/testData/inspectionsLocal/unlabeledReturnInsideLambda/returnInFunction.kt b/idea/testData/inspectionsLocal/unlabeledReturnInsideLambda/returnInFunction.kt new file mode 100644 index 00000000000..a5e3692a59b --- /dev/null +++ b/idea/testData/inspectionsLocal/unlabeledReturnInsideLambda/returnInFunction.kt @@ -0,0 +1,9 @@ +// PROBLEM: none +// WITH_RUNTIME +fun test() { + listOf(1).forEach { + fun foo() { + if (it == 10) return + } + } +} diff --git a/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java index da204c23b92..4c0ed40d124 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java @@ -5999,6 +5999,34 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest { } } + @TestMetadata("idea/testData/inspectionsLocal/unlabeledReturnInsideLambda") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class UnlabeledReturnInsideLambda extends AbstractLocalInspectionTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath); + } + + public void testAllFilesPresentInUnlabeledReturnInsideLambda() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/inspectionsLocal/unlabeledReturnInsideLambda"), Pattern.compile("^([\\w\\-_]+)\\.(kt|kts)$"), TargetBackend.ANY, true); + } + + @TestMetadata("labeledReturn.kt") + public void testLabeledReturn() throws Exception { + runTest("idea/testData/inspectionsLocal/unlabeledReturnInsideLambda/labeledReturn.kt"); + } + + @TestMetadata("return.kt") + public void testReturn() throws Exception { + runTest("idea/testData/inspectionsLocal/unlabeledReturnInsideLambda/return.kt"); + } + + @TestMetadata("returnInFunction.kt") + public void testReturnInFunction() throws Exception { + runTest("idea/testData/inspectionsLocal/unlabeledReturnInsideLambda/returnInFunction.kt"); + } + } + @TestMetadata("idea/testData/inspectionsLocal/unnecessaryVariable") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class)