[kotlin] k2: add override keyword on implement interface

^KTIJ-33307 fixed

GitOrigin-RevId: 58374699daf644f040ec6b537aaaaa46fcaf8635
This commit is contained in:
Anna Kozlova
2025-03-26 10:50:40 +00:00
committed by intellij-monorepo-bot
parent 2e8fa8e94a
commit af84acc92f
7 changed files with 113 additions and 0 deletions
@@ -2,6 +2,7 @@
package org.jetbrains.kotlin.idea.k2.codeinsight.fixes
import com.intellij.codeInsight.intention.LowPriorityAction
import com.intellij.openapi.actionSystem.ex.ActionUtil
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.fileEditor.FileEditorManager
import com.intellij.openapi.project.Project
@@ -22,10 +23,12 @@ import org.jetbrains.kotlin.idea.codeinsight.api.classic.quickfixes.KotlinQuickF
import org.jetbrains.kotlin.idea.codeinsight.utils.containsStarProjections
import org.jetbrains.kotlin.idea.codeinsight.utils.isInterface
import org.jetbrains.kotlin.idea.core.overrideImplement.KtImplementMembersHandler
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.psi.psiUtil.isObjectLiteral
import org.jetbrains.kotlin.psi.psiUtil.visibilityModifierType
import org.jetbrains.kotlin.types.Variance
internal object LetImplementInterfaceFixFactories {
@@ -144,7 +147,25 @@ internal object LetImplementInterfaceFixFactories {
}
val newElement = point.element ?: return
val implementMembersHandler = KtImplementMembersHandler()
val membersToAddOverride = ActionUtil.underModalProgress(project, KotlinBundle.message("progress.title.collect.members.to.generate")) {
implementMembersHandler.collectMembersToAddOverride(newElement)
}
if (membersToAddOverride.isNotEmpty()) {
application.runWriteAction {
membersToAddOverride.forEach {
it.addModifier(KtTokens.OVERRIDE_KEYWORD)
val visibility = element.visibilityModifierType()
if (visibility != null && visibility != KtTokens.PUBLIC_KEYWORD) {
element.removeModifier(visibility)
}
}
}
}
if (implementMembersHandler.collectMembersToGenerateUnderProgress(newElement).isEmpty()) return
if (editor != null) {
@@ -4453,6 +4453,11 @@ public abstract class HighLevelQuickFixTestGenerated extends AbstractHighLevelQu
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
@TestMetadata("hiddenVirtualMethod.kt")
public void testHiddenVirtualMethod() throws Exception {
runTest("../../../idea/tests/testData/quickfix/typeMismatch/letImplementInterface/hiddenVirtualMethod.kt");
}
@TestMetadata("kt25928.kt")
public void testKt25928() throws Exception {
runTest("../../../idea/tests/testData/quickfix/typeMismatch/letImplementInterface/kt25928.kt");
@@ -7,6 +7,7 @@ import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.NlsSafe
import com.intellij.psi.PsiFile
import com.intellij.util.containers.addIfNotNull
import org.jetbrains.annotations.ApiStatus
import org.jetbrains.kotlin.analysis.api.KaExperimentalApi
import org.jetbrains.kotlin.analysis.api.KaSession
@@ -16,11 +17,13 @@ import org.jetbrains.kotlin.analysis.api.symbols.KaCallableSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KaClassKind
import org.jetbrains.kotlin.analysis.api.symbols.KaClassSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KaSymbolModality
import org.jetbrains.kotlin.fir.extensions.FirAnalysisHandlerExtension.Companion.analyze
import org.jetbrains.kotlin.idea.KtIconProvider.getIcon
import org.jetbrains.kotlin.idea.codeinsight.api.applicators.fixes.KotlinQuickFixFactory
import org.jetbrains.kotlin.idea.core.overrideImplement.KtImplementMembersHandler.Companion.getUnimplementedMembers
import org.jetbrains.kotlin.idea.core.util.KotlinIdeaCoreBundle
import org.jetbrains.kotlin.idea.search.ExpectActualSupport
import org.jetbrains.kotlin.psi.KtCallableDeclaration
import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtEnumEntry
@@ -40,6 +43,18 @@ open class KtImplementMembersHandler : KtGenerateMembersHandler(true) {
}
}
@OptIn(KaExperimentalApi::class)
fun collectMembersToAddOverride(classOrObject: KtClassOrObject): List<KtCallableDeclaration> {
analyze(classOrObject) {
val classSymbol = classOrObject.classSymbol
return classSymbol?.memberScope?.callables?.toList()?.mapNotNull { symbol ->
(symbol.psi as? KtCallableDeclaration)?.takeIf {
symbol.getImplementationStatus(classSymbol) == ImplementationStatus.CANNOT_BE_IMPLEMENTED
}
} ?: emptyList()
}
}
companion object {
context(KaSession)
fun getUnimplementedMembers(classWithUnimplementedMembers: KtClassOrObject): List<KtClassMemberInfo> =
@@ -18707,6 +18707,11 @@ public abstract class K1QuickFixTestGenerated extends AbstractK1QuickFixTest {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
@TestMetadata("hiddenVirtualMethod.kt")
public void testHiddenVirtualMethod() throws Exception {
runTest("testData/quickfix/typeMismatch/letImplementInterface/hiddenVirtualMethod.kt");
}
@TestMetadata("kt25928.kt")
public void testKt25928() throws Exception {
runTest("testData/quickfix/typeMismatch/letImplementInterface/kt25928.kt");
@@ -0,0 +1,22 @@
// "Let 'C' implement interface 'I'" "true"
class C : I {
override fun exampleMethod() {
}
}
interface I {
fun exampleMethod()
}
fun acceptExampleInterface(i: I) {
i.exampleMethod()
}
fun testCase(c: C) {
acceptExampleInterface(<caret>c)
}
// IGNORE_K1
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.LetImplementInterfaceFix
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.k2.codeinsight.fixes.LetImplementInterfaceFixFactories$LetImplementInterfaceFix
@@ -0,0 +1,22 @@
// "Let 'C' implement interface 'I'" "true"
class C {
fun exampleMethod() {
}
}
interface I {
fun exampleMethod()
}
fun acceptExampleInterface(i: I) {
i.exampleMethod()
}
fun testCase(c: C) {
acceptExampleInterface(<caret>c)
}
// IGNORE_K1
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.LetImplementInterfaceFix
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.k2.codeinsight.fixes.LetImplementInterfaceFixFactories$LetImplementInterfaceFix
@@ -0,0 +1,23 @@
// "Let 'C' implement interface 'I'" "true"
// ERROR: 'exampleMethod' hides member of supertype 'I' and needs 'override' modifier
class C : I {
fun exampleMethod() {
}
}
interface I {
fun exampleMethod()
}
fun acceptExampleInterface(i: I) {
i.exampleMethod()
}
fun testCase(c: C) {
acceptExampleInterface(<caret>c)
}
// IGNORE_K1
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.LetImplementInterfaceFix
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.k2.codeinsight.fixes.LetImplementInterfaceFixFactories$LetImplementInterfaceFix