From 1e7ecbbd9c06110f85d3ee57e35124aff8420aba Mon Sep 17 00:00:00 2001 From: Andrey Cherkasov Date: Wed, 23 Apr 2025 03:06:14 +0400 Subject: [PATCH] [kotlin] Provide quick fixes for IMPLICIT_NOTHING_RETURN_TYPE and IMPLICIT_NOTHING_PROPERTY_TYPE The quick fixes change the type of the enclosing function or property to `Nothing`. #KTIJ-33891 Fixed GitOrigin-RevId: e269d45cb9f5fbe30664d1e7d61da86c0ad5e516 --- .../fixes/ChangeTypeQuickFixFactories.kt | 19 +++++++++++++++++++ .../fixes/KotlinK2QuickFixRegistrar.kt | 2 ++ .../base/CallableReturnTypeUpdaterUtils.kt | 5 ++++- .../tests/K2QuickFixTestGenerated.java | 10 ++++++++++ .../quickfix/K1QuickFixTestGenerated.java | 10 ++++++++++ .../changeFunctionReturnTypeToNothing.kt | 8 ++++++++ ...changeFunctionReturnTypeToNothing.kt.after | 8 ++++++++ .../changePropertyTypeToNothing.kt | 8 ++++++++ .../changePropertyTypeToNothing.kt.after | 8 ++++++++ 9 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 plugins/kotlin/idea/tests/testData/quickfix/changeSignature/changeFunctionReturnTypeToNothing.kt create mode 100644 plugins/kotlin/idea/tests/testData/quickfix/changeSignature/changeFunctionReturnTypeToNothing.kt.after create mode 100644 plugins/kotlin/idea/tests/testData/quickfix/changeSignature/changePropertyTypeToNothing.kt create mode 100644 plugins/kotlin/idea/tests/testData/quickfix/changeSignature/changePropertyTypeToNothing.kt.after diff --git a/plugins/kotlin/code-insight/fixes-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/fixes/ChangeTypeQuickFixFactories.kt b/plugins/kotlin/code-insight/fixes-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/fixes/ChangeTypeQuickFixFactories.kt index 30294ee58512..b421cadb88c4 100644 --- a/plugins/kotlin/code-insight/fixes-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/fixes/ChangeTypeQuickFixFactories.kt +++ b/plugins/kotlin/code-insight/fixes-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/fixes/ChangeTypeQuickFixFactories.kt @@ -466,6 +466,25 @@ internal object ChangeTypeQuickFixFactories { val containerName = parentOfType()?.nameAsName?.takeUnless { it.isSpecial } return ChangeTypeFixUtils.functionOrConstructorParameterPresentation(this, containerName?.asString()) } + + val implicitNothingPropertyTypeFixFactory = KotlinQuickFixFactory.ModCommandBased { diagnostic: KaFirDiagnostic.ImplicitNothingPropertyType -> + createImplicitNothingTypeFix(diagnostic.psi as? KtProperty) + } + + val implicitNothingReturnTypeFixFactory = KotlinQuickFixFactory.ModCommandBased { diagnostic: KaFirDiagnostic.ImplicitNothingReturnType -> + createImplicitNothingTypeFix(diagnostic.psi as? KtFunction) + } + + private fun createImplicitNothingTypeFix(callable: KtCallableDeclaration?): List { + if (callable == null) return emptyList() + return listOf( + UpdateTypeQuickFix( + callable, + TargetType.ENCLOSING_DECLARATION, + CallableReturnTypeUpdaterUtils.TypeInfo(CallableReturnTypeUpdaterUtils.TypeInfo.NOTHING) + ) + ) + } } @OptIn(KaExperimentalApi::class) diff --git a/plugins/kotlin/code-insight/fixes-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/fixes/KotlinK2QuickFixRegistrar.kt b/plugins/kotlin/code-insight/fixes-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/fixes/KotlinK2QuickFixRegistrar.kt index dd51ffd532eb..07905a3a5cbd 100644 --- a/plugins/kotlin/code-insight/fixes-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/fixes/KotlinK2QuickFixRegistrar.kt +++ b/plugins/kotlin/code-insight/fixes-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/fixes/KotlinK2QuickFixRegistrar.kt @@ -186,6 +186,8 @@ class KotlinK2QuickFixRegistrar : KotlinQuickFixRegistrar() { registerFactory(AbstractSuperCallFixFactories.errorFixFactory) registerFactory(AbstractSuperCallFixFactories.warningFactory) registerFactory(JavaClassOnCompanionFixFactories.factory) + registerFactory(ChangeTypeQuickFixFactories.implicitNothingReturnTypeFixFactory) + registerFactory(ChangeTypeQuickFixFactories.implicitNothingPropertyTypeFixFactory) } private val addAbstract = KtQuickFixesListBuilder.registerPsiQuickFix { diff --git a/plugins/kotlin/code-insight/impl-base/src/org/jetbrains/kotlin/idea/codeinsights/impl/base/CallableReturnTypeUpdaterUtils.kt b/plugins/kotlin/code-insight/impl-base/src/org/jetbrains/kotlin/idea/codeinsights/impl/base/CallableReturnTypeUpdaterUtils.kt index 00709473d40b..e223d60ba1cb 100644 --- a/plugins/kotlin/code-insight/impl-base/src/org/jetbrains/kotlin/idea/codeinsights/impl/base/CallableReturnTypeUpdaterUtils.kt +++ b/plugins/kotlin/code-insight/impl-base/src/org/jetbrains/kotlin/idea/codeinsights/impl/base/CallableReturnTypeUpdaterUtils.kt @@ -1,4 +1,4 @@ -// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package org.jetbrains.kotlin.idea.codeinsights.impl.base @@ -30,6 +30,8 @@ import org.jetbrains.kotlin.idea.base.resources.KotlinBundle import org.jetbrains.kotlin.idea.codeinsight.utils.ChooseValueExpression import org.jetbrains.kotlin.idea.codeinsights.impl.base.CallableReturnTypeUpdaterUtils.TypeInfo.Companion.createByKtTypes import org.jetbrains.kotlin.idea.codeinsights.impl.base.CallableReturnTypeUpdaterUtils.TypeInfo.Companion.createTypeByKtType +import org.jetbrains.kotlin.idea.codeinsights.impl.base.CallableReturnTypeUpdaterUtils.setAndShortenTypeReference +import org.jetbrains.kotlin.idea.codeinsights.impl.base.CallableReturnTypeUpdaterUtils.setTypeReference import org.jetbrains.kotlin.idea.util.application.isUnitTestMode import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.findDescendantOfType @@ -340,6 +342,7 @@ object CallableReturnTypeUpdaterUtils { val UNIT: Type = Type(isUnit = true, isError = false, longTypeRepresentation = "kotlin.Unit", shortTypeRepresentation = "Unit") val ANY: Type = Type(isUnit = false, isError = false, longTypeRepresentation = "kotlin.Any", shortTypeRepresentation = "Any") + val NOTHING: Type = Type(isUnit = false, isError = false, longTypeRepresentation = "kotlin.Nothing", shortTypeRepresentation = "Nothing") } } diff --git a/plugins/kotlin/code-insight/inspections-k2/tests/test/org/jetbrains/kotlin/idea/k2/quickfix/tests/K2QuickFixTestGenerated.java b/plugins/kotlin/code-insight/inspections-k2/tests/test/org/jetbrains/kotlin/idea/k2/quickfix/tests/K2QuickFixTestGenerated.java index 7587b1a9abb3..348e539c6009 100644 --- a/plugins/kotlin/code-insight/inspections-k2/tests/test/org/jetbrains/kotlin/idea/k2/quickfix/tests/K2QuickFixTestGenerated.java +++ b/plugins/kotlin/code-insight/inspections-k2/tests/test/org/jetbrains/kotlin/idea/k2/quickfix/tests/K2QuickFixTestGenerated.java @@ -376,11 +376,21 @@ public abstract class K2QuickFixTestGenerated extends AbstractK2QuickFixTest { runTest("../../../idea/tests/testData/quickfix/changeSignature/changeFunctionLiteralParameters4.kt"); } + @TestMetadata("changeFunctionReturnTypeToNothing.kt") + public void testChangeFunctionReturnTypeToNothing() throws Exception { + runTest("../../../idea/tests/testData/quickfix/changeSignature/changeFunctionReturnTypeToNothing.kt"); + } + @TestMetadata("changeParameterType.kt") public void testChangeParameterType() throws Exception { runTest("../../../idea/tests/testData/quickfix/changeSignature/changeParameterType.kt"); } + @TestMetadata("changePropertyTypeToNothing.kt") + public void testChangePropertyTypeToNothing() throws Exception { + runTest("../../../idea/tests/testData/quickfix/changeSignature/changePropertyTypeToNothing.kt"); + } + @TestMetadata("complexHierarchy.kt") public void testComplexHierarchy() throws Exception { runTest("../../../idea/tests/testData/quickfix/changeSignature/complexHierarchy.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 ae2f19782069..3d479bd3b207 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 @@ -3552,11 +3552,21 @@ public abstract class K1QuickFixTestGenerated extends AbstractK1QuickFixTest { runTest("testData/quickfix/changeSignature/changeFunctionLiteralParameters4.kt"); } + @TestMetadata("changeFunctionReturnTypeToNothing.kt") + public void testChangeFunctionReturnTypeToNothing() throws Exception { + runTest("testData/quickfix/changeSignature/changeFunctionReturnTypeToNothing.kt"); + } + @TestMetadata("changeParameterType.kt") public void testChangeParameterType() throws Exception { runTest("testData/quickfix/changeSignature/changeParameterType.kt"); } + @TestMetadata("changePropertyTypeToNothing.kt") + public void testChangePropertyTypeToNothing() throws Exception { + runTest("testData/quickfix/changeSignature/changePropertyTypeToNothing.kt"); + } + @TestMetadata("complexHierarchy.kt") public void testComplexHierarchy() throws Exception { runTest("testData/quickfix/changeSignature/complexHierarchy.kt"); diff --git a/plugins/kotlin/idea/tests/testData/quickfix/changeSignature/changeFunctionReturnTypeToNothing.kt b/plugins/kotlin/idea/tests/testData/quickfix/changeSignature/changeFunctionReturnTypeToNothing.kt new file mode 100644 index 000000000000..7c30f6443263 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/quickfix/changeSignature/changeFunctionReturnTypeToNothing.kt @@ -0,0 +1,8 @@ +// "Change return type of enclosing function 'Test.foo' to 'Nothing'" "true" + +class Test { + fun foo() = TODO() +} + +// IGNORE_K1 +// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.k2.codeinsight.fixes.ChangeTypeQuickFixFactories$UpdateTypeQuickFix \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/quickfix/changeSignature/changeFunctionReturnTypeToNothing.kt.after b/plugins/kotlin/idea/tests/testData/quickfix/changeSignature/changeFunctionReturnTypeToNothing.kt.after new file mode 100644 index 000000000000..c9153a5952bd --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/quickfix/changeSignature/changeFunctionReturnTypeToNothing.kt.after @@ -0,0 +1,8 @@ +// "Change return type of enclosing function 'Test.foo' to 'Nothing'" "true" + +class Test { + fun foo(): Nothing = TODO() +} + +// IGNORE_K1 +// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.k2.codeinsight.fixes.ChangeTypeQuickFixFactories$UpdateTypeQuickFix \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/quickfix/changeSignature/changePropertyTypeToNothing.kt b/plugins/kotlin/idea/tests/testData/quickfix/changeSignature/changePropertyTypeToNothing.kt new file mode 100644 index 000000000000..27a6daf6e50d --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/quickfix/changeSignature/changePropertyTypeToNothing.kt @@ -0,0 +1,8 @@ +// "Change type of enclosing property 'Test.bar' to 'Nothing'" "true" + +class Test { + val bar = TODO() +} + +// IGNORE_K1 +// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.k2.codeinsight.fixes.ChangeTypeQuickFixFactories$UpdateTypeQuickFix \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/quickfix/changeSignature/changePropertyTypeToNothing.kt.after b/plugins/kotlin/idea/tests/testData/quickfix/changeSignature/changePropertyTypeToNothing.kt.after new file mode 100644 index 000000000000..6a44cd02d947 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/quickfix/changeSignature/changePropertyTypeToNothing.kt.after @@ -0,0 +1,8 @@ +// "Change type of enclosing property 'Test.bar' to 'Nothing'" "true" + +class Test { + val bar: Nothing = TODO() +} + +// IGNORE_K1 +// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.k2.codeinsight.fixes.ChangeTypeQuickFixFactories$UpdateTypeQuickFix \ No newline at end of file