From f811fb689f5c1385820fd027c0dff89da92bf7f8 Mon Sep 17 00:00:00 2001 From: Toshiaki Kameyama Date: Wed, 22 Feb 2023 15:13:52 +0900 Subject: [PATCH] [kotlin] K2 IDE: Add fix for FINAL_SUPERTYPE ^KTIJ-23928 Fixed closes https://github.com/JetBrains/intellij-community/pull/2332 GitOrigin-RevId: 064e38feaea811c1e3a55a862b48e96f24663cdd --- .../quickfix/KotlinK2QuickFixRegistrar.kt | 1 + .../fixes/MakeSuperTypeOpenFixFactory.kt | 24 +++++ .../HighLevelQuickFixTestGenerated.java | 98 +++++++++++++++++++ .../enumSupertype.kt | 5 +- .../enumUpperBound.kt | 5 +- .../finalJavaSupertype.before.Main.kt | 2 +- .../finalJavaUpperBound.before.Main.kt | 2 +- .../finalLibrarySupertype.kt | 3 +- .../finalLibraryUpperBound.kt | 7 +- .../fir/testGenerator/FirGenerateTests.kt | 1 + 10 files changed, 142 insertions(+), 6 deletions(-) create mode 100644 plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/quickfix/fixes/MakeSuperTypeOpenFixFactory.kt diff --git a/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/quickfix/KotlinK2QuickFixRegistrar.kt b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/quickfix/KotlinK2QuickFixRegistrar.kt index 1ae2c898b595..c03c3e64ae6c 100644 --- a/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/quickfix/KotlinK2QuickFixRegistrar.kt +++ b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/quickfix/KotlinK2QuickFixRegistrar.kt @@ -71,6 +71,7 @@ class KotlinK2QuickFixRegistrar : KotlinQuickFixRegistrar() { registerPsiQuickFixes(KtFirDiagnostic.ValOrVarOnFunParameter::class, RemoveValVarFromParameterFix) registerPsiQuickFixes(KtFirDiagnostic.ValOrVarOnCatchParameter::class, RemoveValVarFromParameterFix) registerPsiQuickFixes(KtFirDiagnostic.ValOrVarOnSecondaryConstructorParameter::class, RemoveValVarFromParameterFix) + registerApplicators(MakeSuperTypeOpenFixFactory.makeSuperTypeOpenFixFactory) } private val propertyInitialization = KtQuickFixesListBuilder.registerPsiQuickFix { diff --git a/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/quickfix/fixes/MakeSuperTypeOpenFixFactory.kt b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/quickfix/fixes/MakeSuperTypeOpenFixFactory.kt new file mode 100644 index 000000000000..145dd2b3a0c1 --- /dev/null +++ b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/quickfix/fixes/MakeSuperTypeOpenFixFactory.kt @@ -0,0 +1,24 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package org.jetbrains.kotlin.idea.quickfix.fixes + +import org.jetbrains.kotlin.analysis.api.fir.diagnostics.KtFirDiagnostic.FinalSupertype +import org.jetbrains.kotlin.analysis.api.fir.diagnostics.KtFirDiagnostic.FinalUpperBound +import org.jetbrains.kotlin.analysis.api.symbols.psiSafe +import org.jetbrains.kotlin.idea.codeinsight.api.applicators.fixes.diagnosticFixFactories +import org.jetbrains.kotlin.idea.quickfix.AddModifierFix +import org.jetbrains.kotlin.idea.refactoring.canRefactor +import org.jetbrains.kotlin.lexer.KtTokens +import org.jetbrains.kotlin.psi.KtClassOrObject +import org.jetbrains.kotlin.psi.KtTypeReference + +object MakeSuperTypeOpenFixFactory { + val makeSuperTypeOpenFixFactory = diagnosticFixFactories( + FinalSupertype::class, + FinalUpperBound::class + ) { diagnostic -> + val typeRef = diagnostic.psi as? KtTypeReference ?: return@diagnosticFixFactories emptyList() + val superType = typeRef.getKtType().expandedClassSymbol?.psiSafe() ?: return@diagnosticFixFactories emptyList() + if (!superType.canRefactor()) return@diagnosticFixFactories emptyList() + listOfNotNull(AddModifierFix.createIfApplicable(superType, KtTokens.OPEN_KEYWORD)) + } +} diff --git a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/quickfix/HighLevelQuickFixTestGenerated.java b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/quickfix/HighLevelQuickFixTestGenerated.java index 6ae85962a9bd..3bb124072ad7 100644 --- a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/quickfix/HighLevelQuickFixTestGenerated.java +++ b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/quickfix/HighLevelQuickFixTestGenerated.java @@ -1225,6 +1225,104 @@ public abstract class HighLevelQuickFixTestGenerated extends AbstractHighLevelQu } } + @RunWith(JUnit3RunnerWithInners.class) + @TestMetadata("../idea/tests/testData/quickfix/modifiers/addOpenToClassDeclaration") + public static class AddOpenToClassDeclaration extends AbstractHighLevelQuickFixTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + @TestMetadata("annotationSuperType.kt") + public void testAnnotationSuperType() throws Exception { + runTest("../idea/tests/testData/quickfix/modifiers/addOpenToClassDeclaration/annotationSuperType.kt"); + } + + @TestMetadata("dataSuperType.kt") + public void testDataSuperType() throws Exception { + runTest("../idea/tests/testData/quickfix/modifiers/addOpenToClassDeclaration/dataSuperType.kt"); + } + + @TestMetadata("enumSupertype.kt") + public void testEnumSupertype() throws Exception { + runTest("../idea/tests/testData/quickfix/modifiers/addOpenToClassDeclaration/enumSupertype.kt"); + } + + @TestMetadata("enumUpperBound.kt") + public void testEnumUpperBound() throws Exception { + runTest("../idea/tests/testData/quickfix/modifiers/addOpenToClassDeclaration/enumUpperBound.kt"); + } + + @TestMetadata("explicitlyFinalSupertype.kt") + public void testExplicitlyFinalSupertype() throws Exception { + runTest("../idea/tests/testData/quickfix/modifiers/addOpenToClassDeclaration/explicitlyFinalSupertype.kt"); + } + + @TestMetadata("explicitlyFinalUpperBound.kt") + public void testExplicitlyFinalUpperBound() throws Exception { + runTest("../idea/tests/testData/quickfix/modifiers/addOpenToClassDeclaration/explicitlyFinalUpperBound.kt"); + } + + @TestMetadata("finalLibrarySupertype.kt") + public void testFinalLibrarySupertype() throws Exception { + runTest("../idea/tests/testData/quickfix/modifiers/addOpenToClassDeclaration/finalLibrarySupertype.kt"); + } + + @TestMetadata("finalLibraryUpperBound.kt") + public void testFinalLibraryUpperBound() throws Exception { + runTest("../idea/tests/testData/quickfix/modifiers/addOpenToClassDeclaration/finalLibraryUpperBound.kt"); + } + + @TestMetadata("finalSupertype.kt") + public void testFinalSupertype() throws Exception { + runTest("../idea/tests/testData/quickfix/modifiers/addOpenToClassDeclaration/finalSupertype.kt"); + } + + @TestMetadata("finalUpperBound.kt") + public void testFinalUpperBound() throws Exception { + runTest("../idea/tests/testData/quickfix/modifiers/addOpenToClassDeclaration/finalUpperBound.kt"); + } + + @TestMetadata("implementInterfaceFinalSupertype.kt") + public void testImplementInterfaceFinalSupertype() throws Exception { + runTest("../idea/tests/testData/quickfix/modifiers/addOpenToClassDeclaration/implementInterfaceFinalSupertype.kt"); + } + + @TestMetadata("inlineSuperType.kt") + public void testInlineSuperType() throws Exception { + runTest("../idea/tests/testData/quickfix/modifiers/addOpenToClassDeclaration/inlineSuperType.kt"); + } + + @TestMetadata("nestedFinalClass.kt") + public void testNestedFinalClass() throws Exception { + runTest("../idea/tests/testData/quickfix/modifiers/addOpenToClassDeclaration/nestedFinalClass.kt"); + } + + @TestMetadata("openInCompanion.kt") + public void testOpenInCompanion() throws Exception { + runTest("../idea/tests/testData/quickfix/modifiers/addOpenToClassDeclaration/openInCompanion.kt"); + } + + @TestMetadata("secondaryCtrDelegationInHeader.kt") + public void testSecondaryCtrDelegationInHeader() throws Exception { + runTest("../idea/tests/testData/quickfix/modifiers/addOpenToClassDeclaration/secondaryCtrDelegationInHeader.kt"); + } + + @TestMetadata("secondaryCtrDelegationInSecondary.kt") + public void testSecondaryCtrDelegationInSecondary() throws Exception { + runTest("../idea/tests/testData/quickfix/modifiers/addOpenToClassDeclaration/secondaryCtrDelegationInSecondary.kt"); + } + + @TestMetadata("valueSuperType.kt") + public void testValueSuperType() throws Exception { + runTest("../idea/tests/testData/quickfix/modifiers/addOpenToClassDeclaration/valueSuperType.kt"); + } + + @TestMetadata("withConstructor.kt") + public void testWithConstructor() throws Exception { + runTest("../idea/tests/testData/quickfix/modifiers/addOpenToClassDeclaration/withConstructor.kt"); + } + } + @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../idea/tests/testData/quickfix/nullables") public abstract static class Nullables extends AbstractHighLevelQuickFixTest { diff --git a/plugins/kotlin/idea/tests/testData/quickfix/modifiers/addOpenToClassDeclaration/enumSupertype.kt b/plugins/kotlin/idea/tests/testData/quickfix/modifiers/addOpenToClassDeclaration/enumSupertype.kt index fbe284e68009..35e8bacf5513 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/modifiers/addOpenToClassDeclaration/enumSupertype.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/modifiers/addOpenToClassDeclaration/enumSupertype.kt @@ -1,5 +1,8 @@ -// "class org.jetbrains.kotlin.idea.quickfix.AddModifierFix" "false" +// "Make 'E' open" "false" // ERROR: This type is final, so it cannot be inherited from // ERROR: Cannot access '': it is private in 'E' +// ACTION: Introduce import alias +// ACTION: Make '' internal +// ACTION: Make '' public enum class E {} class A : E() {} diff --git a/plugins/kotlin/idea/tests/testData/quickfix/modifiers/addOpenToClassDeclaration/enumUpperBound.kt b/plugins/kotlin/idea/tests/testData/quickfix/modifiers/addOpenToClassDeclaration/enumUpperBound.kt index ebc8554dac6b..cb5f38403ac5 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/modifiers/addOpenToClassDeclaration/enumUpperBound.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/modifiers/addOpenToClassDeclaration/enumUpperBound.kt @@ -1,3 +1,6 @@ -// "class org.jetbrains.kotlin.idea.quickfix.AddModifierFix" "false" +// "Make 'E' open" "false" +// ACTION: Create test +// ACTION: Enable a trailing comma by default in the formatter +// ACTION: Introduce import alias enum class E {} class A> {} diff --git a/plugins/kotlin/idea/tests/testData/quickfix/modifiers/addOpenToClassDeclaration/finalJavaSupertype.before.Main.kt b/plugins/kotlin/idea/tests/testData/quickfix/modifiers/addOpenToClassDeclaration/finalJavaSupertype.before.Main.kt index 50193f727f1b..db9cd0db23fa 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/modifiers/addOpenToClassDeclaration/finalJavaSupertype.before.Main.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/modifiers/addOpenToClassDeclaration/finalJavaSupertype.before.Main.kt @@ -1,4 +1,4 @@ -// "class org.jetbrains.kotlin.idea.quickfix.AddModifierFix" "false" +// "Make 'JavaClass' open" "false" // ERROR: This type is final, so it cannot be inherited from // ACTION: Create test // ACTION: Introduce import alias diff --git a/plugins/kotlin/idea/tests/testData/quickfix/modifiers/addOpenToClassDeclaration/finalJavaUpperBound.before.Main.kt b/plugins/kotlin/idea/tests/testData/quickfix/modifiers/addOpenToClassDeclaration/finalJavaUpperBound.before.Main.kt index c14b4754ce8e..35789f7b9d49 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/modifiers/addOpenToClassDeclaration/finalJavaUpperBound.before.Main.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/modifiers/addOpenToClassDeclaration/finalJavaUpperBound.before.Main.kt @@ -1,4 +1,4 @@ -// "class org.jetbrains.kotlin.idea.quickfix.AddModifierFix" "false" +// "Make 'JavaClass' open" "false" // ACTION: Convert to secondary constructor // ACTION: Create test // ACTION: Enable a trailing comma by default in the formatter diff --git a/plugins/kotlin/idea/tests/testData/quickfix/modifiers/addOpenToClassDeclaration/finalLibrarySupertype.kt b/plugins/kotlin/idea/tests/testData/quickfix/modifiers/addOpenToClassDeclaration/finalLibrarySupertype.kt index d2ac8296e014..7375776fe515 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/modifiers/addOpenToClassDeclaration/finalLibrarySupertype.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/modifiers/addOpenToClassDeclaration/finalLibrarySupertype.kt @@ -1,3 +1,4 @@ -// "class org.jetbrains.kotlin.idea.quickfix.AddModifierFix" "false" +// "Make 'String' open" "false" // ERROR: This type is final, so it cannot be inherited from +// ACTION: Add full qualifier class A : String() {} diff --git a/plugins/kotlin/idea/tests/testData/quickfix/modifiers/addOpenToClassDeclaration/finalLibraryUpperBound.kt b/plugins/kotlin/idea/tests/testData/quickfix/modifiers/addOpenToClassDeclaration/finalLibraryUpperBound.kt index 4067a679d7ff..135c6d86f673 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/modifiers/addOpenToClassDeclaration/finalLibraryUpperBound.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/modifiers/addOpenToClassDeclaration/finalLibraryUpperBound.kt @@ -1,2 +1,7 @@ -// "class org.jetbrains.kotlin.idea.quickfix.AddModifierFix" "false" +// "Make 'String' open" "false" +// ACTION: Add full qualifier +// ACTION: Create test +// ACTION: Enable a trailing comma by default in the formatter +// ACTION: Inline type parameter +// ACTION: Remove final upper bound class A> {} diff --git a/plugins/kotlin/util/test-generator-fir/test/org/jetbrains/kotlin/fir/testGenerator/FirGenerateTests.kt b/plugins/kotlin/util/test-generator-fir/test/org/jetbrains/kotlin/fir/testGenerator/FirGenerateTests.kt index fba2f870ec8c..22c846fca6fb 100644 --- a/plugins/kotlin/util/test-generator-fir/test/org/jetbrains/kotlin/fir/testGenerator/FirGenerateTests.kt +++ b/plugins/kotlin/util/test-generator-fir/test/org/jetbrains/kotlin/fir/testGenerator/FirGenerateTests.kt @@ -103,6 +103,7 @@ private fun assembleWorkspace(): TWorkspace = workspace { model("quickfix/lateinit", pattern = pattern) model("quickfix/localVariableWithTypeParameters", pattern = pattern) model("quickfix/modifiers", pattern = pattern, isRecursive = false) + model("quickfix/modifiers/addOpenToClassDeclaration", pattern = pattern) model("quickfix/nullables", pattern = pattern) model("quickfix/override", pattern = pattern, isRecursive = false) model("quickfix/override/typeMismatchOnOverride", pattern = pattern, isRecursive = false)