Introduce "Add '== true'" quick fix for TYPE_MISMATCH

#KT-39930 Fixed
This commit is contained in:
Toshiaki Kameyama
2020-07-02 15:55:36 +09:00
committed by Dmitry Gridin
parent 5bf18c09bb
commit efdeb7b449
11 changed files with 140 additions and 5 deletions
@@ -2240,6 +2240,7 @@ title.import.layout=Import Layout
title.packages.to.use.import.with=Packages to Use Import with '*'
redundant.qualifier.unnecessary.non.direct.parent.class.qualifier=Unnecessary non-direct parent classes qualifiers
fix.add.exception.to.throws=Add ''{0}''
fix.add.eq.eq.true=Add '== true'
hints.title.codevision=Code Vision
hints.title.codevision.show.hints.for=Show hints for:
@@ -0,0 +1,25 @@
/*
* 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.openapi.editor.Editor
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.psi.createExpressionByPattern
class AddEqEqTrueFix(expression: KtExpression) : KotlinQuickFixAction<KtExpression>(expression) {
override fun getText() = KotlinBundle.message("fix.add.eq.eq.true")
override fun getFamilyName() = text
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val expression = element ?: return
expression.replace(KtPsiFactory(expression).createExpressionByPattern("$0 == true", expression))
}
}
@@ -50,10 +50,7 @@ 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.NO_EXPECTED_TYPE
import org.jetbrains.kotlin.types.typeUtil.isInterface
import org.jetbrains.kotlin.types.typeUtil.isSignedOrUnsignedNumberType
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
import org.jetbrains.kotlin.types.typeUtil.makeNullable
import org.jetbrains.kotlin.types.typeUtil.*
import java.util.*
//TODO: should use change signature to deal with cases of multiple overridden descriptors
@@ -168,7 +165,11 @@ class QuickFixFactoryForTypeMismatchError : KotlinIntentionActionsFactory() {
if (!expectedType.isMarkedNullable && TypeUtils.isNullableType(expressionType)) {
val nullableExpected = expectedType.makeNullable()
if (expressionType.isSubtypeOf(nullableExpected)) {
actions.add(AddExclExclCallFix(diagnosticElement.getTopMostQualifiedForSelectorIfAny()))
val targetExpression = diagnosticElement.getTopMostQualifiedForSelectorIfAny()
actions.add(AddExclExclCallFix(targetExpression))
if (expectedType.isBoolean()) {
actions.add(AddEqEqTrueFix(targetExpression))
}
}
}
+10
View File
@@ -0,0 +1,10 @@
// "Add '== true'" "false"
// DISABLE-ERRORS
class Foo {
fun bar() = ""
}
fun test(foo: Foo?) {
if (foo?.bar()<caret>) {
}
}
+14
View File
@@ -0,0 +1,14 @@
// "Add '== true'" "false"
// DISABLE-ERRORS
// ACTION: Add 'toString()' call
// ACTION: Change parameter 's' type of function 'baz' to 'Boolean?'
// ACTION: Create function 'baz'
class Foo {
fun bar() = true
}
fun baz(s: String) {}
fun test(foo: Foo?) {
baz(foo?.bar()<caret>)
}
+9
View File
@@ -0,0 +1,9 @@
// "Add '== true'" "true"
class Foo {
fun bar() = true
}
fun test(foo: Foo?) {
if (foo?.bar()<caret>) {
}
}
+9
View File
@@ -0,0 +1,9 @@
// "Add '== true'" "true"
class Foo {
fun bar() = true
}
fun test(foo: Foo?) {
if (foo?.bar() == true) {
}
}
+10
View File
@@ -0,0 +1,10 @@
// "Add '== true'" "true"
class Foo {
fun bar() = true
}
fun baz(b: Boolean) {}
fun test(foo: Foo?) {
baz(foo?.bar()<caret>)
}
+10
View File
@@ -0,0 +1,10 @@
// "Add '== true'" "true"
class Foo {
fun bar() = true
}
fun baz(b: Boolean) {}
fun test(foo: Foo?) {
baz(foo?.bar() == true)
}
@@ -111,6 +111,19 @@ public class QuickFixMultiFileTestGenerated extends AbstractQuickFixMultiFileTes
}
}
@TestMetadata("idea/testData/quickfix/addEqEqTrue")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class AddEqEqTrue extends AbstractQuickFixMultiFileTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTestWithExtraFile, this, testDataFilePath);
}
public void testAllFilesPresentInAddEqEqTrue() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/testData/quickfix/addEqEqTrue"), Pattern.compile("^(\\w+)\\.((before\\.Main\\.\\w+)|(test))$"), null, true);
}
}
@TestMetadata("idea/testData/quickfix/addExclExclCall")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -576,6 +576,39 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
}
}
@TestMetadata("idea/testData/quickfix/addEqEqTrue")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class AddEqEqTrue extends AbstractQuickFixTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInAddEqEqTrue() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/testData/quickfix/addEqEqTrue"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), null, true);
}
@TestMetadata("notBoolean.kt")
public void testNotBoolean() throws Exception {
runTest("idea/testData/quickfix/addEqEqTrue/notBoolean.kt");
}
@TestMetadata("notBoolean2.kt")
public void testNotBoolean2() throws Exception {
runTest("idea/testData/quickfix/addEqEqTrue/notBoolean2.kt");
}
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
runTest("idea/testData/quickfix/addEqEqTrue/simple.kt");
}
@TestMetadata("simple2.kt")
public void testSimple2() throws Exception {
runTest("idea/testData/quickfix/addEqEqTrue/simple2.kt");
}
}
@TestMetadata("idea/testData/quickfix/addExclExclCall")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)