From 3c49b5f342a151d406e73972508ac490c842a735 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Mon, 6 Jun 2016 16:43:59 +0300 Subject: [PATCH] KT-11104 extra : "wrap with safe let call" is now applicable for argument type mismatches --- .../kotlin/idea/quickfix/QuickFixRegistrar.kt | 7 ++++--- .../idea/quickfix/WrapWithSafeLetCallFix.kt | 21 ++++++++++++++++++- .../wrapWithSafeLetCall/argumentNullable.kt | 8 +++++++ .../argumentNullable.kt.after | 8 +++++++ .../idea/quickfix/QuickFixTestGenerated.java | 6 ++++++ 5 files changed, 46 insertions(+), 4 deletions(-) create mode 100644 idea/testData/quickfix/wrapWithSafeLetCall/argumentNullable.kt create mode 100644 idea/testData/quickfix/wrapWithSafeLetCall/argumentNullable.kt.after diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt index 600a6b7dfb2..5fcf19c7ded 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt @@ -194,9 +194,10 @@ class QuickFixRegistrar : QuickFixContributor { UNSAFE_IMPLICIT_INVOKE_CALL.registerFactory(SurroundWithNullCheckFix) UNSAFE_INFIX_CALL.registerFactory(SurroundWithNullCheckFix) - UNSAFE_CALL.registerFactory(WrapWithSafeLetCallFix) - UNSAFE_IMPLICIT_INVOKE_CALL.registerFactory(WrapWithSafeLetCallFix) - UNSAFE_INFIX_CALL.registerFactory(WrapWithSafeLetCallFix) + UNSAFE_CALL.registerFactory(WrapWithSafeLetCallFix.UnsafeFactory) + UNSAFE_IMPLICIT_INVOKE_CALL.registerFactory(WrapWithSafeLetCallFix.UnsafeFactory) + UNSAFE_INFIX_CALL.registerFactory(WrapWithSafeLetCallFix.UnsafeFactory) + TYPE_MISMATCH.registerFactory(WrapWithSafeLetCallFix.TypeMismatchFactory) UNSAFE_CALL.registerFactory(AddExclExclCallFix) UNNECESSARY_NOT_NULL_ASSERTION.registerFactory(RemoveExclExclCallFix) diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/WrapWithSafeLetCallFix.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/WrapWithSafeLetCallFix.kt index 8487595b607..141c2b7dae3 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/WrapWithSafeLetCallFix.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/WrapWithSafeLetCallFix.kt @@ -20,8 +20,11 @@ import com.intellij.codeInsight.intention.IntentionAction import com.intellij.openapi.editor.Editor import com.intellij.openapi.project.Project import org.jetbrains.kotlin.diagnostics.Diagnostic +import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.getParentOfType +import org.jetbrains.kotlin.types.TypeUtils +import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf class WrapWithSafeLetCallFix( expression: KtExpression, @@ -40,7 +43,7 @@ class WrapWithSafeLetCallFix( element.replace(wrapped) } - companion object : KotlinSingleIntentionActionFactory() { + object UnsafeFactory : KotlinSingleIntentionActionFactory() { override fun createAction(diagnostic: Diagnostic): IntentionAction? { val element = diagnostic.psiElement val expression = element.getParentOfType(true) ?: return null @@ -51,4 +54,20 @@ class WrapWithSafeLetCallFix( return WrapWithSafeLetCallFix(expression, nullableExpression) } } + + object TypeMismatchFactory : KotlinSingleIntentionActionFactory() { + override fun createAction(diagnostic: Diagnostic): IntentionAction? { + val typeMismatch = Errors.TYPE_MISMATCH.cast(diagnostic) + val argument = typeMismatch.psiElement.parent as? KtValueArgument ?: return null + val call = argument.getParentOfType(true) ?: return null + + val expected = typeMismatch.a + val actual = typeMismatch.b + if (expected.isMarkedNullable || !actual.isMarkedNullable) return null + val expectedNullable = TypeUtils.makeNullable(expected) + if (!actual.isSubtypeOf(expectedNullable)) return null + + return WrapWithSafeLetCallFix(call, typeMismatch.psiElement) + } + } } \ No newline at end of file diff --git a/idea/testData/quickfix/wrapWithSafeLetCall/argumentNullable.kt b/idea/testData/quickfix/wrapWithSafeLetCall/argumentNullable.kt new file mode 100644 index 00000000000..cdf2162ed64 --- /dev/null +++ b/idea/testData/quickfix/wrapWithSafeLetCall/argumentNullable.kt @@ -0,0 +1,8 @@ +// "Wrap with '?.let { ... }' call" "true" +// WITH_RUNTIME + +fun foo(x: String?) { + bar(x) +} + +fun bar(s: String) = s.hashCode() \ No newline at end of file diff --git a/idea/testData/quickfix/wrapWithSafeLetCall/argumentNullable.kt.after b/idea/testData/quickfix/wrapWithSafeLetCall/argumentNullable.kt.after new file mode 100644 index 00000000000..29fe3c66c74 --- /dev/null +++ b/idea/testData/quickfix/wrapWithSafeLetCall/argumentNullable.kt.after @@ -0,0 +1,8 @@ +// "Wrap with '?.let { ... }' call" "true" +// WITH_RUNTIME + +fun foo(x: String?) { + x?.let { bar(it) } +} + +fun bar(s: String) = s.hashCode() \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java index f0e4c65a695..9086f64adba 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java @@ -8770,6 +8770,12 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/wrapWithSafeLetCall"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), true); } + @TestMetadata("argumentNullable.kt") + public void testArgumentNullable() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/wrapWithSafeLetCall/argumentNullable.kt"); + doTest(fileName); + } + @TestMetadata("chainedUnsafeCall.kt") public void testChainedUnsafeCall() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/wrapWithSafeLetCall/chainedUnsafeCall.kt");