From c44cab4565dbec6a3d44349f2f959fa34337b420 Mon Sep 17 00:00:00 2001 From: Toshiaki Kameyama Date: Wed, 25 Apr 2018 07:39:33 +0300 Subject: [PATCH] "Redundant Unit" inspection: Fix for labeled return #KT-23977 Fixed --- .../RedundantUnitExpressionInspection.kt | 21 ++++++++++++++++++- .../labeledReturnAny.kt | 9 ++++++++ .../labeledReturnAnyInValueArgument.kt | 7 +++++++ .../labeledReturnGenericType.kt | 7 +++++++ .../labeledReturnGenericType.kt.after | 7 +++++++ .../labeledReturnUnit.kt | 7 +++++++ .../labeledReturnUnit.kt.after | 7 +++++++ .../LocalInspectionTestGenerated.java | 20 ++++++++++++++++++ 8 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 idea/testData/inspectionsLocal/redundantUnitExpression/labeledReturnAny.kt create mode 100644 idea/testData/inspectionsLocal/redundantUnitExpression/labeledReturnAnyInValueArgument.kt create mode 100644 idea/testData/inspectionsLocal/redundantUnitExpression/labeledReturnGenericType.kt create mode 100644 idea/testData/inspectionsLocal/redundantUnitExpression/labeledReturnGenericType.kt.after create mode 100644 idea/testData/inspectionsLocal/redundantUnitExpression/labeledReturnUnit.kt create mode 100644 idea/testData/inspectionsLocal/redundantUnitExpression/labeledReturnUnit.kt.after diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/RedundantUnitExpressionInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/RedundantUnitExpressionInspection.kt index cdd92c39807..d5d7e15f54b 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/RedundantUnitExpressionInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/RedundantUnitExpressionInspection.kt @@ -10,10 +10,13 @@ import com.intellij.openapi.project.Project import com.intellij.psi.PsiElementVisitor import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall +import org.jetbrains.kotlin.idea.intentions.getCallableDescriptor import org.jetbrains.kotlin.idea.intentions.loopToCallChain.previousStatement +import org.jetbrains.kotlin.js.descriptorUtils.nameIfStandardType import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.getParentOfType import org.jetbrains.kotlin.psi.psiUtil.getParentOfTypesAndPredicate +import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType import org.jetbrains.kotlin.psi.psiUtil.lastBlockStatementOrThis import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.types.typeUtil.isUnit @@ -36,7 +39,23 @@ class RedundantUnitExpressionInspection : AbstractKotlinInspection(), CleanupLoc private fun KtReferenceExpression.isRedundantUnit(): Boolean { if (!isUnitLiteral()) return false val parent = this.parent ?: return false - if (parent is KtReturnExpression) return true + if (parent is KtReturnExpression) { + if (parent.labeledExpression != null) { + val functionLiteral = parent.getStrictParentOfType() + val callExpression = functionLiteral?.getStrictParentOfType() + if (functionLiteral != null && callExpression != null) { + val valueArgument = functionLiteral.getStrictParentOfType() + val index = if (valueArgument != null) + callExpression.valueArguments.indexOf(valueArgument) + else + callExpression.valueArguments.size - 1 + val parameter = callExpression.getCallableDescriptor()?.valueParameters?.getOrNull(index) + val returnType = parameter?.returnType?.arguments?.firstOrNull()?.type + if (returnType?.nameIfStandardType == KotlinBuiltIns.FQ_NAMES.any.shortName()) return false + } + } + return true + } if (parent is KtBlockExpression) { // Do not report just 'Unit' in function literals (return@label Unit is OK even in literals) if (parent.getParentOfType(strict = true) != null) return false diff --git a/idea/testData/inspectionsLocal/redundantUnitExpression/labeledReturnAny.kt b/idea/testData/inspectionsLocal/redundantUnitExpression/labeledReturnAny.kt new file mode 100644 index 00000000000..2221577c7c4 --- /dev/null +++ b/idea/testData/inspectionsLocal/redundantUnitExpression/labeledReturnAny.kt @@ -0,0 +1,9 @@ +// PROBLEM: none + +fun foo(f: () -> Any) {} + +fun test() { + foo { + return@foo Unit + } +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/redundantUnitExpression/labeledReturnAnyInValueArgument.kt b/idea/testData/inspectionsLocal/redundantUnitExpression/labeledReturnAnyInValueArgument.kt new file mode 100644 index 00000000000..102a2f4cae4 --- /dev/null +++ b/idea/testData/inspectionsLocal/redundantUnitExpression/labeledReturnAnyInValueArgument.kt @@ -0,0 +1,7 @@ +// PROBLEM: none + +fun foo(f: () -> Unit, g: () -> Any) {} + +fun test() { + foo({ return@foo Unit }, { return@foo Unit }) +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/redundantUnitExpression/labeledReturnGenericType.kt b/idea/testData/inspectionsLocal/redundantUnitExpression/labeledReturnGenericType.kt new file mode 100644 index 00000000000..2853726c339 --- /dev/null +++ b/idea/testData/inspectionsLocal/redundantUnitExpression/labeledReturnGenericType.kt @@ -0,0 +1,7 @@ +fun foo(f: () -> T) {} + +fun test() { + foo { + return@foo Unit + } +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/redundantUnitExpression/labeledReturnGenericType.kt.after b/idea/testData/inspectionsLocal/redundantUnitExpression/labeledReturnGenericType.kt.after new file mode 100644 index 00000000000..cc316b7b5d6 --- /dev/null +++ b/idea/testData/inspectionsLocal/redundantUnitExpression/labeledReturnGenericType.kt.after @@ -0,0 +1,7 @@ +fun foo(f: () -> T) {} + +fun test() { + foo { + return@foo + } +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/redundantUnitExpression/labeledReturnUnit.kt b/idea/testData/inspectionsLocal/redundantUnitExpression/labeledReturnUnit.kt new file mode 100644 index 00000000000..dec8e22091d --- /dev/null +++ b/idea/testData/inspectionsLocal/redundantUnitExpression/labeledReturnUnit.kt @@ -0,0 +1,7 @@ +fun foo(f: () -> Unit) {} + +fun test() { + foo { + return@foo Unit + } +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/redundantUnitExpression/labeledReturnUnit.kt.after b/idea/testData/inspectionsLocal/redundantUnitExpression/labeledReturnUnit.kt.after new file mode 100644 index 00000000000..0c5fc6f7dac --- /dev/null +++ b/idea/testData/inspectionsLocal/redundantUnitExpression/labeledReturnUnit.kt.after @@ -0,0 +1,7 @@ +fun foo(f: () -> Unit) {} + +fun test() { + foo { + return@foo + } +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java index 1a531bfccdd..4cf35e3962a 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java @@ -3358,6 +3358,26 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest { runTest("idea/testData/inspectionsLocal/redundantUnitExpression/atLastAfterVal.kt"); } + @TestMetadata("labeledReturnAny.kt") + public void testLabeledReturnAny() throws Exception { + runTest("idea/testData/inspectionsLocal/redundantUnitExpression/labeledReturnAny.kt"); + } + + @TestMetadata("labeledReturnAnyInValueArgument.kt") + public void testLabeledReturnAnyInValueArgument() throws Exception { + runTest("idea/testData/inspectionsLocal/redundantUnitExpression/labeledReturnAnyInValueArgument.kt"); + } + + @TestMetadata("labeledReturnGenericType.kt") + public void testLabeledReturnGenericType() throws Exception { + runTest("idea/testData/inspectionsLocal/redundantUnitExpression/labeledReturnGenericType.kt"); + } + + @TestMetadata("labeledReturnUnit.kt") + public void testLabeledReturnUnit() throws Exception { + runTest("idea/testData/inspectionsLocal/redundantUnitExpression/labeledReturnUnit.kt"); + } + @TestMetadata("lambda.kt") public void testLambda() throws Exception { runTest("idea/testData/inspectionsLocal/redundantUnitExpression/lambda.kt");