From 941b41598124ad4df271e94ce9c093a5f51ab01e Mon Sep 17 00:00:00 2001 From: Valentin Kipyatkov Date: Fri, 29 Apr 2016 17:05:05 +0300 Subject: [PATCH] KT-12150 Smart completion suggests to compare non-nullable with null #KT-12150 Fixed --- .../kotlin/idea/completion/KeywordValues.kt | 16 ++++++++-------- .../idea-completion/testData/smart/EqOperator.kt | 2 +- .../testData/smart/EqOperatorPlatformType.kt | 7 +++++++ .../testData/smart/NotEqOperator.kt | 3 ++- .../test/JvmSmartCompletionTestGenerated.java | 6 ++++++ .../jetbrains/kotlin/idea/core/ExpectedInfos.kt | 8 ++++++-- 6 files changed, 30 insertions(+), 12 deletions(-) create mode 100644 idea/idea-completion/testData/smart/EqOperatorPlatformType.kt diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/KeywordValues.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/KeywordValues.kt index 65da159b6ed..a71645d085d 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/KeywordValues.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/KeywordValues.kt @@ -26,10 +26,7 @@ import org.jetbrains.kotlin.idea.caches.resolve.resolveImportReference import org.jetbrains.kotlin.idea.completion.smart.ExpectedInfoMatch import org.jetbrains.kotlin.idea.completion.smart.SmartCompletionItemPriority import org.jetbrains.kotlin.idea.completion.smart.matchExpectedInfo -import org.jetbrains.kotlin.idea.core.ExpectedInfo -import org.jetbrains.kotlin.idea.core.IfConditionAdditionalData -import org.jetbrains.kotlin.idea.core.WhenEntryAdditionalData -import org.jetbrains.kotlin.idea.core.fuzzyType +import org.jetbrains.kotlin.idea.core.* import org.jetbrains.kotlin.idea.resolve.ResolutionFacade import org.jetbrains.kotlin.idea.util.CallTypeAndReceiver import org.jetbrains.kotlin.idea.util.toFuzzyType @@ -83,10 +80,13 @@ object KeywordValues { } val nullMatcher = { info: ExpectedInfo -> - if (info.fuzzyType != null && info.fuzzyType!!.type.isMarkedNullable) - ExpectedInfoMatch.match(TypeSubstitutor.EMPTY) - else - ExpectedInfoMatch.noMatch + when { + (info.additionalData as? ComparisonOperandAdditionalData)?.suppressNullLiteral == true -> ExpectedInfoMatch.noMatch + + info.fuzzyType?.type?.isMarkedNullable == true -> ExpectedInfoMatch.match(TypeSubstitutor.EMPTY) + + else -> ExpectedInfoMatch.noMatch + } } consumer.consume("null", nullMatcher, SmartCompletionItemPriority.NULL) { LookupElementBuilder.create(KeywordLookupObject(), "null").bold() diff --git a/idea/idea-completion/testData/smart/EqOperator.kt b/idea/idea-completion/testData/smart/EqOperator.kt index 9e9540425bc..b503b218f81 100644 --- a/idea/idea-completion/testData/smart/EqOperator.kt +++ b/idea/idea-completion/testData/smart/EqOperator.kt @@ -11,7 +11,7 @@ fun f(e1: E, e2: E?, x: Any) { // EXIST: { itemText:"e2" } // EXIST: { lookupString:"A", itemText:"E.A", typeText:"E" } // EXIST: { lookupString:"B", itemText:"E.B", typeText:"E" } -// EXIST: null +// ABSENT: null // ABSENT: { itemText:"!! e2" } // ABSENT: e1 // ABSENT: x diff --git a/idea/idea-completion/testData/smart/EqOperatorPlatformType.kt b/idea/idea-completion/testData/smart/EqOperatorPlatformType.kt new file mode 100644 index 00000000000..36d8eb77aef --- /dev/null +++ b/idea/idea-completion/testData/smart/EqOperatorPlatformType.kt @@ -0,0 +1,7 @@ +import java.io.File + +fun foo(file: File) { + if (file.name == ) +} + +// EXIST: null diff --git a/idea/idea-completion/testData/smart/NotEqOperator.kt b/idea/idea-completion/testData/smart/NotEqOperator.kt index 35de02612a4..3bc25461d4a 100644 --- a/idea/idea-completion/testData/smart/NotEqOperator.kt +++ b/idea/idea-completion/testData/smart/NotEqOperator.kt @@ -3,12 +3,13 @@ enum class E { B } -fun f(e1: E, e2: E?, x: Any) { +fun f(e1: E?, e2: E, x: Any) { if (e1 != } // EXIST: { lookupString:"A", itemText:"E.A" } // EXIST: { lookupString:"B", itemText:"E.B" } // EXIST: e2 +// EXIST: null // ABSENT: e1 // ABSENT: x diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmSmartCompletionTestGenerated.java b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmSmartCompletionTestGenerated.java index d2b3a05bc2a..7cf1710e73c 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmSmartCompletionTestGenerated.java +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmSmartCompletionTestGenerated.java @@ -137,6 +137,12 @@ public class JvmSmartCompletionTestGenerated extends AbstractJvmSmartCompletionT doTest(fileName); } + @TestMetadata("EqOperatorPlatformType.kt") + public void testEqOperatorPlatformType() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/smart/EqOperatorPlatformType.kt"); + doTest(fileName); + } + @TestMetadata("ExtensionFunctionTypeVariables.kt") public void testExtensionFunctionTypeVariables() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/smart/ExtensionFunctionTypeVariables.kt"); diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/ExpectedInfos.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/ExpectedInfos.kt index 33c6891f0c1..ef755731d8d 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/ExpectedInfos.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/ExpectedInfos.kt @@ -148,6 +148,8 @@ object IfConditionAdditionalData : ExpectedInfo.AdditionalData object PropertyDelegateAdditionalData : ExpectedInfo.AdditionalData +class ComparisonOperandAdditionalData(val suppressNullLiteral: Boolean) : ExpectedInfo.AdditionalData + class ExpectedInfos( private val bindingContext: BindingContext, private val resolutionFacade: ResolutionFacade, @@ -414,12 +416,14 @@ class ExpectedInfos( return listOf(ExpectedInfo(NullableTypesFilter, expectedName, null)) } - // if we complete argument of == or !=, make types in expected info's nullable to allow nullable items too + var additionalData: ExpectedInfo.AdditionalData? = null if (operationToken in COMPARISON_TOKENS) { + // if we complete argument of == or !=, make types in expected info's nullable to allow items of nullable type too + additionalData = ComparisonOperandAdditionalData(suppressNullLiteral = expectedType.nullability() == TypeNullability.NOT_NULL) expectedType = expectedType.makeNullable() } - return listOf(ExpectedInfo(expectedType, expectedName, null)) + return listOf(ExpectedInfo(expectedType, expectedName, null, additionalData = additionalData)) } } }