提交 56854a8b 编写于 作者: T Tianyu Geng 提交者: Ilya Kirillov

FIR IDE: register quickfix for the following

  1. NON_ABSTRACT_FUNCTION_WITH_NO_BODY
  2. ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS
  3. ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS
上级 88c43e7f
......@@ -1114,6 +1114,7 @@ fun main(args: Array<String>) {
testClass<AbstractHighLevelQuickFixTest> {
val pattern = "^([\\w\\-_]+)\\.kt$"
model("quickfix/abstract", pattern = pattern, filenameStartsLowerCase = true)
model("quickfix/lateinit", pattern = pattern, filenameStartsLowerCase = true)
model("quickfix/modifiers", pattern = pattern, filenameStartsLowerCase = true, recursive = false)
model("quickfix/override/typeMismatchOnOverride", pattern = pattern, filenameStartsLowerCase = true, recursive = false)
......
......@@ -10,7 +10,6 @@ import org.jetbrains.kotlin.idea.fir.api.fixes.KtQuickFixesList
import org.jetbrains.kotlin.idea.fir.api.fixes.KtQuickFixesListBuilder
import org.jetbrains.kotlin.idea.frontend.api.fir.diagnostics.KtFirDiagnostic
import org.jetbrains.kotlin.idea.quickfix.fixes.ChangeTypeQuickFix
import org.jetbrains.kotlin.lexer.KtTokens
class MainKtQuickFixRegistrar : KtQuickFixRegistrar() {
private val modifiers = KtQuickFixesListBuilder.registerPsiQuickFix {
......@@ -19,12 +18,17 @@ class MainKtQuickFixRegistrar : KtQuickFixRegistrar() {
registerPsiQuickFixes(KtFirDiagnostic.RepeatedModifier::class, RemoveModifierFix.removeNonRedundantModifier)
registerPsiQuickFixes(KtFirDiagnostic.DeprecatedModifierPair::class, RemoveModifierFix.removeRedundantModifier)
registerPsiQuickFixes(KtFirDiagnostic.TypeParametersInEnum::class, RemoveModifierFix.removeRedundantModifier)
registerPsiQuickFixes(KtFirDiagnostic.RedundantOpenInInterface::class, RemoveModifierFix.removeRedundantOpenModifier)
registerPsiQuickFixes(KtFirDiagnostic.NonAbstractFunctionWithNoBody::class, AddFunctionBodyFix, AddModifierFix.addAbstractModifier)
registerPsiQuickFixes(
KtFirDiagnostic.RedundantOpenInInterface::class,
RemoveModifierFix.createRemoveModifierFromListOwnerFactoryByModifierListOwner(
modifier = KtTokens.OPEN_KEYWORD,
isRedundant = true
)
KtFirDiagnostic.AbstractPropertyInNonAbstractClass::class,
AddModifierFix.addAbstractToContainingClass,
RemoveModifierFix.removeAbstractModifier
)
registerPsiQuickFixes(
KtFirDiagnostic.AbstractFunctionInNonAbstractClass::class,
AddModifierFix.addAbstractToContainingClass,
RemoveModifierFix.removeAbstractModifier
)
}
......
......@@ -19,6 +19,184 @@ import java.util.regex.Pattern;
@SuppressWarnings("all")
@RunWith(JUnit3RunnerWithInners.class)
public class HighLevelQuickFixTestGenerated extends AbstractHighLevelQuickFixTest {
@TestMetadata("idea/testData/quickfix/abstract")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Abstract extends AbstractHighLevelQuickFixTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
@TestMetadata("abstractFunctionInNonAbstractClass.kt")
public void testAbstractFunctionInNonAbstractClass() throws Exception {
runTest("idea/testData/quickfix/abstract/abstractFunctionInNonAbstractClass.kt");
}
@TestMetadata("abstractFunctionWithBody.kt")
public void testAbstractFunctionWithBody() throws Exception {
runTest("idea/testData/quickfix/abstract/abstractFunctionWithBody.kt");
}
@TestMetadata("abstractFunctionWithBody2.kt")
public void testAbstractFunctionWithBody2() throws Exception {
runTest("idea/testData/quickfix/abstract/abstractFunctionWithBody2.kt");
}
@TestMetadata("abstractFunctionWithBody3.kt")
public void testAbstractFunctionWithBody3() throws Exception {
runTest("idea/testData/quickfix/abstract/abstractFunctionWithBody3.kt");
}
@TestMetadata("abstractFunctionWithBodyWithComments.kt")
public void testAbstractFunctionWithBodyWithComments() throws Exception {
runTest("idea/testData/quickfix/abstract/abstractFunctionWithBodyWithComments.kt");
}
@TestMetadata("abstractFunctionWithBodyWithComments2.kt")
public void testAbstractFunctionWithBodyWithComments2() throws Exception {
runTest("idea/testData/quickfix/abstract/abstractFunctionWithBodyWithComments2.kt");
}
@TestMetadata("abstractPropertyInCompanionObject.kt")
public void testAbstractPropertyInCompanionObject() throws Exception {
runTest("idea/testData/quickfix/abstract/abstractPropertyInCompanionObject.kt");
}
@TestMetadata("abstractPropertyInNonAbstractClass1.kt")
public void testAbstractPropertyInNonAbstractClass1() throws Exception {
runTest("idea/testData/quickfix/abstract/abstractPropertyInNonAbstractClass1.kt");
}
@TestMetadata("abstractPropertyInNonAbstractClass2.kt")
public void testAbstractPropertyInNonAbstractClass2() throws Exception {
runTest("idea/testData/quickfix/abstract/abstractPropertyInNonAbstractClass2.kt");
}
@TestMetadata("abstractPropertyInNonAbstractClass3.kt")
public void testAbstractPropertyInNonAbstractClass3() throws Exception {
runTest("idea/testData/quickfix/abstract/abstractPropertyInNonAbstractClass3.kt");
}
@TestMetadata("abstractPropertyInPrimaryConstructorParameters.kt")
public void testAbstractPropertyInPrimaryConstructorParameters() throws Exception {
runTest("idea/testData/quickfix/abstract/abstractPropertyInPrimaryConstructorParameters.kt");
}
@TestMetadata("abstractPropertyNotInClass.kt")
public void testAbstractPropertyNotInClass() throws Exception {
runTest("idea/testData/quickfix/abstract/abstractPropertyNotInClass.kt");
}
@TestMetadata("abstractPropertyWIthInitializer2.kt")
public void testAbstractPropertyWIthInitializer2() throws Exception {
runTest("idea/testData/quickfix/abstract/abstractPropertyWIthInitializer2.kt");
}
@TestMetadata("abstractPropertyWIthInitializer3.kt")
public void testAbstractPropertyWIthInitializer3() throws Exception {
runTest("idea/testData/quickfix/abstract/abstractPropertyWIthInitializer3.kt");
}
@TestMetadata("abstractPropertyWithGetter1.kt")
public void testAbstractPropertyWithGetter1() throws Exception {
runTest("idea/testData/quickfix/abstract/abstractPropertyWithGetter1.kt");
}
@TestMetadata("abstractPropertyWithGetter2.kt")
public void testAbstractPropertyWithGetter2() throws Exception {
runTest("idea/testData/quickfix/abstract/abstractPropertyWithGetter2.kt");
}
@TestMetadata("abstractPropertyWithInitializer1.kt")
public void testAbstractPropertyWithInitializer1() throws Exception {
runTest("idea/testData/quickfix/abstract/abstractPropertyWithInitializer1.kt");
}
@TestMetadata("abstractPropertyWithSetter.kt")
public void testAbstractPropertyWithSetter() throws Exception {
runTest("idea/testData/quickfix/abstract/abstractPropertyWithSetter.kt");
}
public void testAllFilesPresentInAbstract() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/testData/quickfix/abstract"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), null, true);
}
@TestMetadata("makeEnumEntryAbstract.kt")
public void testMakeEnumEntryAbstract() throws Exception {
runTest("idea/testData/quickfix/abstract/makeEnumEntryAbstract.kt");
}
@TestMetadata("makeInlineClassAbstract.kt")
public void testMakeInlineClassAbstract() throws Exception {
runTest("idea/testData/quickfix/abstract/makeInlineClassAbstract.kt");
}
@TestMetadata("makeObjectMemberAbstract.kt")
public void testMakeObjectMemberAbstract() throws Exception {
runTest("idea/testData/quickfix/abstract/makeObjectMemberAbstract.kt");
}
@TestMetadata("makeTopLevelAbstract.kt")
public void testMakeTopLevelAbstract() throws Exception {
runTest("idea/testData/quickfix/abstract/makeTopLevelAbstract.kt");
}
@TestMetadata("manyImpl.kt")
public void testManyImpl() throws Exception {
runTest("idea/testData/quickfix/abstract/manyImpl.kt");
}
@TestMetadata("mustBeInitializedOrBeAbstract.kt")
public void testMustBeInitializedOrBeAbstract() throws Exception {
runTest("idea/testData/quickfix/abstract/mustBeInitializedOrBeAbstract.kt");
}
@TestMetadata("mustBeInitializedOrBeAbstractInFinalClass.kt")
public void testMustBeInitializedOrBeAbstractInFinalClass() throws Exception {
runTest("idea/testData/quickfix/abstract/mustBeInitializedOrBeAbstractInFinalClass.kt");
}
@TestMetadata("mustBeInitializedOrBeAbstractInOpenClass.kt")
public void testMustBeInitializedOrBeAbstractInOpenClass() throws Exception {
runTest("idea/testData/quickfix/abstract/mustBeInitializedOrBeAbstractInOpenClass.kt");
}
@TestMetadata("mustBeInitializedOrBeAbstractInSealedClass.kt")
public void testMustBeInitializedOrBeAbstractInSealedClass() throws Exception {
runTest("idea/testData/quickfix/abstract/mustBeInitializedOrBeAbstractInSealedClass.kt");
}
@TestMetadata("nonAbstractFunctionWithNoBody.kt")
public void testNonAbstractFunctionWithNoBody() throws Exception {
runTest("idea/testData/quickfix/abstract/nonAbstractFunctionWithNoBody.kt");
}
@TestMetadata("nonMemberAbstractFunction.kt")
public void testNonMemberAbstractFunction() throws Exception {
runTest("idea/testData/quickfix/abstract/nonMemberAbstractFunction.kt");
}
@TestMetadata("nonMemberFunctionNoBody.kt")
public void testNonMemberFunctionNoBody() throws Exception {
runTest("idea/testData/quickfix/abstract/nonMemberFunctionNoBody.kt");
}
@TestMetadata("notImplementedMember.kt")
public void testNotImplementedMember() throws Exception {
runTest("idea/testData/quickfix/abstract/notImplementedMember.kt");
}
@TestMetadata("notImplementedMemberFromAbstractClass.kt")
public void testNotImplementedMemberFromAbstractClass() throws Exception {
runTest("idea/testData/quickfix/abstract/notImplementedMemberFromAbstractClass.kt");
}
@TestMetadata("replaceOpen.kt")
public void testReplaceOpen() throws Exception {
runTest("idea/testData/quickfix/abstract/replaceOpen.kt");
}
}
@TestMetadata("idea/testData/quickfix/lateinit")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
......
......@@ -5,14 +5,13 @@
package org.jetbrains.kotlin.idea.quickfix
import com.intellij.codeInsight.intention.IntentionAction
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtFunction
import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
class AddFunctionBodyFix(element: KtFunction) : KotlinPsiOnlyQuickFixAction<KtFunction>(element) {
override fun getFamilyName() = KotlinBundle.message("fix.add.function.body")
......@@ -30,9 +29,7 @@ class AddFunctionBodyFix(element: KtFunction) : KotlinPsiOnlyQuickFixAction<KtFu
}
}
companion object : KotlinSingleIntentionActionFactory() {
public override fun createAction(diagnostic: Diagnostic): AddFunctionBodyFix? {
return diagnostic.psiElement.getNonStrictParentOfType<KtFunction>()?.let(::AddFunctionBodyFix)
}
companion object : QuickFixesPsiBasedFactory<KtFunction>(KtFunction::class, PsiElementSuitabilityCheckers.ALWAYS_SUITABLE) {
override fun doCreateQuickFix(psiElement: KtFunction): List<IntentionAction> = listOfNotNull(AddFunctionBodyFix(psiElement))
}
}
......@@ -106,9 +106,14 @@ open class AddModifierFix(
}
companion object : Factory<AddModifierFix> {
private val modalityModifiers = setOf(KtTokens.ABSTRACT_KEYWORD, KtTokens.OPEN_KEYWORD, KtTokens.FINAL_KEYWORD)
val addAbstractModifier: QuickFixesPsiBasedFactory<PsiElement> = AddModifierFix.createFactory(KtTokens.ABSTRACT_KEYWORD)
val addAbstractToContainingClass: QuickFixesPsiBasedFactory<PsiElement> =
AddModifierFix.createFactory(KtTokens.ABSTRACT_KEYWORD, KtClassOrObject::class.java)
private val modalityModifiers: Set<KtModifierKeywordToken> =
setOf(KtTokens.ABSTRACT_KEYWORD, KtTokens.OPEN_KEYWORD, KtTokens.FINAL_KEYWORD)
override fun createModifierFix(element: KtModifierListOwner, modifier: KtModifierKeywordToken): AddModifierFix =
AddModifierFix(element, modifier)
}
}
\ No newline at end of file
}
......@@ -51,8 +51,15 @@ class RemoveModifierFix(
}
companion object {
val removeRedundantModifier = createRemoveModifierFactory(isRedundant = true)
val removeNonRedundantModifier = createRemoveModifierFactory(isRedundant = false)
val removeRedundantModifier: QuickFixesPsiBasedFactory<PsiElement> = createRemoveModifierFactory(isRedundant = true)
val removeNonRedundantModifier: QuickFixesPsiBasedFactory<PsiElement> = createRemoveModifierFactory(isRedundant = false)
val removeAbstractModifier: QuickFixesPsiBasedFactory<PsiElement> =
createRemoveModifierFromListOwnerPsiBasedFactory(KtTokens.ABSTRACT_KEYWORD)
val removeRedundantOpenModifier: QuickFixesPsiBasedFactory<KtModifierListOwner> =
createRemoveModifierFromListOwnerFactoryByModifierListOwner(
modifier = KtTokens.OPEN_KEYWORD,
isRedundant = true
)
@Deprecated(
"For binary compatibility",
......
// "Make 'foo' not abstract" "true"
class A() {
<caret>abstract fun foo() {}
}
\ No newline at end of file
}
/* FIR_COMPARISON */
// "Make 'foo' not abstract" "true"
class A() {
fun foo() {}
}
\ No newline at end of file
}
/* FIR_COMPARISON */
......@@ -7,4 +7,5 @@ class Owner {
companion object {
<caret>abstract val x: Int
}
}
\ No newline at end of file
}
/* FIR_COMPARISON */
......@@ -2,3 +2,4 @@
class A() {
<caret>abstract var i : Int
}
/* FIR_COMPARISON */
......@@ -2,3 +2,4 @@
abstract class A() {
<caret>abstract var i : Int
}
/* FIR_COMPARISON */
......@@ -2,3 +2,4 @@
class A() {
<caret>abstract var i : Int = 0
}
/* FIR_COMPARISON */
......@@ -2,3 +2,4 @@
class A() {
var i : Int = 0
}
/* FIR_COMPARISON */
......@@ -2,3 +2,4 @@
public class A() {
<caret>abstract var i : Int
}
/* FIR_COMPARISON */
......@@ -2,3 +2,4 @@
public abstract class A() {
<caret>abstract var i : Int
}
/* FIR_COMPARISON */
......@@ -2,4 +2,5 @@
class B {
<caret>abstract val i: Int = 0
get() = field
}
\ No newline at end of file
}
/* FIR_COMPARISON */
......@@ -2,4 +2,5 @@
class B {
val i: Int = 0
get() = field
}
\ No newline at end of file
}
/* FIR_COMPARISON */
......@@ -2,3 +2,4 @@
class A {
<caret>abstract var i = 0
}
/* FIR_COMPARISON */
......@@ -2,3 +2,4 @@
class A {
<caret>var i = 0
}
/* FIR_COMPARISON */
......@@ -3,3 +3,4 @@ class B {
abstract<caret> var j: Int = 0
set(v: Int) {}
}
/* FIR_COMPARISON */
......@@ -3,3 +3,4 @@ class B {
var j: Int = 0
set(v: Int) {}
}
/* FIR_COMPARISON */
......@@ -6,4 +6,5 @@ enum class E {
<caret>A;
abstract fun foo()
}
\ No newline at end of file
}
/* FIR_COMPARISON */
......@@ -9,4 +9,5 @@ interface I {
fun foo(): String
}
inline class A<caret> : I
\ No newline at end of file
inline class A<caret> : I
/* FIR_COMPARISON */
......@@ -7,4 +7,5 @@
object O {
<caret>fun foo()
}
\ No newline at end of file
}
/* FIR_COMPARISON */
......@@ -5,4 +5,5 @@
// ACTION: Make private
// ERROR: Function 'foo' must have a body
<caret>fun foo()
\ No newline at end of file
<caret>fun foo()
/* FIR_COMPARISON */
......@@ -18,4 +18,5 @@ object Impl : D, E {
override fun foo() {}
}
<caret>class X : D by Impl, E by Impl {}
\ No newline at end of file
<caret>class X : D by Impl, E by Impl {}
/* FIR_COMPARISON */
......@@ -2,3 +2,4 @@
sealed class A() {
fun <caret>i() : Int
}
/* FIR_COMPARISON */
......@@ -2,3 +2,4 @@
sealed class A() {
abstract fun <caret>i() : Int
}
/* FIR_COMPARISON */
......@@ -2,3 +2,4 @@
class A() {
fun <caret>foo()
}
/* FIR_COMPARISON */
......@@ -2,3 +2,4 @@
class A() {
fun <caret>foo() {}
}
/* FIR_COMPARISON */
......@@ -2,3 +2,4 @@
abstract class B() {
open fun <caret>foo()
}
/* FIR_COMPARISON */
......@@ -2,3 +2,4 @@
abstract class B() {
abstract fun <caret>foo()
}
/* FIR_COMPARISON */
......@@ -29,9 +29,9 @@ public class KaptToolIntegrationTestGenerated extends AbstractKaptToolIntegratio
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/kapt3/kapt3-cli/testData/integration"), Pattern.compile("^([^\\.]+)$"), null, false);
}
@TestMetadata("defaultPackage")
@TestMetadata("argfile")
public void testArgfile() throws Exception {
runTest("plugins/kapt3/kapt3-cli/testData/integration/defaultPackage/");
runTest("plugins/kapt3/kapt3-cli/testData/integration/argfile/");
}
@TestMetadata("correctErrorTypesOff")
......@@ -44,6 +44,11 @@ public class KaptToolIntegrationTestGenerated extends AbstractKaptToolIntegratio
runTest("plugins/kapt3/kapt3-cli/testData/integration/correctErrorTypesOn/");
}
@TestMetadata("defaultPackage")
public void testDefaultPackage() throws Exception {
runTest("plugins/kapt3/kapt3-cli/testData/integration/defaultPackage/");
}
@TestMetadata("kotlinFileGeneration")
public void testKotlinFileGeneration() throws Exception {
runTest("plugins/kapt3/kapt3-cli/testData/integration/kotlinFileGeneration/");
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册