Useless call on collection: propose 'Replace with toList()' instead of 'Remove useless call' if receiver is array type
#KT-38961 Fixed
This commit is contained in:
committed by
Nikita Bobko
parent
994897cee9
commit
081d6c1dff
+12
-1
@@ -7,7 +7,9 @@ package org.jetbrains.kotlin.idea.inspections.collections
|
|||||||
|
|
||||||
import com.intellij.codeInspection.ProblemHighlightType
|
import com.intellij.codeInspection.ProblemHighlightType
|
||||||
import com.intellij.openapi.util.TextRange
|
import com.intellij.openapi.util.TextRange
|
||||||
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.idea.KotlinBundle
|
import org.jetbrains.kotlin.idea.KotlinBundle
|
||||||
|
import org.jetbrains.kotlin.idea.quickfix.ReplaceSelectorOfQualifiedExpressionFix
|
||||||
import org.jetbrains.kotlin.psi.KtExpression
|
import org.jetbrains.kotlin.psi.KtExpression
|
||||||
import org.jetbrains.kotlin.psi.KtQualifiedExpression
|
import org.jetbrains.kotlin.psi.KtQualifiedExpression
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||||
@@ -15,6 +17,8 @@ import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
|||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getType
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getType
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||||
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.TypeUtils
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
import org.jetbrains.kotlin.types.isFlexible
|
import org.jetbrains.kotlin.types.isFlexible
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
||||||
@@ -68,6 +72,11 @@ class UselessCallOnCollectionInspection : AbstractUselessCallInspection() {
|
|||||||
)
|
)
|
||||||
holder.registerProblem(descriptor)
|
holder.registerProblem(descriptor)
|
||||||
} else {
|
} else {
|
||||||
|
val fix = if (resolvedCall.resultingDescriptor.returnType.isList() && !receiverType.isList()) {
|
||||||
|
ReplaceSelectorOfQualifiedExpressionFix("toList()")
|
||||||
|
} else {
|
||||||
|
RemoveUselessCallFix()
|
||||||
|
}
|
||||||
val descriptor = holder.manager.createProblemDescriptor(
|
val descriptor = holder.manager.createProblemDescriptor(
|
||||||
expression,
|
expression,
|
||||||
TextRange(
|
TextRange(
|
||||||
@@ -77,9 +86,11 @@ class UselessCallOnCollectionInspection : AbstractUselessCallInspection() {
|
|||||||
KotlinBundle.message("useless.call.on.collection.type"),
|
KotlinBundle.message("useless.call.on.collection.type"),
|
||||||
ProblemHighlightType.LIKE_UNUSED_SYMBOL,
|
ProblemHighlightType.LIKE_UNUSED_SYMBOL,
|
||||||
isOnTheFly,
|
isOnTheFly,
|
||||||
RemoveUselessCallFix()
|
fix
|
||||||
)
|
)
|
||||||
holder.registerProblem(descriptor)
|
holder.registerProblem(descriptor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun KotlinType?.isList() = this?.constructor?.declarationDescriptor?.fqNameSafe == KotlinBuiltIns.FQ_NAMES.list
|
||||||
}
|
}
|
||||||
+26
@@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* 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.quickfix
|
||||||
|
|
||||||
|
import com.intellij.codeInspection.LocalQuickFix
|
||||||
|
import com.intellij.codeInspection.ProblemDescriptor
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import org.jetbrains.kotlin.idea.KotlinBundle
|
||||||
|
import org.jetbrains.kotlin.psi.KtPsiFactory
|
||||||
|
import org.jetbrains.kotlin.psi.KtQualifiedExpression
|
||||||
|
import org.jetbrains.kotlin.psi.createExpressionByPattern
|
||||||
|
|
||||||
|
class ReplaceSelectorOfQualifiedExpressionFix(private val newSelector: String) : LocalQuickFix {
|
||||||
|
override fun getName() = KotlinBundle.message("replace.with.0", newSelector)
|
||||||
|
|
||||||
|
override fun getFamilyName() = name
|
||||||
|
|
||||||
|
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
|
||||||
|
(descriptor.psiElement as? KtQualifiedExpression)?.let {
|
||||||
|
it.replace(KtPsiFactory(it).createExpressionByPattern("$0.$newSelector", it.receiverExpression))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Vendored
+3
@@ -0,0 +1,3 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
val x: List<String> = arrayOf("1").<caret>filterIsInstance<String>()
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
val x: List<String> = arrayOf("1").toList()
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
val x: List<String> = arrayOf("1").<caret>filterNotNull()
|
||||||
Vendored
+3
@@ -0,0 +1,3 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
val x: List<String> = arrayOf("1").toList()
|
||||||
Vendored
+5
@@ -0,0 +1,5 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
fun test(iterable: Iterable<Int>): List<Int> {
|
||||||
|
return iterable.<caret>filterNotNull()
|
||||||
|
}
|
||||||
Vendored
+5
@@ -0,0 +1,5 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
fun test(iterable: Iterable<Int>): List<Int> {
|
||||||
|
return iterable.toList()
|
||||||
|
}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
fun test(): List<Int> {
|
||||||
|
return setOf(1).<caret>filterNotNull()
|
||||||
|
}
|
||||||
Vendored
+5
@@ -0,0 +1,5 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
fun test(): List<Int> {
|
||||||
|
return setOf(1).toList()
|
||||||
|
}
|
||||||
+20
@@ -1935,6 +1935,11 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest {
|
|||||||
runTest("idea/testData/inspectionsLocal/collections/uselessCallOnCollection/FilterIsExactInstanceFake.kt");
|
runTest("idea/testData/inspectionsLocal/collections/uselessCallOnCollection/FilterIsExactInstanceFake.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("FilterIsExactInstanceOnArray.kt")
|
||||||
|
public void testFilterIsExactInstanceOnArray() throws Exception {
|
||||||
|
runTest("idea/testData/inspectionsLocal/collections/uselessCallOnCollection/FilterIsExactInstanceOnArray.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("FilterIsForFlexible.kt")
|
@TestMetadata("FilterIsForFlexible.kt")
|
||||||
public void testFilterIsForFlexible() throws Exception {
|
public void testFilterIsForFlexible() throws Exception {
|
||||||
runTest("idea/testData/inspectionsLocal/collections/uselessCallOnCollection/FilterIsForFlexible.kt");
|
runTest("idea/testData/inspectionsLocal/collections/uselessCallOnCollection/FilterIsForFlexible.kt");
|
||||||
@@ -1960,6 +1965,21 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest {
|
|||||||
runTest("idea/testData/inspectionsLocal/collections/uselessCallOnCollection/filterNotNullFake.kt");
|
runTest("idea/testData/inspectionsLocal/collections/uselessCallOnCollection/filterNotNullFake.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("FilterNotNullOnArray.kt")
|
||||||
|
public void testFilterNotNullOnArray() throws Exception {
|
||||||
|
runTest("idea/testData/inspectionsLocal/collections/uselessCallOnCollection/FilterNotNullOnArray.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("FilterNotNullOnIterable.kt")
|
||||||
|
public void testFilterNotNullOnIterable() throws Exception {
|
||||||
|
runTest("idea/testData/inspectionsLocal/collections/uselessCallOnCollection/FilterNotNullOnIterable.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("FilterNotNullOnSet.kt")
|
||||||
|
public void testFilterNotNullOnSet() throws Exception {
|
||||||
|
runTest("idea/testData/inspectionsLocal/collections/uselessCallOnCollection/FilterNotNullOnSet.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("MapIndexedNotNullTo.kt")
|
@TestMetadata("MapIndexedNotNullTo.kt")
|
||||||
public void testMapIndexedNotNullTo() throws Exception {
|
public void testMapIndexedNotNullTo() throws Exception {
|
||||||
runTest("idea/testData/inspectionsLocal/collections/uselessCallOnCollection/MapIndexedNotNullTo.kt");
|
runTest("idea/testData/inspectionsLocal/collections/uselessCallOnCollection/MapIndexedNotNullTo.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user