diff --git a/plugins/kotlin/code-insight/inspections-k2/tests/test/org/jetbrains/kotlin/idea/inspections/tests/K2LocalInspectionTestGenerated.java b/plugins/kotlin/code-insight/inspections-k2/tests/test/org/jetbrains/kotlin/idea/inspections/tests/K2LocalInspectionTestGenerated.java index 449af1617c9f..c5f3f73cd1f9 100644 --- a/plugins/kotlin/code-insight/inspections-k2/tests/test/org/jetbrains/kotlin/idea/inspections/tests/K2LocalInspectionTestGenerated.java +++ b/plugins/kotlin/code-insight/inspections-k2/tests/test/org/jetbrains/kotlin/idea/inspections/tests/K2LocalInspectionTestGenerated.java @@ -29526,6 +29526,11 @@ public abstract class K2LocalInspectionTestGenerated extends AbstractK2LocalInsp runTest("../../../idea/tests/testData/intentions/removeExplicitTypeArguments/getterBody.kt"); } + @TestMetadata("getterBodyInsideClass.kt") + public void testGetterBodyInsideClass() throws Exception { + runTest("../../../idea/tests/testData/intentions/removeExplicitTypeArguments/getterBodyInsideClass.kt"); + } + @TestMetadata("hasAnnotation.kt") public void testHasAnnotation() throws Exception { runTest("../../../idea/tests/testData/intentions/removeExplicitTypeArguments/hasAnnotation.kt"); @@ -29656,6 +29661,16 @@ public abstract class K2LocalInspectionTestGenerated extends AbstractK2LocalInsp runTest("../../../idea/tests/testData/intentions/removeExplicitTypeArguments/script.kts"); } + @TestMetadata("setterBody.kt") + public void testSetterBody() throws Exception { + runTest("../../../idea/tests/testData/intentions/removeExplicitTypeArguments/setterBody.kt"); + } + + @TestMetadata("setterBodyInsideClass.kt") + public void testSetterBodyInsideClass() throws Exception { + runTest("../../../idea/tests/testData/intentions/removeExplicitTypeArguments/setterBodyInsideClass.kt"); + } + @TestMetadata("twoArguments.kt") public void testTwoArguments() throws Exception { runTest("../../../idea/tests/testData/intentions/removeExplicitTypeArguments/twoArguments.kt"); diff --git a/plugins/kotlin/idea/tests/testData/intentions/removeExplicitTypeArguments/getterBodyInsideClass.kt b/plugins/kotlin/idea/tests/testData/intentions/removeExplicitTypeArguments/getterBodyInsideClass.kt new file mode 100644 index 000000000000..d1e7aa4a9087 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/intentions/removeExplicitTypeArguments/getterBodyInsideClass.kt @@ -0,0 +1,7 @@ +// FIX: Remove explicit type arguments +// WITH_STDLIB + +class Main { + val x: List
+ get() = listOf
() +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/intentions/removeExplicitTypeArguments/getterBodyInsideClass.kt.after b/plugins/kotlin/idea/tests/testData/intentions/removeExplicitTypeArguments/getterBodyInsideClass.kt.after new file mode 100644 index 000000000000..98d4d29fd454 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/intentions/removeExplicitTypeArguments/getterBodyInsideClass.kt.after @@ -0,0 +1,7 @@ +// FIX: Remove explicit type arguments +// WITH_STDLIB + +class Main { + val x: List
+ get() = listOf() +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/intentions/removeExplicitTypeArguments/setterBody.kt b/plugins/kotlin/idea/tests/testData/intentions/removeExplicitTypeArguments/setterBody.kt new file mode 100644 index 000000000000..a0ea8943182e --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/intentions/removeExplicitTypeArguments/setterBody.kt @@ -0,0 +1,7 @@ +// FIX: Remove explicit type arguments +// WITH_STDLIB + +var x: List = listOf() + set(value) { + field = listOf() + } diff --git a/plugins/kotlin/idea/tests/testData/intentions/removeExplicitTypeArguments/setterBody.kt.after b/plugins/kotlin/idea/tests/testData/intentions/removeExplicitTypeArguments/setterBody.kt.after new file mode 100644 index 000000000000..197152a0e6ba --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/intentions/removeExplicitTypeArguments/setterBody.kt.after @@ -0,0 +1,7 @@ +// FIX: Remove explicit type arguments +// WITH_STDLIB + +var x: List = listOf() + set(value) { + field = listOf() + } diff --git a/plugins/kotlin/idea/tests/testData/intentions/removeExplicitTypeArguments/setterBodyInsideClass.kt b/plugins/kotlin/idea/tests/testData/intentions/removeExplicitTypeArguments/setterBodyInsideClass.kt new file mode 100644 index 000000000000..5dbb257e56d3 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/intentions/removeExplicitTypeArguments/setterBodyInsideClass.kt @@ -0,0 +1,9 @@ +// FIX: Remove explicit type arguments +// WITH_STDLIB + +class Main { + var x: List
= listOf
() + set(value) { + field = listOf
() + } +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/intentions/removeExplicitTypeArguments/setterBodyInsideClass.kt.after b/plugins/kotlin/idea/tests/testData/intentions/removeExplicitTypeArguments/setterBodyInsideClass.kt.after new file mode 100644 index 000000000000..371e2ec2f3f1 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/intentions/removeExplicitTypeArguments/setterBodyInsideClass.kt.after @@ -0,0 +1,9 @@ +// FIX: Remove explicit type arguments +// WITH_STDLIB + +class Main { + var x: List
= listOf
() + set(value) { + field = listOf() + } +} \ No newline at end of file diff --git a/plugins/kotlin/refactorings/kotlin.refactorings.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/util/RedundantExplicitTypeArgumentsUtil.kt b/plugins/kotlin/refactorings/kotlin.refactorings.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/util/RedundantExplicitTypeArgumentsUtil.kt index 24d5ba48241a..9c383c6616db 100644 --- a/plugins/kotlin/refactorings/kotlin.refactorings.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/util/RedundantExplicitTypeArgumentsUtil.kt +++ b/plugins/kotlin/refactorings/kotlin.refactorings.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/util/RedundantExplicitTypeArgumentsUtil.kt @@ -32,11 +32,11 @@ import org.jetbrains.kotlin.idea.base.codeInsight.handlers.fixers.range import org.jetbrains.kotlin.idea.base.codeInsight.handlers.fixers.start import org.jetbrains.kotlin.idea.base.psi.copied import org.jetbrains.kotlin.psi.KtCallExpression -import org.jetbrains.kotlin.psi.KtClassBody import org.jetbrains.kotlin.psi.KtDotQualifiedExpression +import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtProperty +import org.jetbrains.kotlin.psi.KtPropertyAccessor import org.jetbrains.kotlin.psi.KtPsiFactory -import org.jetbrains.kotlin.psi.KtScriptInitializer import org.jetbrains.kotlin.psi.KtTypeArgumentList import org.jetbrains.kotlin.psi.KtTypeProjection @@ -77,7 +77,7 @@ private fun buildCallExpressionWithoutTypeArgs(element: KtCallExpression): KtCal typeArgumentListRange.end - contextStartOffset, ) - val (prefix, suffix) = if (context !is KtScriptInitializer && context.parent !is KtClassBody) { + val (prefix, suffix) = if (hasPropertyAccessorBetween(element, context)) { "object __Obj__ {" to "}" } else "" to "" @@ -89,6 +89,26 @@ private fun buildCallExpressionWithoutTypeArgs(element: KtCallExpression): KtCal return codeFragment.findElementAt(typeArgumentListRange.start + prefix.length - contextStartOffset)?.parentOfType() } +/** + * Detects whether the code fragment is created inside a property accessor. + * This is needed because `KtBlockCodeFragment` loses expected-type information + * for property accessors. + * + * See: + * - org.jetbrains.kotlin.idea.inspections.tests.K2LocalInspectionTestGenerated.RemoveExplicitTypeArgumentsFormerIntentionTest#testGetterBody + * - org.jetbrains.kotlin.idea.inspections.tests.K2LocalInspectionTestGenerated.RemoveExplicitTypeArgumentsFormerIntentionTest#testGetterBodyInsideClass + * - org.jetbrains.kotlin.idea.inspections.tests.K2LocalInspectionTestGenerated.RemoveExplicitTypeArgumentsFormerIntentionTest#testSetterBody + * - org.jetbrains.kotlin.idea.inspections.tests.K2LocalInspectionTestGenerated.RemoveExplicitTypeArgumentsFormerIntentionTest#testSetterBodyInsideClass + */ +private fun hasPropertyAccessorBetween(element: KtElement, context: KtElement): Boolean { + var current = element.parent + while (current != null && current != context) { + if (current is KtPropertyAccessor) return true + current = current.parent + } + return false +} + private fun KaSession.isInlineReifiedFunction(symbol: KaFunctionSymbol): Boolean = symbol is KaNamedFunctionSymbol && symbol.importableFqName?.asString() !in INLINE_REIFIED_FUNCTIONS_WITH_INSIGNIFICANT_TYPE_ARGUMENTS &&