From a9c1c3edb6540550de706b103c7bb9920509cc90 Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Tue, 12 May 2015 18:04:27 +0300 Subject: [PATCH] Add quickfix for missing 'constructor' inside primary ctor --- .../kotlin/psi/JetPrimaryConstructor.java | 8 ++- .../org/jetbrains/kotlin/psi/JetPsiFactory.kt | 3 ++ .../quickfix/MissingConstructorKeywordFix.kt | 51 +++++++++++++++++++ .../idea/quickfix/QuickFixRegistrar.java | 3 ++ .../quickfix/quickfixUtil/quickfixUtil.kt | 7 +++ .../missingConstructorKeyword/basic.kt | 3 ++ .../missingConstructorKeyword/basic.kt.after | 3 ++ .../manyFilesMuitliple.after.data.Sample.kt | 1 + .../manyFilesMuitliple.after.kt | 12 +++++ .../manyFilesMuitliple.before.Main.kt | 12 +++++ .../manyFilesMuitliple.before.data.Sample.kt | 1 + .../QuickFixMultiFileTestGenerated.java | 15 ++++++ .../idea/quickfix/QuickFixTestGenerated.java | 15 ++++++ 13 files changed, 133 insertions(+), 1 deletion(-) create mode 100644 idea/src/org/jetbrains/kotlin/idea/quickfix/MissingConstructorKeywordFix.kt create mode 100644 idea/testData/quickfix/migration/missingConstructorKeyword/basic.kt create mode 100644 idea/testData/quickfix/migration/missingConstructorKeyword/basic.kt.after create mode 100644 idea/testData/quickfix/migration/missingConstructorKeyword/manyFilesMuitliple.after.data.Sample.kt create mode 100644 idea/testData/quickfix/migration/missingConstructorKeyword/manyFilesMuitliple.after.kt create mode 100644 idea/testData/quickfix/migration/missingConstructorKeyword/manyFilesMuitliple.before.Main.kt create mode 100644 idea/testData/quickfix/migration/missingConstructorKeyword/manyFilesMuitliple.before.data.Sample.kt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/JetPrimaryConstructor.java b/compiler/frontend/src/org/jetbrains/kotlin/psi/JetPrimaryConstructor.java index 044e5ebe049..a75cb3afb13 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/JetPrimaryConstructor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/JetPrimaryConstructor.java @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.psi; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.lexer.JetModifierKeywordToken; @@ -85,6 +86,11 @@ public class JetPrimaryConstructor extends JetDeclarationStub(element) { + override fun getFamilyName(): String = getText() + override fun getText(): String = "Add 'constructor' keyword" + + override fun invoke(project: Project, editor: Editor?, file: JetFile?) { + element.addConstructorKeyword() + } + + companion object : JetSingleIntentionActionFactory() { + override fun createAction(diagnostic: Diagnostic): IntentionAction? = + diagnostic.createIntentionForFirstParentOfType(::MissingConstructorKeywordFix) + + public fun createWholeProjectFixFactory(): JetSingleIntentionActionFactory = createIntentionFactory { + JetWholeProjectForEachElementOfTypeFix.createByPredicate( + predicate = { it.getModifierList() != null && !it.hasConstructorKeyword() }, + taskProcessor = { it.addConstructorKeyword() }, + modalTitle = "Adding missing 'constructor' keyword", + name = "Add missing 'constructor' keyword in whole project", + familyName = "Add missing 'constructor' keyword in whole project" + ) + } + } +} diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.java b/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.java index b5a21e0ce25..2ce59f81604 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.java +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.java @@ -334,5 +334,8 @@ public class QuickFixRegistrar { QuickFixes.factories.put(ENUM_ENTRY_USES_DEPRECATED_OR_NO_DELIMITER, DeprecatedEnumEntryDelimiterSyntaxFix.Companion); QuickFixes.factories.put(ENUM_ENTRY_USES_DEPRECATED_OR_NO_DELIMITER, DeprecatedEnumEntryDelimiterSyntaxFix.Companion.createWholeProjectFixFactory()); + + QuickFixes.factories.put(MISSING_CONSTRUCTOR_KEYWORD, MissingConstructorKeywordFix.Companion); + QuickFixes.factories.put(MISSING_CONSTRUCTOR_KEYWORD, MissingConstructorKeywordFix.Companion.createWholeProjectFixFactory()); } } diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/quickfixUtil/quickfixUtil.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/quickfixUtil/quickfixUtil.kt index 22bc14af899..98122a60ba6 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/quickfixUtil/quickfixUtil.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/quickfixUtil/quickfixUtil.kt @@ -21,6 +21,8 @@ import com.intellij.psi.PsiElement import org.jetbrains.kotlin.diagnostics.Diagnostic import org.jetbrains.kotlin.idea.quickfix.JetIntentionAction import org.jetbrains.kotlin.idea.quickfix.JetSingleIntentionActionFactory +import org.jetbrains.kotlin.psi.JetPrimaryConstructor +import org.jetbrains.kotlin.psi.JetPsiFactory import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType inline fun Diagnostic.createIntentionForFirstParentOfType( @@ -33,3 +35,8 @@ fun createIntentionFactory( ) = object : JetSingleIntentionActionFactory() { override fun createAction(diagnostic: Diagnostic) = factory(diagnostic) } + +public fun JetPrimaryConstructor.addConstructorKeyword(): PsiElement? { + val keyword = JetPsiFactory(this).createConstructorKeyword() + return addAfter(keyword, getModifierList() ?: return null) +} diff --git a/idea/testData/quickfix/migration/missingConstructorKeyword/basic.kt b/idea/testData/quickfix/migration/missingConstructorKeyword/basic.kt new file mode 100644 index 00000000000..dd5d4f44a66 --- /dev/null +++ b/idea/testData/quickfix/migration/missingConstructorKeyword/basic.kt @@ -0,0 +1,3 @@ +// "Add 'constructor' keyword" "true" + +class A private() diff --git a/idea/testData/quickfix/migration/missingConstructorKeyword/basic.kt.after b/idea/testData/quickfix/migration/missingConstructorKeyword/basic.kt.after new file mode 100644 index 00000000000..69df9eecd7a --- /dev/null +++ b/idea/testData/quickfix/migration/missingConstructorKeyword/basic.kt.after @@ -0,0 +1,3 @@ +// "Add 'constructor' keyword" "true" + +class A private constructor() diff --git a/idea/testData/quickfix/migration/missingConstructorKeyword/manyFilesMuitliple.after.data.Sample.kt b/idea/testData/quickfix/migration/missingConstructorKeyword/manyFilesMuitliple.after.data.Sample.kt new file mode 100644 index 00000000000..74a9128dcad --- /dev/null +++ b/idea/testData/quickfix/migration/missingConstructorKeyword/manyFilesMuitliple.after.data.Sample.kt @@ -0,0 +1 @@ +class Q private constructor() diff --git a/idea/testData/quickfix/migration/missingConstructorKeyword/manyFilesMuitliple.after.kt b/idea/testData/quickfix/migration/missingConstructorKeyword/manyFilesMuitliple.after.kt new file mode 100644 index 00000000000..438f84e0da6 --- /dev/null +++ b/idea/testData/quickfix/migration/missingConstructorKeyword/manyFilesMuitliple.after.kt @@ -0,0 +1,12 @@ +// "Add missing 'constructor' keyword in whole project" "true" + +annotation class Ann(val x: Int = 1) + +class A @Ann(1)private constructor(x: Int) { + inner class B() // do not insert here + inner class C protected constructor() { + fun foo() { + @data class Local private constructor() + } + } +} diff --git a/idea/testData/quickfix/migration/missingConstructorKeyword/manyFilesMuitliple.before.Main.kt b/idea/testData/quickfix/migration/missingConstructorKeyword/manyFilesMuitliple.before.Main.kt new file mode 100644 index 00000000000..ff08607318d --- /dev/null +++ b/idea/testData/quickfix/migration/missingConstructorKeyword/manyFilesMuitliple.before.Main.kt @@ -0,0 +1,12 @@ +// "Add missing 'constructor' keyword in whole project" "true" + +annotation class Ann(val x: Int = 1) + +class A @Ann(1)private (x: Int) { + inner class B() // do not insert here + inner class C protected () { + fun foo() { + @data class Local private() + } + } +} diff --git a/idea/testData/quickfix/migration/missingConstructorKeyword/manyFilesMuitliple.before.data.Sample.kt b/idea/testData/quickfix/migration/missingConstructorKeyword/manyFilesMuitliple.before.data.Sample.kt new file mode 100644 index 00000000000..49c1b1d2c49 --- /dev/null +++ b/idea/testData/quickfix/migration/missingConstructorKeyword/manyFilesMuitliple.before.data.Sample.kt @@ -0,0 +1 @@ +class Q private() diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java index f4c3d279f07..c933f3486de 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java @@ -903,6 +903,21 @@ public class QuickFixMultiFileTestGenerated extends AbstractQuickFixMultiFileTes } } + @TestMetadata("idea/testData/quickfix/migration/missingConstructorKeyword") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class MissingConstructorKeyword extends AbstractQuickFixMultiFileTest { + public void testAllFilesPresentInMissingConstructorKeyword() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/migration/missingConstructorKeyword"), Pattern.compile("^(\\w+)\\.before\\.Main\\.kt$"), true); + } + + @TestMetadata("manyFilesMuitliple.before.Main.kt") + public void testManyFilesMuitliple() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/missingConstructorKeyword/manyFilesMuitliple.before.Main.kt"); + doTestWithExtraFile(fileName); + } + } + @TestMetadata("idea/testData/quickfix/migration/replaceJavaClassAsAnnotationParameter") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java index bd73b8c78f7..77afa7a2b4a 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java @@ -3280,6 +3280,21 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { } } + @TestMetadata("idea/testData/quickfix/migration/missingConstructorKeyword") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class MissingConstructorKeyword extends AbstractQuickFixTest { + public void testAllFilesPresentInMissingConstructorKeyword() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/migration/missingConstructorKeyword"), Pattern.compile("^(\\w+)\\.kt$"), true); + } + + @TestMetadata("basic.kt") + public void testBasic() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/missingConstructorKeyword/basic.kt"); + doTest(fileName); + } + } + @TestMetadata("idea/testData/quickfix/migration/replaceJavaClassAsAnnotationParameter") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class)