Unnecessary local variable: highlight with INFORMATION level when initializer has any multi-line blocks (#3359)
#KT-26752 Fixed
This commit is contained in:
committed by
GitHub
parent
e82857996f
commit
b9a4b60b93
@@ -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>(KtProperty::class.java) {
|
||||
|
||||
@@ -43,6 +48,11 @@ class UnnecessaryVariableInspection : AbstractApplicabilityBasedInspection<KtPro
|
||||
|
||||
override fun inspectionHighlightRangeInElement(element: KtProperty) = element.nameIdentifierTextRangeInThis()
|
||||
|
||||
override fun inspectionHighlightType(element: KtProperty): ProblemHighlightType {
|
||||
val hasMultiLineBlock = element.initializer?.hasMultiLineBlock() == true
|
||||
return if (hasMultiLineBlock) ProblemHighlightType.INFORMATION else ProblemHighlightType.GENERIC_ERROR_OR_WARNING
|
||||
}
|
||||
|
||||
override fun inspectionText(element: KtProperty) = when (statusFor(element)) {
|
||||
Status.RETURN_ONLY -> KotlinBundle.message("variable.used.only.in.following.return.and.should.be.inlined")
|
||||
Status.EXACT_COPY -> KotlinBundle.message(
|
||||
@@ -60,6 +70,11 @@ class UnnecessaryVariableInspection : AbstractApplicabilityBasedInspection<KtPro
|
||||
KotlinInlineValHandler(withPrompt = false).inlineElement(project, editor, element)
|
||||
}
|
||||
|
||||
private fun LeafPsiElement.startsMultilineBlock(): Boolean =
|
||||
node.elementType == KtTokens.LBRACE && parent.safeAs<KtExpression>()?.getLineCount()?.let { it > 1 } == true
|
||||
|
||||
private fun KtExpression.hasMultiLineBlock(): Boolean = anyDescendantOfType<LeafPsiElement> { it.startsMultilineBlock() }
|
||||
|
||||
companion object {
|
||||
private enum class Status {
|
||||
RETURN_ONLY,
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
// HIGHLIGHT: INFORMATION
|
||||
fun test(b: Boolean): Int {
|
||||
val <caret>result = if (b) {
|
||||
foo()
|
||||
} else {
|
||||
bar()
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
fun foo() = 1
|
||||
|
||||
fun bar() = 2
|
||||
@@ -0,0 +1,12 @@
|
||||
// HIGHLIGHT: INFORMATION
|
||||
fun test(b: Boolean): Int {
|
||||
return if (b) {
|
||||
foo()
|
||||
} else {
|
||||
bar()
|
||||
}
|
||||
}
|
||||
|
||||
fun foo() = 1
|
||||
|
||||
fun bar() = 2
|
||||
@@ -0,0 +1,9 @@
|
||||
// HIGHLIGHT: GENERIC_ERROR_OR_WARNING
|
||||
fun test(b: Boolean): Int {
|
||||
val <caret>result = if (b) foo() else bar()
|
||||
return result
|
||||
}
|
||||
|
||||
fun foo() = 1
|
||||
|
||||
fun bar() = 2
|
||||
@@ -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
|
||||
@@ -0,0 +1,12 @@
|
||||
// HIGHLIGHT: GENERIC_ERROR_OR_WARNING
|
||||
fun test(b: Boolean): Int {
|
||||
val <caret>result = if (b)
|
||||
foo()
|
||||
else
|
||||
bar()
|
||||
return result
|
||||
}
|
||||
|
||||
fun foo() = 1
|
||||
|
||||
fun bar() = 2
|
||||
@@ -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
|
||||
@@ -0,0 +1,14 @@
|
||||
// HIGHLIGHT: GENERIC_ERROR_OR_WARNING
|
||||
fun test(b: Boolean): Int {
|
||||
val <caret>result = if (b)
|
||||
baz { foo() }
|
||||
else
|
||||
baz { bar() }
|
||||
return result
|
||||
}
|
||||
|
||||
fun foo() = 1
|
||||
|
||||
fun bar() = 2
|
||||
|
||||
fun baz(f: () -> Int) = f()
|
||||
@@ -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()
|
||||
@@ -0,0 +1,18 @@
|
||||
// HIGHLIGHT: INFORMATION
|
||||
fun test(b: Boolean): Int {
|
||||
val <caret>result = if (b)
|
||||
baz {
|
||||
foo()
|
||||
}
|
||||
else
|
||||
baz {
|
||||
bar()
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
fun foo() = 1
|
||||
|
||||
fun bar() = 2
|
||||
|
||||
fun baz(f: () -> Int) = f()
|
||||
@@ -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()
|
||||
@@ -0,0 +1,9 @@
|
||||
// HIGHLIGHT: GENERIC_ERROR_OR_WARNING
|
||||
fun test(): Int {
|
||||
val <caret>result = foo { bar() }
|
||||
return result
|
||||
}
|
||||
|
||||
fun foo(f: () -> Int) = f()
|
||||
|
||||
fun bar() = 1
|
||||
@@ -0,0 +1,8 @@
|
||||
// HIGHLIGHT: GENERIC_ERROR_OR_WARNING
|
||||
fun test(): Int {
|
||||
return foo { bar() }
|
||||
}
|
||||
|
||||
fun foo(f: () -> Int) = f()
|
||||
|
||||
fun bar() = 1
|
||||
@@ -0,0 +1,11 @@
|
||||
// HIGHLIGHT: INFORMATION
|
||||
fun test(): Int {
|
||||
val <caret>result = foo {
|
||||
bar()
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
fun foo(f: () -> Int) = f()
|
||||
|
||||
fun bar() = 1
|
||||
@@ -0,0 +1,10 @@
|
||||
// HIGHLIGHT: INFORMATION
|
||||
fun test(): Int {
|
||||
return foo {
|
||||
bar()
|
||||
}
|
||||
}
|
||||
|
||||
fun foo(f: () -> Int) = f()
|
||||
|
||||
fun bar() = 1
|
||||
@@ -0,0 +1,13 @@
|
||||
// HIGHLIGHT: INFORMATION
|
||||
fun test(): Int {
|
||||
val <caret>result = try {
|
||||
foo()
|
||||
} finally {
|
||||
bar()
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
fun foo() = 1
|
||||
|
||||
fun bar() {}
|
||||
@@ -0,0 +1,12 @@
|
||||
// HIGHLIGHT: INFORMATION
|
||||
fun test(): Int {
|
||||
return try {
|
||||
foo()
|
||||
} finally {
|
||||
bar()
|
||||
}
|
||||
}
|
||||
|
||||
fun foo() = 1
|
||||
|
||||
fun bar() {}
|
||||
@@ -0,0 +1,12 @@
|
||||
// HIGHLIGHT: INFORMATION
|
||||
fun test(i: Int): Int {
|
||||
val <caret>result = when (i) {
|
||||
1 -> foo()
|
||||
else -> bar()
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
fun foo() = 1
|
||||
|
||||
fun bar() = 2
|
||||
@@ -0,0 +1,11 @@
|
||||
// HIGHLIGHT: INFORMATION
|
||||
fun test(i: Int): Int {
|
||||
return when (i) {
|
||||
1 -> foo()
|
||||
else -> bar()
|
||||
}
|
||||
}
|
||||
|
||||
fun foo() = 1
|
||||
|
||||
fun bar() = 2
|
||||
+45
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user