From 98cb6d673fa6cef1d0f7540958f6fc372638deb4 Mon Sep 17 00:00:00 2001 From: Vladimir Dolzhenko Date: Thu, 11 Jul 2024 12:51:07 +0200 Subject: [PATCH] [kotlin] Surround with null check should not be available for non-stable variables #KTIJ-30588 Fixed GitOrigin-RevId: f30dfd5da1172748b1bbd8136a0a8657676ec446 --- .../fixes/SurroundWithNullCheckFixFactory.kt | 15 ++++++++++++++- .../fixes/HighLevelQuickFixTestGenerated.java | 10 ++++++++++ .../idea/quickfix/K1QuickFixTestGenerated.java | 10 ++++++++++ .../unstableTopLevelValueWithGetter.kt | 15 +++++++++++++++ .../unstableTopLevelVariable.kt | 14 ++++++++++++++ 5 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 plugins/kotlin/idea/tests/testData/quickfix/surroundWithNullCheck/unstableTopLevelValueWithGetter.kt create mode 100644 plugins/kotlin/idea/tests/testData/quickfix/surroundWithNullCheck/unstableTopLevelVariable.kt diff --git a/plugins/kotlin/code-insight/fixes-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/fixes/SurroundWithNullCheckFixFactory.kt b/plugins/kotlin/code-insight/fixes-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/fixes/SurroundWithNullCheckFixFactory.kt index b0bdaf350e1e..e31b643a6b6b 100644 --- a/plugins/kotlin/code-insight/fixes-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/fixes/SurroundWithNullCheckFixFactory.kt +++ b/plugins/kotlin/code-insight/fixes-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/fixes/SurroundWithNullCheckFixFactory.kt @@ -7,6 +7,9 @@ import com.intellij.psi.SmartPsiElementPointer import com.intellij.psi.createSmartPointer import org.jetbrains.kotlin.analysis.api.KaSession import org.jetbrains.kotlin.analysis.api.fir.diagnostics.KaFirDiagnostic +import org.jetbrains.kotlin.analysis.api.symbols.KaPropertySymbol +import org.jetbrains.kotlin.analysis.api.symbols.KaSymbolLocation +import org.jetbrains.kotlin.analysis.api.symbols.KaVariableSymbol import org.jetbrains.kotlin.analysis.api.symbols.markers.KaNamedSymbol import org.jetbrains.kotlin.idea.base.resources.KotlinBundle import org.jetbrains.kotlin.idea.codeinsight.api.applicable.intentions.KotlinPsiUpdateModCommandAction @@ -93,9 +96,19 @@ internal object SurroundWithNullCheckFixFactory { val file = expressionTarget.containingKtFile val scope = file.scopeContext(expressionTarget).compositeScope() - val callableSymbol = scope.getCallableSymbols(referenceSymbol.name).firstOrNull() ?: return emptyList() + val callableSymbol = scope.callables(referenceSymbol.name).firstOrNull() ?: return emptyList() if (referenceSymbol != callableSymbol) return emptyList() + if (callableSymbol is KaVariableSymbol) { + if (callableSymbol.isVal) { + if ((callableSymbol as? KaPropertySymbol)?.getter?.isDefault == false) { + return emptyList() + } + } else if (callableSymbol.location != KaSymbolLocation.LOCAL) { + return emptyList() + } + } + val elementContext = ElementContext(nullableExpression.createSmartPointer()) return listOf( SurroundWithNullCheckFix(expressionTarget, elementContext) diff --git a/plugins/kotlin/code-insight/fixes-k2/tests/test/org/jetbrains/kotlin/idea/k2/codeinsight/fixes/HighLevelQuickFixTestGenerated.java b/plugins/kotlin/code-insight/fixes-k2/tests/test/org/jetbrains/kotlin/idea/k2/codeinsight/fixes/HighLevelQuickFixTestGenerated.java index 072fb96dac6e..34c38adc7a95 100644 --- a/plugins/kotlin/code-insight/fixes-k2/tests/test/org/jetbrains/kotlin/idea/k2/codeinsight/fixes/HighLevelQuickFixTestGenerated.java +++ b/plugins/kotlin/code-insight/fixes-k2/tests/test/org/jetbrains/kotlin/idea/k2/codeinsight/fixes/HighLevelQuickFixTestGenerated.java @@ -9405,6 +9405,16 @@ public abstract class HighLevelQuickFixTestGenerated extends AbstractHighLevelQu runTest("../../../idea/tests/testData/quickfix/surroundWithNullCheck/unsafeCallInsideWhile.kt"); } + @TestMetadata("unstableTopLevelValueWithGetter.kt") + public void testUnstableTopLevelValueWithGetter() throws Exception { + runTest("../../../idea/tests/testData/quickfix/surroundWithNullCheck/unstableTopLevelValueWithGetter.kt"); + } + + @TestMetadata("unstableTopLevelVariable.kt") + public void testUnstableTopLevelVariable() throws Exception { + runTest("../../../idea/tests/testData/quickfix/surroundWithNullCheck/unstableTopLevelVariable.kt"); + } + @TestMetadata("unstableValue.kt") public void testUnstableValue() throws Exception { runTest("../../../idea/tests/testData/quickfix/surroundWithNullCheck/unstableValue.kt"); diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/quickfix/K1QuickFixTestGenerated.java b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/quickfix/K1QuickFixTestGenerated.java index a4382dd65704..f216b506158b 100644 --- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/quickfix/K1QuickFixTestGenerated.java +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/quickfix/K1QuickFixTestGenerated.java @@ -17017,6 +17017,16 @@ public abstract class K1QuickFixTestGenerated extends AbstractK1QuickFixTest { runTest("testData/quickfix/surroundWithNullCheck/unsafeCallInsideWhile.kt"); } + @TestMetadata("unstableTopLevelValueWithGetter.kt") + public void testUnstableTopLevelValueWithGetter() throws Exception { + runTest("testData/quickfix/surroundWithNullCheck/unstableTopLevelValueWithGetter.kt"); + } + + @TestMetadata("unstableTopLevelVariable.kt") + public void testUnstableTopLevelVariable() throws Exception { + runTest("testData/quickfix/surroundWithNullCheck/unstableTopLevelVariable.kt"); + } + @TestMetadata("unstableValue.kt") public void testUnstableValue() throws Exception { runTest("testData/quickfix/surroundWithNullCheck/unstableValue.kt"); diff --git a/plugins/kotlin/idea/tests/testData/quickfix/surroundWithNullCheck/unstableTopLevelValueWithGetter.kt b/plugins/kotlin/idea/tests/testData/quickfix/surroundWithNullCheck/unstableTopLevelValueWithGetter.kt new file mode 100644 index 000000000000..2122cc9be92f --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/quickfix/surroundWithNullCheck/unstableTopLevelValueWithGetter.kt @@ -0,0 +1,15 @@ +// "Surround with null check" "false" +// ACTION: Add non-null asserted (x!!) call +// ACTION: Convert to run +// ACTION: Convert to with +// ACTION: Introduce import alias +// ACTION: Introduce local variable +// ACTION: Replace with safe (?.) call +// ERROR: Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type Int? + +val x: Int? + get() = 0 + +fun foo() { + x.hashCode() +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/quickfix/surroundWithNullCheck/unstableTopLevelVariable.kt b/plugins/kotlin/idea/tests/testData/quickfix/surroundWithNullCheck/unstableTopLevelVariable.kt new file mode 100644 index 000000000000..332367e0f876 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/quickfix/surroundWithNullCheck/unstableTopLevelVariable.kt @@ -0,0 +1,14 @@ +// "Surround with null check" "false" +// ACTION: Add non-null asserted (x!!) call +// ACTION: Convert to run +// ACTION: Convert to with +// ACTION: Introduce import alias +// ACTION: Introduce local variable +// ACTION: Replace with safe (?.) call +// ERROR: Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type Int? + +var x: Int? = null + +fun foo() { + x.hashCode() +} \ No newline at end of file