From b9a4b60b93ef9f35a0c2d7079a0908eabe242558 Mon Sep 17 00:00:00 2001 From: Toshiaki Kameyama Date: Thu, 20 May 2021 18:12:41 +0900 Subject: [PATCH] Unnecessary local variable: highlight with INFORMATION level when initializer has any multi-line blocks (#3359) #KT-26752 Fixed --- .../UnnecessaryVariableInspection.kt | 15 +++++++ .../unnecessaryVariable/ifElse.kt | 13 ++++++ .../unnecessaryVariable/ifElse.kt.after | 12 +++++ .../unnecessaryVariable/ifElse2.kt | 9 ++++ .../unnecessaryVariable/ifElse2.kt.after | 8 ++++ .../unnecessaryVariable/ifElse3.kt | 12 +++++ .../unnecessaryVariable/ifElse3.kt.after | 11 +++++ .../unnecessaryVariable/ifElse4.kt | 14 ++++++ .../unnecessaryVariable/ifElse4.kt.after | 13 ++++++ .../unnecessaryVariable/ifElse5.kt | 18 ++++++++ .../unnecessaryVariable/ifElse5.kt.after | 17 +++++++ .../unnecessaryVariable/lambda.kt | 9 ++++ .../unnecessaryVariable/lambda.kt.after | 8 ++++ .../unnecessaryVariable/lambda2.kt | 11 +++++ .../unnecessaryVariable/lambda2.kt.after | 10 +++++ .../unnecessaryVariable/try.kt | 13 ++++++ .../unnecessaryVariable/try.kt.after | 12 +++++ .../unnecessaryVariable/when.kt | 12 +++++ .../unnecessaryVariable/when.kt.after | 11 +++++ .../LocalInspectionTestGenerated.java | 45 +++++++++++++++++++ 20 files changed, 273 insertions(+) create mode 100644 idea/testData/inspectionsLocal/unnecessaryVariable/ifElse.kt create mode 100644 idea/testData/inspectionsLocal/unnecessaryVariable/ifElse.kt.after create mode 100644 idea/testData/inspectionsLocal/unnecessaryVariable/ifElse2.kt create mode 100644 idea/testData/inspectionsLocal/unnecessaryVariable/ifElse2.kt.after create mode 100644 idea/testData/inspectionsLocal/unnecessaryVariable/ifElse3.kt create mode 100644 idea/testData/inspectionsLocal/unnecessaryVariable/ifElse3.kt.after create mode 100644 idea/testData/inspectionsLocal/unnecessaryVariable/ifElse4.kt create mode 100644 idea/testData/inspectionsLocal/unnecessaryVariable/ifElse4.kt.after create mode 100644 idea/testData/inspectionsLocal/unnecessaryVariable/ifElse5.kt create mode 100644 idea/testData/inspectionsLocal/unnecessaryVariable/ifElse5.kt.after create mode 100644 idea/testData/inspectionsLocal/unnecessaryVariable/lambda.kt create mode 100644 idea/testData/inspectionsLocal/unnecessaryVariable/lambda.kt.after create mode 100644 idea/testData/inspectionsLocal/unnecessaryVariable/lambda2.kt create mode 100644 idea/testData/inspectionsLocal/unnecessaryVariable/lambda2.kt.after create mode 100644 idea/testData/inspectionsLocal/unnecessaryVariable/try.kt create mode 100644 idea/testData/inspectionsLocal/unnecessaryVariable/try.kt.after create mode 100644 idea/testData/inspectionsLocal/unnecessaryVariable/when.kt create mode 100644 idea/testData/inspectionsLocal/unnecessaryVariable/when.kt.after diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/UnnecessaryVariableInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/UnnecessaryVariableInspection.kt index f4ea4e9c443..ea2461f8dc6 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/UnnecessaryVariableInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/UnnecessaryVariableInspection.kt @@ -16,8 +16,10 @@ package org.jetbrains.kotlin.idea.inspections +import com.intellij.codeInspection.ProblemHighlightType import com.intellij.openapi.editor.Editor import com.intellij.openapi.project.Project +import com.intellij.psi.impl.source.tree.LeafPsiElement import com.intellij.psi.search.LocalSearchScope import com.intellij.psi.search.searches.ReferencesSearch import org.jetbrains.kotlin.descriptors.FunctionDescriptor @@ -27,15 +29,18 @@ import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall import org.jetbrains.kotlin.idea.core.NewDeclarationNameValidator import org.jetbrains.kotlin.idea.refactoring.inline.KotlinInlineValHandler +import org.jetbrains.kotlin.idea.util.getLineCount import org.jetbrains.kotlin.idea.util.nameIdentifierTextRangeInThis import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.psiUtil.anyDescendantOfType import org.jetbrains.kotlin.psi.psiUtil.getNextSiblingIgnoringWhitespaceAndComments import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType import org.jetbrains.kotlin.resolve.BindingContext.DECLARATION_TO_DESCRIPTOR import org.jetbrains.kotlin.resolve.BindingContext.REFERENCE_TARGET import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode +import org.jetbrains.kotlin.utils.addToStdlib.safeAs class UnnecessaryVariableInspection : AbstractApplicabilityBasedInspection(KtProperty::class.java) { @@ -43,6 +48,11 @@ class UnnecessaryVariableInspection : AbstractApplicabilityBasedInspection KotlinBundle.message("variable.used.only.in.following.return.and.should.be.inlined") Status.EXACT_COPY -> KotlinBundle.message( @@ -60,6 +70,11 @@ class UnnecessaryVariableInspection : AbstractApplicabilityBasedInspection()?.getLineCount()?.let { it > 1 } == true + + private fun KtExpression.hasMultiLineBlock(): Boolean = anyDescendantOfType { it.startsMultilineBlock() } + companion object { private enum class Status { RETURN_ONLY, diff --git a/idea/testData/inspectionsLocal/unnecessaryVariable/ifElse.kt b/idea/testData/inspectionsLocal/unnecessaryVariable/ifElse.kt new file mode 100644 index 00000000000..abdc905270d --- /dev/null +++ b/idea/testData/inspectionsLocal/unnecessaryVariable/ifElse.kt @@ -0,0 +1,13 @@ +// HIGHLIGHT: INFORMATION +fun test(b: Boolean): Int { + val result = if (b) { + foo() + } else { + bar() + } + return result +} + +fun foo() = 1 + +fun bar() = 2 \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/unnecessaryVariable/ifElse.kt.after b/idea/testData/inspectionsLocal/unnecessaryVariable/ifElse.kt.after new file mode 100644 index 00000000000..5096d02ca92 --- /dev/null +++ b/idea/testData/inspectionsLocal/unnecessaryVariable/ifElse.kt.after @@ -0,0 +1,12 @@ +// HIGHLIGHT: INFORMATION +fun test(b: Boolean): Int { + return if (b) { + foo() + } else { + bar() + } +} + +fun foo() = 1 + +fun bar() = 2 \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/unnecessaryVariable/ifElse2.kt b/idea/testData/inspectionsLocal/unnecessaryVariable/ifElse2.kt new file mode 100644 index 00000000000..0a008349cea --- /dev/null +++ b/idea/testData/inspectionsLocal/unnecessaryVariable/ifElse2.kt @@ -0,0 +1,9 @@ +// HIGHLIGHT: GENERIC_ERROR_OR_WARNING +fun test(b: Boolean): Int { + val result = if (b) foo() else bar() + return result +} + +fun foo() = 1 + +fun bar() = 2 \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/unnecessaryVariable/ifElse2.kt.after b/idea/testData/inspectionsLocal/unnecessaryVariable/ifElse2.kt.after new file mode 100644 index 00000000000..5441308b661 --- /dev/null +++ b/idea/testData/inspectionsLocal/unnecessaryVariable/ifElse2.kt.after @@ -0,0 +1,8 @@ +// HIGHLIGHT: GENERIC_ERROR_OR_WARNING +fun test(b: Boolean): Int { + return if (b) foo() else bar() +} + +fun foo() = 1 + +fun bar() = 2 \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/unnecessaryVariable/ifElse3.kt b/idea/testData/inspectionsLocal/unnecessaryVariable/ifElse3.kt new file mode 100644 index 00000000000..afd65d5d8d9 --- /dev/null +++ b/idea/testData/inspectionsLocal/unnecessaryVariable/ifElse3.kt @@ -0,0 +1,12 @@ +// HIGHLIGHT: GENERIC_ERROR_OR_WARNING +fun test(b: Boolean): Int { + val result = if (b) + foo() + else + bar() + return result +} + +fun foo() = 1 + +fun bar() = 2 \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/unnecessaryVariable/ifElse3.kt.after b/idea/testData/inspectionsLocal/unnecessaryVariable/ifElse3.kt.after new file mode 100644 index 00000000000..6745b2edc3f --- /dev/null +++ b/idea/testData/inspectionsLocal/unnecessaryVariable/ifElse3.kt.after @@ -0,0 +1,11 @@ +// HIGHLIGHT: GENERIC_ERROR_OR_WARNING +fun test(b: Boolean): Int { + return if (b) + foo() + else + bar() +} + +fun foo() = 1 + +fun bar() = 2 \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/unnecessaryVariable/ifElse4.kt b/idea/testData/inspectionsLocal/unnecessaryVariable/ifElse4.kt new file mode 100644 index 00000000000..9d3e423c4a8 --- /dev/null +++ b/idea/testData/inspectionsLocal/unnecessaryVariable/ifElse4.kt @@ -0,0 +1,14 @@ +// HIGHLIGHT: GENERIC_ERROR_OR_WARNING +fun test(b: Boolean): Int { + val result = if (b) + baz { foo() } + else + baz { bar() } + return result +} + +fun foo() = 1 + +fun bar() = 2 + +fun baz(f: () -> Int) = f() \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/unnecessaryVariable/ifElse4.kt.after b/idea/testData/inspectionsLocal/unnecessaryVariable/ifElse4.kt.after new file mode 100644 index 00000000000..11b0ebded85 --- /dev/null +++ b/idea/testData/inspectionsLocal/unnecessaryVariable/ifElse4.kt.after @@ -0,0 +1,13 @@ +// HIGHLIGHT: GENERIC_ERROR_OR_WARNING +fun test(b: Boolean): Int { + return if (b) + baz { foo() } + else + baz { bar() } +} + +fun foo() = 1 + +fun bar() = 2 + +fun baz(f: () -> Int) = f() \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/unnecessaryVariable/ifElse5.kt b/idea/testData/inspectionsLocal/unnecessaryVariable/ifElse5.kt new file mode 100644 index 00000000000..8a5d38eaa58 --- /dev/null +++ b/idea/testData/inspectionsLocal/unnecessaryVariable/ifElse5.kt @@ -0,0 +1,18 @@ +// HIGHLIGHT: INFORMATION +fun test(b: Boolean): Int { + val result = if (b) + baz { + foo() + } + else + baz { + bar() + } + return result +} + +fun foo() = 1 + +fun bar() = 2 + +fun baz(f: () -> Int) = f() \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/unnecessaryVariable/ifElse5.kt.after b/idea/testData/inspectionsLocal/unnecessaryVariable/ifElse5.kt.after new file mode 100644 index 00000000000..c21c1dbb9dc --- /dev/null +++ b/idea/testData/inspectionsLocal/unnecessaryVariable/ifElse5.kt.after @@ -0,0 +1,17 @@ +// HIGHLIGHT: INFORMATION +fun test(b: Boolean): Int { + return if (b) + baz { + foo() + } + else + baz { + bar() + } +} + +fun foo() = 1 + +fun bar() = 2 + +fun baz(f: () -> Int) = f() \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/unnecessaryVariable/lambda.kt b/idea/testData/inspectionsLocal/unnecessaryVariable/lambda.kt new file mode 100644 index 00000000000..a1baacfdc76 --- /dev/null +++ b/idea/testData/inspectionsLocal/unnecessaryVariable/lambda.kt @@ -0,0 +1,9 @@ +// HIGHLIGHT: GENERIC_ERROR_OR_WARNING +fun test(): Int { + val result = foo { bar() } + return result +} + +fun foo(f: () -> Int) = f() + +fun bar() = 1 \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/unnecessaryVariable/lambda.kt.after b/idea/testData/inspectionsLocal/unnecessaryVariable/lambda.kt.after new file mode 100644 index 00000000000..af66704d3fb --- /dev/null +++ b/idea/testData/inspectionsLocal/unnecessaryVariable/lambda.kt.after @@ -0,0 +1,8 @@ +// HIGHLIGHT: GENERIC_ERROR_OR_WARNING +fun test(): Int { + return foo { bar() } +} + +fun foo(f: () -> Int) = f() + +fun bar() = 1 \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/unnecessaryVariable/lambda2.kt b/idea/testData/inspectionsLocal/unnecessaryVariable/lambda2.kt new file mode 100644 index 00000000000..f8262703880 --- /dev/null +++ b/idea/testData/inspectionsLocal/unnecessaryVariable/lambda2.kt @@ -0,0 +1,11 @@ +// HIGHLIGHT: INFORMATION +fun test(): Int { + val result = foo { + bar() + } + return result +} + +fun foo(f: () -> Int) = f() + +fun bar() = 1 \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/unnecessaryVariable/lambda2.kt.after b/idea/testData/inspectionsLocal/unnecessaryVariable/lambda2.kt.after new file mode 100644 index 00000000000..2a6341e8ec7 --- /dev/null +++ b/idea/testData/inspectionsLocal/unnecessaryVariable/lambda2.kt.after @@ -0,0 +1,10 @@ +// HIGHLIGHT: INFORMATION +fun test(): Int { + return foo { + bar() + } +} + +fun foo(f: () -> Int) = f() + +fun bar() = 1 \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/unnecessaryVariable/try.kt b/idea/testData/inspectionsLocal/unnecessaryVariable/try.kt new file mode 100644 index 00000000000..d5fd0f1631a --- /dev/null +++ b/idea/testData/inspectionsLocal/unnecessaryVariable/try.kt @@ -0,0 +1,13 @@ +// HIGHLIGHT: INFORMATION +fun test(): Int { + val result = try { + foo() + } finally { + bar() + } + return result +} + +fun foo() = 1 + +fun bar() {} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/unnecessaryVariable/try.kt.after b/idea/testData/inspectionsLocal/unnecessaryVariable/try.kt.after new file mode 100644 index 00000000000..454f90c3ad5 --- /dev/null +++ b/idea/testData/inspectionsLocal/unnecessaryVariable/try.kt.after @@ -0,0 +1,12 @@ +// HIGHLIGHT: INFORMATION +fun test(): Int { + return try { + foo() + } finally { + bar() + } +} + +fun foo() = 1 + +fun bar() {} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/unnecessaryVariable/when.kt b/idea/testData/inspectionsLocal/unnecessaryVariable/when.kt new file mode 100644 index 00000000000..150c7217a06 --- /dev/null +++ b/idea/testData/inspectionsLocal/unnecessaryVariable/when.kt @@ -0,0 +1,12 @@ +// HIGHLIGHT: INFORMATION +fun test(i: Int): Int { + val result = when (i) { + 1 -> foo() + else -> bar() + } + return result +} + +fun foo() = 1 + +fun bar() = 2 \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/unnecessaryVariable/when.kt.after b/idea/testData/inspectionsLocal/unnecessaryVariable/when.kt.after new file mode 100644 index 00000000000..477c025c385 --- /dev/null +++ b/idea/testData/inspectionsLocal/unnecessaryVariable/when.kt.after @@ -0,0 +1,11 @@ +// HIGHLIGHT: INFORMATION +fun test(i: Int): Int { + return when (i) { + 1 -> foo() + else -> bar() + } +} + +fun foo() = 1 + +fun bar() = 2 \ 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 dec1909bd56..a4f9880f266 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java @@ -14083,11 +14083,46 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest { runTest("idea/testData/inspectionsLocal/unnecessaryVariable/copyOfVar.kt"); } + @TestMetadata("ifElse.kt") + public void testIfElse() throws Exception { + runTest("idea/testData/inspectionsLocal/unnecessaryVariable/ifElse.kt"); + } + + @TestMetadata("ifElse2.kt") + public void testIfElse2() throws Exception { + runTest("idea/testData/inspectionsLocal/unnecessaryVariable/ifElse2.kt"); + } + + @TestMetadata("ifElse3.kt") + public void testIfElse3() throws Exception { + runTest("idea/testData/inspectionsLocal/unnecessaryVariable/ifElse3.kt"); + } + + @TestMetadata("ifElse4.kt") + public void testIfElse4() throws Exception { + runTest("idea/testData/inspectionsLocal/unnecessaryVariable/ifElse4.kt"); + } + + @TestMetadata("ifElse5.kt") + public void testIfElse5() throws Exception { + runTest("idea/testData/inspectionsLocal/unnecessaryVariable/ifElse5.kt"); + } + @TestMetadata("it.kt") public void testIt() throws Exception { runTest("idea/testData/inspectionsLocal/unnecessaryVariable/it.kt"); } + @TestMetadata("lambda.kt") + public void testLambda() throws Exception { + runTest("idea/testData/inspectionsLocal/unnecessaryVariable/lambda.kt"); + } + + @TestMetadata("lambda2.kt") + public void testLambda2() throws Exception { + runTest("idea/testData/inspectionsLocal/unnecessaryVariable/lambda2.kt"); + } + @TestMetadata("override.kt") public void testOverride() throws Exception { runTest("idea/testData/inspectionsLocal/unnecessaryVariable/override.kt"); @@ -14118,11 +14153,21 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest { runTest("idea/testData/inspectionsLocal/unnecessaryVariable/topLevelCopy.kt"); } + @TestMetadata("try.kt") + public void testTry() throws Exception { + runTest("idea/testData/inspectionsLocal/unnecessaryVariable/try.kt"); + } + @TestMetadata("varCopy.kt") public void testVarCopy() throws Exception { runTest("idea/testData/inspectionsLocal/unnecessaryVariable/varCopy.kt"); } + @TestMetadata("when.kt") + public void testWhen() throws Exception { + runTest("idea/testData/inspectionsLocal/unnecessaryVariable/when.kt"); + } + @TestMetadata("whenSubject.kt") public void testWhenSubject() throws Exception { runTest("idea/testData/inspectionsLocal/unnecessaryVariable/whenSubject.kt");