Replace assert boolean with assert equality: do not report when arguments type are not subtype
#KT-30761 Fixed
This commit is contained in:
committed by
Mikhail Glukhikh
parent
93d854362b
commit
849d18669b
+23
-4
@@ -9,16 +9,23 @@ import com.intellij.codeInsight.actions.OptimizeImportsProcessor
|
|||||||
import com.intellij.openapi.editor.Editor
|
import com.intellij.openapi.editor.Editor
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
|
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||||
import org.jetbrains.kotlin.idea.core.ShortenReferences
|
import org.jetbrains.kotlin.idea.core.ShortenReferences
|
||||||
import org.jetbrains.kotlin.idea.core.replaced
|
import org.jetbrains.kotlin.idea.core.replaced
|
||||||
import org.jetbrains.kotlin.idea.intentions.getCallableDescriptor
|
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||||
|
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||||
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
||||||
|
|
||||||
class ReplaceAssertBooleanWithAssertEqualityInspection : AbstractApplicabilityBasedInspection<KtCallExpression>(KtCallExpression::class.java) {
|
class ReplaceAssertBooleanWithAssertEqualityInspection : AbstractApplicabilityBasedInspection<KtCallExpression>(
|
||||||
|
KtCallExpression::class.java
|
||||||
|
) {
|
||||||
override fun inspectionText(element: KtCallExpression) = "Replace assert boolean with assert equality"
|
override fun inspectionText(element: KtCallExpression) = "Replace assert boolean with assert equality"
|
||||||
|
|
||||||
override val defaultFixText = "Replace assert boolean with assert equality"
|
override val defaultFixText = "Replace assert boolean with assert equality"
|
||||||
@@ -58,17 +65,29 @@ class ReplaceAssertBooleanWithAssertEqualityInspection : AbstractApplicabilityBa
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getCallableDescriptor()?.containingDeclaration?.fqNameSafe != FqName(kotlinTestPackage)) {
|
val context = analyze(BodyResolveMode.PARTIAL)
|
||||||
|
if (descriptor(context)?.containingDeclaration?.fqNameSafe != FqName(kotlinTestPackage)) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (valueArguments.size != 1 && valueArguments.size != 2) return null
|
if (valueArguments.size != 1 && valueArguments.size != 2) return null
|
||||||
val binaryExpression = valueArguments.first().getArgumentExpression() as? KtBinaryExpression ?: return null
|
val binaryExpression = valueArguments.first().getArgumentExpression() as? KtBinaryExpression ?: return null
|
||||||
|
val leftType = binaryExpression.left?.type(context) ?: return null
|
||||||
|
val rightType = binaryExpression.right?.type(context) ?: return null
|
||||||
|
if (!leftType.isSubtypeOf(rightType) && !rightType.isSubtypeOf(leftType)) return null
|
||||||
val operationToken = binaryExpression.operationToken
|
val operationToken = binaryExpression.operationToken
|
||||||
|
|
||||||
return assertionMap[Pair(referencedName, operationToken)]
|
return assertionMap[Pair(referencedName, operationToken)]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun KtExpression.descriptor(context: BindingContext): CallableDescriptor? {
|
||||||
|
return getResolvedCall(context)?.resultingDescriptor
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun KtExpression.type(context: BindingContext): KotlinType? {
|
||||||
|
return descriptor(context)?.returnType
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val kotlinTestPackage = "kotlin.test"
|
private const val kotlinTestPackage = "kotlin.test"
|
||||||
|
|
||||||
|
|||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
// RUNTIME_WITH_KOTLIN_TEST
|
||||||
|
// PROBLEM: none
|
||||||
|
|
||||||
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
|
interface Parent
|
||||||
|
|
||||||
|
interface Child : Parent
|
||||||
|
|
||||||
|
fun test(p: Parent, c: Child?) {
|
||||||
|
assertTrue<caret>(p == c)
|
||||||
|
}
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
// RUNTIME_WITH_KOTLIN_TEST
|
||||||
|
// PROBLEM: none
|
||||||
|
|
||||||
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
|
interface Parent
|
||||||
|
|
||||||
|
interface Child : Parent
|
||||||
|
|
||||||
|
fun test(p: Parent, c: Child?) {
|
||||||
|
assertTrue<caret>(c === p)
|
||||||
|
}
|
||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
// RUNTIME_WITH_KOTLIN_TEST
|
||||||
|
|
||||||
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
|
interface Parent
|
||||||
|
|
||||||
|
interface Child : Parent
|
||||||
|
|
||||||
|
fun test(p: Parent?, c: Child) {
|
||||||
|
<caret>assertTrue(p == c)
|
||||||
|
}
|
||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
// RUNTIME_WITH_KOTLIN_TEST
|
||||||
|
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
interface Parent
|
||||||
|
|
||||||
|
interface Child : Parent
|
||||||
|
|
||||||
|
fun test(p: Parent?, c: Child) {
|
||||||
|
assertEquals(p, c)
|
||||||
|
}
|
||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
// RUNTIME_WITH_KOTLIN_TEST
|
||||||
|
|
||||||
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
|
interface Parent
|
||||||
|
|
||||||
|
interface Child : Parent
|
||||||
|
|
||||||
|
fun test(p: Parent?, c: Child) {
|
||||||
|
<caret>assertTrue(c === p)
|
||||||
|
}
|
||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
// RUNTIME_WITH_KOTLIN_TEST
|
||||||
|
|
||||||
|
import kotlin.test.assertSame
|
||||||
|
|
||||||
|
interface Parent
|
||||||
|
|
||||||
|
interface Child : Parent
|
||||||
|
|
||||||
|
fun test(p: Parent?, c: Child) {
|
||||||
|
assertSame(c, p)
|
||||||
|
}
|
||||||
+20
@@ -6845,6 +6845,26 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest {
|
|||||||
public void testAssertTrueWithMessage() throws Exception {
|
public void testAssertTrueWithMessage() throws Exception {
|
||||||
runTest("idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/assertTrueWithMessage.kt");
|
runTest("idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/assertTrueWithMessage.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("notSubtype.kt")
|
||||||
|
public void testNotSubtype() throws Exception {
|
||||||
|
runTest("idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/notSubtype.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("notSubtype2.kt")
|
||||||
|
public void testNotSubtype2() throws Exception {
|
||||||
|
runTest("idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/notSubtype2.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("subtype.kt")
|
||||||
|
public void testSubtype() throws Exception {
|
||||||
|
runTest("idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/subtype.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("subtype2.kt")
|
||||||
|
public void testSubtype2() throws Exception {
|
||||||
|
runTest("idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/subtype2.kt");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("idea/testData/inspectionsLocal/replaceAssociateFunction")
|
@TestMetadata("idea/testData/inspectionsLocal/replaceAssociateFunction")
|
||||||
|
|||||||
Reference in New Issue
Block a user