mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[kotlin] Port AddFunModifierFix to K2
This quick fix is for the INTERFACE_AS_FUNCTION error. ^KTIJ-26890 GitOrigin-RevId: 57e2171b1ee82ca4202edd69aa3ed19d26ca2c46
This commit is contained in:
committed by
intellij-monorepo-bot
parent
78fcccc1a7
commit
8d0b39fe2d
+76
@@ -0,0 +1,76 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.kotlin.idea.k2.codeinsight.fixes
|
||||
|
||||
import com.intellij.modcommand.ActionContext
|
||||
import com.intellij.modcommand.ModPsiUpdater
|
||||
import com.intellij.psi.SmartPsiElementPointer
|
||||
import com.intellij.refactoring.suggested.createSmartPointer
|
||||
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.fir.diagnostics.KtFirDiagnostic
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtClassKind
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtNamedClassOrObjectSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolWithModality
|
||||
import org.jetbrains.kotlin.config.LanguageVersion
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.idea.base.projectStructure.languageVersionSettings
|
||||
import org.jetbrains.kotlin.idea.base.psi.replaceSamConstructorCall
|
||||
import org.jetbrains.kotlin.idea.base.resources.KotlinBundle
|
||||
import org.jetbrains.kotlin.idea.codeinsight.api.applicators.fixes.KotlinModCommandAction
|
||||
import org.jetbrains.kotlin.idea.codeinsight.api.applicators.fixes.KotlinQuickFixFactory
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.KtCallExpression
|
||||
import org.jetbrains.kotlin.psi.KtClass
|
||||
import org.jetbrains.kotlin.psi.KtLambdaArgument
|
||||
import org.jetbrains.kotlin.psi.KtValueArgument
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||
|
||||
internal object AddFunModifierFixFactory {
|
||||
val addFunModifierFixFactory = KotlinQuickFixFactory.ModCommandBased { diagnostic: KtFirDiagnostic.InterfaceAsFunction ->
|
||||
val referrer = diagnostic.psi
|
||||
if (referrer.languageVersionSettings.languageVersion < LanguageVersion.KOTLIN_1_4) return@ModCommandBased emptyList()
|
||||
|
||||
val referrerCall = referrer.parent as? KtCallExpression ?: return@ModCommandBased emptyList()
|
||||
if (referrerCall.valueArguments.singleOrNull() !is KtLambdaArgument) return@ModCommandBased emptyList()
|
||||
val referenceClassSymbol = diagnostic.classSymbol as? KtNamedClassOrObjectSymbol ?: return@ModCommandBased emptyList()
|
||||
if (referenceClassSymbol.isFun || !referenceClassSymbol.isSamInterface()) return@ModCommandBased emptyList()
|
||||
|
||||
val referenceClass = referenceClassSymbol.psi as? KtClass ?: return@ModCommandBased emptyList()
|
||||
val referenceClassName = referenceClass.name ?: return@ModCommandBased emptyList()
|
||||
|
||||
return@ModCommandBased listOf(
|
||||
AddFunModifierFix(
|
||||
referenceClass,
|
||||
referenceClassName,
|
||||
AddFunModifierFix.ElementContext(referrerCall.createSmartPointer())
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private class AddFunModifierFix(ktClass: KtClass, private val elementName: String, context: ElementContext) :
|
||||
KotlinModCommandAction<KtClass, AddFunModifierFix.ElementContext>(ktClass, context) {
|
||||
|
||||
class ElementContext(val referrerCallPointer: SmartPsiElementPointer<KtCallExpression>) : KotlinModCommandAction.ElementContext
|
||||
|
||||
override fun invoke(context: ActionContext, element: KtClass, elementContext: ElementContext, updater: ModPsiUpdater) {
|
||||
val referrerCall = updater.getWritable(elementContext.referrerCallPointer.element)
|
||||
element.addModifier(KtTokens.FUN_KEYWORD)
|
||||
if (referrerCall?.lambdaArguments?.singleOrNull() == null) return
|
||||
referrerCall.getStrictParentOfType<KtValueArgument>()?.takeIf { it.getArgumentExpression() == referrerCall } ?: return
|
||||
replaceSamConstructorCall(referrerCall)
|
||||
}
|
||||
|
||||
override fun getFamilyName() = KotlinBundle.message("add.fun.modifier.to.0", elementName)
|
||||
}
|
||||
}
|
||||
|
||||
context(KtAnalysisSession)
|
||||
private fun KtNamedClassOrObjectSymbol.isSamInterface(): Boolean {
|
||||
if (classKind != KtClassKind.INTERFACE) return false
|
||||
val singleAbstractMember = getMemberScope()
|
||||
.getCallableSymbols()
|
||||
.filterIsInstance<KtSymbolWithModality>()
|
||||
.filter { it.modality == Modality.ABSTRACT }
|
||||
.singleOrNull() ?: return false
|
||||
return singleAbstractMember is KtFunctionSymbol && singleAbstractMember.typeParameters.isEmpty()
|
||||
}
|
||||
+1
@@ -85,6 +85,7 @@ class KotlinK2QuickFixRegistrar : KotlinQuickFixRegistrar() {
|
||||
registerPsiQuickFixes(KtFirDiagnostic.ValOrVarOnSecondaryConstructorParameter::class, RemoveValVarFromParameterFix)
|
||||
registerFactory(MakeSuperTypeOpenFixFactory.makeSuperTypeOpenFixFactory)
|
||||
registerFactory(MakeSuperTypeOpenFixFactory.makeUpperBoundOpenFixFactory)
|
||||
registerFactory(AddFunModifierFixFactory.addFunModifierFixFactory)
|
||||
}
|
||||
|
||||
private val addAbstract = KtQuickFixesListBuilder.registerPsiQuickFix {
|
||||
|
||||
+61
@@ -4576,7 +4576,68 @@ public abstract class HighLevelQuickFixTestGenerated extends AbstractHighLevelQu
|
||||
|
||||
|
||||
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
@TestMetadata("../../../idea/tests/testData/quickfix/addFunModifier")
|
||||
public static class AddFunModifier extends AbstractHighLevelQuickFixTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
||||
}
|
||||
|
||||
@TestMetadata("asFirstArgument.kt")
|
||||
public void testAsFirstArgument() throws Exception {
|
||||
runTest("../../../idea/tests/testData/quickfix/addFunModifier/asFirstArgument.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("asLastArgument.kt")
|
||||
public void testAsLastArgument() throws Exception {
|
||||
runTest("../../../idea/tests/testData/quickfix/addFunModifier/asLastArgument.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("hasArguments.kt")
|
||||
public void testHasArguments() throws Exception {
|
||||
runTest("../../../idea/tests/testData/quickfix/addFunModifier/hasArguments.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("hasNoArguments.kt")
|
||||
public void testHasNoArguments() throws Exception {
|
||||
runTest("../../../idea/tests/testData/quickfix/addFunModifier/hasNoArguments.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("multipleLambdaArgumentsAreNotMovedOutsideParentheses.kt")
|
||||
public void testMultipleLambdaArgumentsAreNotMovedOutsideParentheses() throws Exception {
|
||||
runTest("../../../idea/tests/testData/quickfix/addFunModifier/multipleLambdaArgumentsAreNotMovedOutsideParentheses.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("namedLambdaArgumentIsNotMovedOutsideParentheses.kt")
|
||||
public void testNamedLambdaArgumentIsNotMovedOutsideParentheses() throws Exception {
|
||||
runTest("../../../idea/tests/testData/quickfix/addFunModifier/namedLambdaArgumentIsNotMovedOutsideParentheses.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nonSource.kt")
|
||||
public void testNonSource() throws Exception {
|
||||
runTest("../../../idea/tests/testData/quickfix/addFunModifier/nonSource.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("notSam.kt")
|
||||
public void testNotSam() throws Exception {
|
||||
runTest("../../../idea/tests/testData/quickfix/addFunModifier/notSam.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("notSam2.kt")
|
||||
public void testNotSam2() throws Exception {
|
||||
runTest("../../../idea/tests/testData/quickfix/addFunModifier/notSam2.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("notSam3.kt")
|
||||
public void testNotSam3() throws Exception {
|
||||
runTest("../../../idea/tests/testData/quickfix/addFunModifier/notSam3.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("simple.kt")
|
||||
public void testSimple() throws Exception {
|
||||
runTest("../../../idea/tests/testData/quickfix/addFunModifier/simple.kt");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -9,4 +9,5 @@ fun test() {
|
||||
val x = foo(<caret>I {}, 2)
|
||||
}
|
||||
|
||||
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddFunModifierFix
|
||||
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddFunModifierFix
|
||||
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.k2.codeinsight.fixes.AddFunModifierFixFactory$AddFunModifierFix
|
||||
@@ -9,4 +9,5 @@ fun test() {
|
||||
val x = foo({}, 2)
|
||||
}
|
||||
|
||||
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddFunModifierFix
|
||||
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddFunModifierFix
|
||||
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.k2.codeinsight.fixes.AddFunModifierFixFactory$AddFunModifierFix
|
||||
@@ -9,4 +9,5 @@ fun test() {
|
||||
val x = foo(<caret>I {})
|
||||
}
|
||||
|
||||
/* IGNORE_K2 */
|
||||
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddFunModifierFix
|
||||
@@ -9,4 +9,5 @@ fun test() {
|
||||
val x = foo {}
|
||||
}
|
||||
|
||||
/* IGNORE_K2 */
|
||||
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddFunModifierFix
|
||||
+2
-1
@@ -9,4 +9,5 @@ fun test() {
|
||||
val x = foo({}, <caret>I {})
|
||||
}
|
||||
|
||||
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddFunModifierFix
|
||||
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddFunModifierFix
|
||||
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.k2.codeinsight.fixes.AddFunModifierFixFactory$AddFunModifierFix
|
||||
+2
-1
@@ -9,4 +9,5 @@ fun test() {
|
||||
val x = foo({}, {})
|
||||
}
|
||||
|
||||
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddFunModifierFix
|
||||
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddFunModifierFix
|
||||
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.k2.codeinsight.fixes.AddFunModifierFixFactory$AddFunModifierFix
|
||||
+2
-1
@@ -9,4 +9,5 @@ fun test() {
|
||||
val x = foo(i = <caret>I {})
|
||||
}
|
||||
|
||||
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddFunModifierFix
|
||||
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddFunModifierFix
|
||||
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.k2.codeinsight.fixes.AddFunModifierFixFactory$AddFunModifierFix
|
||||
+2
-1
@@ -9,4 +9,5 @@ fun test() {
|
||||
val x = foo(i = {})
|
||||
}
|
||||
|
||||
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddFunModifierFix
|
||||
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddFunModifierFix
|
||||
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.k2.codeinsight.fixes.AddFunModifierFixFactory$AddFunModifierFix
|
||||
@@ -7,4 +7,5 @@ fun test() {
|
||||
val x = <caret>I {}
|
||||
}
|
||||
|
||||
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddFunModifierFix
|
||||
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddFunModifierFix
|
||||
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.k2.codeinsight.fixes.AddFunModifierFixFactory$AddFunModifierFix
|
||||
@@ -7,4 +7,5 @@ fun test() {
|
||||
val x = I {}
|
||||
}
|
||||
|
||||
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddFunModifierFix
|
||||
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddFunModifierFix
|
||||
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.k2.codeinsight.fixes.AddFunModifierFixFactory$AddFunModifierFix
|
||||
+1
-1
@@ -63,7 +63,7 @@ internal fun MutableTWorkspace.generateK2FixTests() {
|
||||
model("$idea/quickfix/addElseBranchToIf", pattern = pattern, isIgnored = true)
|
||||
model("$idea/quickfix/addEmptyArgumentList", pattern = pattern, isIgnored = true)
|
||||
model("$idea/quickfix/addEqEqTrue", pattern = pattern, isIgnored = true)
|
||||
model("$idea/quickfix/addFunModifier", pattern = pattern, isIgnored = true)
|
||||
model("$idea/quickfix/addFunModifier", pattern = pattern)
|
||||
model("$idea/quickfix/addGenericUpperBound", pattern = pattern, isIgnored = true)
|
||||
model("$idea/quickfix/addInline", pattern = pattern, isIgnored = true)
|
||||
model("$idea/quickfix/addInlineToReifiedFunctionFix", pattern = pattern, isIgnored = true)
|
||||
|
||||
Reference in New Issue
Block a user