Introduce "Redundant return label" inspection #KT-25270 Fixed

This commit is contained in:
Toshiaki Kameyama
2018-08-06 18:44:27 +03:00
committed by Mikhail Glukhikh
parent b91f30ab15
commit 2dcbf6aa34
19 changed files with 193 additions and 0 deletions
@@ -402,3 +402,11 @@ fun qualifiedExpressionRecursiveVisitor(block: (KtQualifiedExpression) -> Unit)
block(qualifiedExpression)
}
}
fun returnExpressionVisitor(block: (KtReturnExpression) -> Unit) =
object : KtVisitorVoid() {
override fun visitReturnExpression(returnExpression: KtReturnExpression) {
super.visitReturnExpression(returnExpression)
block(returnExpression)
}
}
@@ -130,6 +130,10 @@ inline fun <reified T : PsiElement, reified V : PsiElement, reified U : PsiEleme
return PsiTreeUtil.getParentOfType(this, T::class.java, V::class.java, U::class.java)
}
inline fun <reified T : PsiElement> PsiElement.getParentOfType(strict: Boolean, vararg stopAt: Class<out PsiElement>): T? {
return PsiTreeUtil.getParentOfType(this, T::class.java, strict, *stopAt)
}
inline fun <reified T : PsiElement> PsiElement.getStrictParentOfType(): T? {
return PsiTreeUtil.getParentOfType(this, T::class.java, true)
}
@@ -0,0 +1,5 @@
<html>
<body>
This inspection reports redundant return label outside of lambda.
</body>
</html>
+9
View File
@@ -3011,6 +3011,15 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
language="kotlin"
/>
<localInspection implementationClass="org.jetbrains.kotlin.idea.inspections.RedundantReturnLabelInspection"
displayName="Redundant 'return' label"
groupPath="Kotlin"
groupName="Redundant constructs"
enabledByDefault="true"
level="WEAK WARNING"
language="kotlin"
/>
<referenceImporter implementation="org.jetbrains.kotlin.idea.quickfix.KotlinReferenceImporter"/>
<fileType.fileViewProviderFactory filetype="KJSM" implementationClass="com.intellij.psi.ClassFileViewProviderFactory"/>
+9
View File
@@ -3010,6 +3010,15 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
language="kotlin"
/>
<localInspection implementationClass="org.jetbrains.kotlin.idea.inspections.RedundantReturnLabelInspection"
displayName="Redundant 'return' label"
groupPath="Kotlin"
groupName="Redundant constructs"
enabledByDefault="true"
level="WEAK WARNING"
language="kotlin"
/>
<referenceImporter implementation="org.jetbrains.kotlin.idea.quickfix.KotlinReferenceImporter"/>
<fileType.fileViewProviderFactory filetype="KJSM" implementationClass="com.intellij.psi.ClassFileViewProviderFactory"/>
+9
View File
@@ -3010,6 +3010,15 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
language="kotlin"
/>
<localInspection implementationClass="org.jetbrains.kotlin.idea.inspections.RedundantReturnLabelInspection"
displayName="Redundant 'return' label"
groupPath="Kotlin"
groupName="Redundant constructs"
enabledByDefault="true"
level="WEAK WARNING"
language="kotlin"
/>
<referenceImporter implementation="org.jetbrains.kotlin.idea.quickfix.KotlinReferenceImporter"/>
<fileType.fileViewProviderFactory filetype="KJSM" implementationClass="com.intellij.psi.ClassFileViewProviderFactory"/>
+9
View File
@@ -3011,6 +3011,15 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
language="kotlin"
/>
<localInspection implementationClass="org.jetbrains.kotlin.idea.inspections.RedundantReturnLabelInspection"
displayName="Redundant 'return' label"
groupPath="Kotlin"
groupName="Redundant constructs"
enabledByDefault="true"
level="WEAK WARNING"
language="kotlin"
/>
<referenceImporter implementation="org.jetbrains.kotlin.idea.quickfix.KotlinReferenceImporter"/>
<fileType.fileViewProviderFactory filetype="KJSM" implementationClass="com.intellij.psi.ClassFileViewProviderFactory"/>
+9
View File
@@ -3010,6 +3010,15 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
language="kotlin"
/>
<localInspection implementationClass="org.jetbrains.kotlin.idea.inspections.RedundantReturnLabelInspection"
displayName="Redundant 'return' label"
groupPath="Kotlin"
groupName="Redundant constructs"
enabledByDefault="true"
level="WEAK WARNING"
language="kotlin"
/>
<referenceImporter implementation="org.jetbrains.kotlin.idea.quickfix.KotlinReferenceImporter"/>
<fileType.fileViewProviderFactory filetype="KJSM" implementationClass="com.intellij.psi.ClassFileViewProviderFactory"/>
+9
View File
@@ -3010,6 +3010,15 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
language="kotlin"
/>
<localInspection implementationClass="org.jetbrains.kotlin.idea.inspections.RedundantReturnLabelInspection"
displayName="Redundant 'return' label"
groupPath="Kotlin"
groupName="Redundant constructs"
enabledByDefault="true"
level="WEAK WARNING"
language="kotlin"
/>
<referenceImporter implementation="org.jetbrains.kotlin.idea.quickfix.KotlinReferenceImporter"/>
<fileType.fileViewProviderFactory filetype="KJSM" implementationClass="com.intellij.psi.ClassFileViewProviderFactory"/>
+9
View File
@@ -3012,6 +3012,15 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
language="kotlin"
/>
<localInspection implementationClass="org.jetbrains.kotlin.idea.inspections.RedundantReturnLabelInspection"
displayName="Redundant 'return' label"
groupPath="Kotlin"
groupName="Redundant constructs"
enabledByDefault="true"
level="WEAK WARNING"
language="kotlin"
/>
<referenceImporter implementation="org.jetbrains.kotlin.idea.quickfix.KotlinReferenceImporter"/>
<fileType.fileViewProviderFactory filetype="KJSM" implementationClass="com.intellij.psi.ClassFileViewProviderFactory"/>
@@ -0,0 +1,43 @@
/*
* 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.LocalQuickFix
import com.intellij.codeInspection.ProblemDescriptor
import com.intellij.codeInspection.ProblemHighlightType
import com.intellij.codeInspection.ProblemsHolder
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElementVisitor
import org.jetbrains.kotlin.psi.KtLambdaExpression
import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
import org.jetbrains.kotlin.psi.returnExpressionVisitor
class RedundantReturnLabelInspection : AbstractKotlinInspection() {
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor =
returnExpressionVisitor(fun(returnExpression) {
val label = returnExpression.getTargetLabel() ?: return
val function = returnExpression.getParentOfType<KtNamedFunction>(true, KtLambdaExpression::class.java) ?: return
if (function.name == null) return
val labelName = label.getReferencedName()
holder.registerProblem(
label,
"Redundant '@$labelName'",
ProblemHighlightType.LIKE_UNUSED_SYMBOL,
RemoveReturnLabelFix(labelName)
)
})
}
private class RemoveReturnLabelFix(private val labelName: String) : LocalQuickFix {
override fun getName() = "Remove redundant '@$labelName'"
override fun getFamilyName() = name
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
descriptor.psiElement?.delete()
}
}
@@ -0,0 +1 @@
org.jetbrains.kotlin.idea.inspections.RedundantReturnLabelInspection
@@ -0,0 +1,9 @@
// PROBLEM: none
fun foo(f: (String?) -> Int) {}
fun test() {
foo(fun(it: String?): Int {
if (it != null) return@foo<caret> 1
return 0
})
}
@@ -0,0 +1,3 @@
fun test() {
return@test<caret>
}
@@ -0,0 +1,3 @@
fun test() {
return
}
@@ -0,0 +1,6 @@
fun test(s: String?): Int {
if (s != null) {
return@test<caret> 1
}
return 0
}
@@ -0,0 +1,6 @@
fun test(s: String?): Int {
if (s != null) {
return 1
}
return 0
}
@@ -0,0 +1,9 @@
// PROBLEM: none
fun foo(f: (String?) -> Int) {}
fun test() {
foo {
if (it != null) return@foo<caret> 1
0
}
}
@@ -3948,6 +3948,39 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest {
}
}
@TestMetadata("idea/testData/inspectionsLocal/redundantReturnLabel")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class RedundantReturnLabel extends AbstractLocalInspectionTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
}
public void testAllFilesPresentInRedundantReturnLabel() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/inspectionsLocal/redundantReturnLabel"), Pattern.compile("^([\\w\\-_]+)\\.(kt|kts)$"), TargetBackend.ANY, true);
}
@TestMetadata("inAnonymousFunction.kt")
public void testInAnonymousFunction() throws Exception {
runTest("idea/testData/inspectionsLocal/redundantReturnLabel/inAnonymousFunction.kt");
}
@TestMetadata("inFunction.kt")
public void testInFunction() throws Exception {
runTest("idea/testData/inspectionsLocal/redundantReturnLabel/inFunction.kt");
}
@TestMetadata("inFunction2.kt")
public void testInFunction2() throws Exception {
runTest("idea/testData/inspectionsLocal/redundantReturnLabel/inFunction2.kt");
}
@TestMetadata("inLambda.kt")
public void testInLambda() throws Exception {
runTest("idea/testData/inspectionsLocal/redundantReturnLabel/inLambda.kt");
}
}
@TestMetadata("idea/testData/inspectionsLocal/redundantSamConstructor")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)