"Call chain may be simplified": fix false positive on Java Map
So #KT-25089 Fixed
This commit is contained in:
committed by
Mikhail Glukhikh
parent
c9a784ebb0
commit
a059d50c8f
+11
-7
@@ -8,10 +8,13 @@ package org.jetbrains.kotlin.idea.inspections.collections
|
|||||||
import com.intellij.codeInspection.ProblemHighlightType
|
import com.intellij.codeInspection.ProblemHighlightType
|
||||||
import com.intellij.codeInspection.ProblemsHolder
|
import com.intellij.codeInspection.ProblemsHolder
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.js.resolve.JsPlatform
|
import org.jetbrains.kotlin.js.resolve.JsPlatform
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||||
import org.jetbrains.kotlin.psi.qualifiedExpressionVisitor
|
import org.jetbrains.kotlin.psi.qualifiedExpressionVisitor
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.isSubclassOf
|
||||||
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.typeUtil.builtIns
|
import org.jetbrains.kotlin.types.typeUtil.builtIns
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
||||||
|
|
||||||
@@ -20,16 +23,12 @@ class SimplifiableCallChainInspection : AbstractCallChainChecker() {
|
|||||||
qualifiedExpressionVisitor(fun(expression) {
|
qualifiedExpressionVisitor(fun(expression) {
|
||||||
val conversion = findQualifiedConversion(expression, conversionGroups) check@{ conversion, firstResolvedCall, _, context ->
|
val conversion = findQualifiedConversion(expression, conversionGroups) check@{ conversion, firstResolvedCall, _, context ->
|
||||||
// Do not apply on maps due to lack of relevant stdlib functions
|
// Do not apply on maps due to lack of relevant stdlib functions
|
||||||
val builtIns = context[BindingContext.EXPRESSION_TYPE_INFO, expression]?.type?.builtIns ?: return@check false
|
|
||||||
val firstReceiverType = firstResolvedCall.extensionReceiver?.type
|
val firstReceiverType = firstResolvedCall.extensionReceiver?.type
|
||||||
if (firstReceiverType != null) {
|
if (firstReceiverType != null) {
|
||||||
if (conversion.replacement == "mapNotNull" && KotlinBuiltIns.isPrimitiveArray(firstReceiverType)) return@check false
|
if (conversion.replacement == "mapNotNull" && KotlinBuiltIns.isPrimitiveArray(firstReceiverType)) return@check false
|
||||||
|
val builtIns = context[BindingContext.EXPRESSION_TYPE_INFO, expression]?.type?.builtIns ?: return@check false
|
||||||
val firstReceiverRawType = firstReceiverType.constructor.declarationDescriptor?.defaultType
|
val firstReceiverRawType = firstReceiverType.constructor.declarationDescriptor?.defaultType
|
||||||
if (firstReceiverRawType != null) {
|
if (firstReceiverRawType.isMap(builtIns)) return@check false
|
||||||
if (firstReceiverRawType.isSubtypeOf(builtIns.map.defaultType) ||
|
|
||||||
firstReceiverRawType.isSubtypeOf(builtIns.mutableMap.defaultType)
|
|
||||||
) return@check false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (conversion.replacement.startsWith("joinTo")) {
|
if (conversion.replacement.startsWith("joinTo")) {
|
||||||
// Function parameter in map must have String result type
|
// Function parameter in map must have String result type
|
||||||
@@ -83,4 +82,9 @@ class SimplifiableCallChainInspection : AbstractCallChainChecker() {
|
|||||||
Conversion("kotlin.collections.listOf", "kotlin.collections.filterNotNull", "listOfNotNull")
|
Conversion("kotlin.collections.listOf", "kotlin.collections.filterNotNull", "listOfNotNull")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun KotlinType?.isMap(builtIns: KotlinBuiltIns): Boolean {
|
||||||
|
val classDescriptor = this?.constructor?.declarationDescriptor as? ClassDescriptor ?: return false
|
||||||
|
return classDescriptor.name.asString().endsWith("Map") && classDescriptor.isSubclassOf(builtIns.map)
|
||||||
|
}
|
||||||
|
|||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
// PROBLEM: none
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
fun test(data: HashMap<String, String>) {
|
||||||
|
val result = data.<caret>map { "${it.key}: ${it.value}" }.joinToString("\n")
|
||||||
|
}
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
// PROBLEM: none
|
||||||
|
// WITH_RUNTIME
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
class MyMap: HashMap<String, String>()
|
||||||
|
|
||||||
|
fun test(data: MyMap) {
|
||||||
|
val result = data.<caret>map { "${it.key}: ${it.value}" }.joinToString("\n")
|
||||||
|
}
|
||||||
+10
@@ -579,6 +579,16 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest {
|
|||||||
runTest("idea/testData/inspectionsLocal/collections/simplifiableCallChain/joinToString.kt");
|
runTest("idea/testData/inspectionsLocal/collections/simplifiableCallChain/joinToString.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("joinToStringOnHashMap.kt")
|
||||||
|
public void testJoinToStringOnHashMap() throws Exception {
|
||||||
|
runTest("idea/testData/inspectionsLocal/collections/simplifiableCallChain/joinToStringOnHashMap.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("joinToStringOnHashMap2.kt")
|
||||||
|
public void testJoinToStringOnHashMap2() throws Exception {
|
||||||
|
runTest("idea/testData/inspectionsLocal/collections/simplifiableCallChain/joinToStringOnHashMap2.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("joinToStringOnMap.kt")
|
@TestMetadata("joinToStringOnMap.kt")
|
||||||
public void testJoinToStringOnMap() throws Exception {
|
public void testJoinToStringOnMap() throws Exception {
|
||||||
runTest("idea/testData/inspectionsLocal/collections/simplifiableCallChain/joinToStringOnMap.kt");
|
runTest("idea/testData/inspectionsLocal/collections/simplifiableCallChain/joinToStringOnMap.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user