[kotlin] KTIJ-38334 Narrow property accessor workaround in redundant type argument analysis

(cherry picked from commit b455d9991d94bff4bbaabe70991e78ef2baab068)

IJ-CR-212042

GitOrigin-RevId: 626b911ee2c54e0ceba6aed9f4b6157eff1fb500
This commit is contained in:
Andrey Cherkasov
2026-07-16 07:54:29 +00:00
committed by intellij-monorepo-bot
parent 5d3eda59f7
commit b8c69838cd
8 changed files with 84 additions and 3 deletions
@@ -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");
@@ -0,0 +1,7 @@
// FIX: Remove explicit type arguments
// WITH_STDLIB
class Main {
val x: List<Main>
get() = listOf<caret><Main>()
}
@@ -0,0 +1,7 @@
// FIX: Remove explicit type arguments
// WITH_STDLIB
class Main {
val x: List<Main>
get() = listOf()
}
@@ -0,0 +1,7 @@
// FIX: Remove explicit type arguments
// WITH_STDLIB
var x: List<String> = listOf<String>()
set(value) {
field = listOf<caret><String>()
}
@@ -0,0 +1,7 @@
// FIX: Remove explicit type arguments
// WITH_STDLIB
var x: List<String> = listOf<String>()
set(value) {
field = listOf()
}
@@ -0,0 +1,9 @@
// FIX: Remove explicit type arguments
// WITH_STDLIB
class Main {
var x: List<Main> = listOf<Main>()
set(value) {
field = listOf<caret><Main>()
}
}
@@ -0,0 +1,9 @@
// FIX: Remove explicit type arguments
// WITH_STDLIB
class Main {
var x: List<Main> = listOf<Main>()
set(value) {
field = listOf()
}
}
@@ -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 &&