diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/JetBundle.properties b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/JetBundle.properties index 541d383712f..f1e470eb67f 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/JetBundle.properties +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/JetBundle.properties @@ -181,6 +181,8 @@ change.to.function.invocation=Change to function invocation migrate.sure=Replace sure() calls by !! in project migrate.class.object.to.default=Replace 'class' keyword with 'default' modifier migrate.class.object.to.default.family=Replace 'class' Keyword with 'default' Modifier +migrate.class.object.to.default.in.whole.project=Replace 'class' keyword with 'default' modifier in whole project +migrate.class.object.to.default.in.whole.project.family=Replace 'class' Keyword with 'default' Modifier in Whole Project remove.val.var.from.parameter=Remove ''{0}'' from parameter add.override.to.equals.hashCode.toString=Add 'override' to equals, hashCode, toString in project add.when.else.branch.action.family.name=Add Else Branch diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/ClassObjectToDefaultObjectFix.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/ClassObjectToDefaultObjectFix.kt index 8f917831ae7..0c0e1cdd567 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/ClassObjectToDefaultObjectFix.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/ClassObjectToDefaultObjectFix.kt @@ -20,9 +20,9 @@ import com.intellij.openapi.editor.Editor import com.intellij.openapi.project.Project import org.jetbrains.kotlin.diagnostics.Diagnostic import org.jetbrains.kotlin.idea.JetBundle +import org.jetbrains.kotlin.idea.project.PluginJetFilesProvider import org.jetbrains.kotlin.lexer.JetTokens -import org.jetbrains.kotlin.psi.JetFile -import org.jetbrains.kotlin.psi.JetObjectDeclaration +import org.jetbrains.kotlin.psi.* public class ClassObjectToDefaultObjectFix(private val elem: JetObjectDeclaration) : JetIntentionAction(elem) { override fun getText(): String = JetBundle.message("migrate.class.object.to.default") @@ -30,12 +30,44 @@ public class ClassObjectToDefaultObjectFix(private val elem: JetObjectDeclaratio override fun getFamilyName(): String = JetBundle.message("migrate.class.object.to.default.family") override fun invoke(project: Project, editor: Editor, file: JetFile) { - elem.getClassKeyword()?.delete() - elem.addModifier(JetTokens.DEFAULT_KEYWORD) + classKeywordToDefaultModifier(elem) } default object Factory : JetSingleIntentionActionFactory() { override fun createAction(diagnostic: Diagnostic) = (diagnostic.getPsiElement() as? JetObjectDeclaration)?.let { ClassObjectToDefaultObjectFix(it) } + + fun classKeywordToDefaultModifier(objectDeclaration: JetObjectDeclaration) { + objectDeclaration.getClassKeyword()?.delete() + if (!objectDeclaration.hasModifier(JetTokens.DEFAULT_KEYWORD)) { + objectDeclaration.addModifier(JetTokens.DEFAULT_KEYWORD) + } + } + } +} + +public class ClassObjectToDefaultObjectInWholeProjectFix(private val elem: JetObjectDeclaration) : JetIntentionAction(elem) { + override fun getText(): String = JetBundle.message("migrate.class.object.to.default.in.whole.project") + + override fun getFamilyName(): String = JetBundle.message("migrate.class.object.to.default.in.whole.project.family") + + override fun invoke(project: Project, editor: Editor, file: JetFile) { + val files = PluginJetFilesProvider.allFilesInProject(file.getProject()) + + files.forEach { it.accept(ClassObjectToDefaultObjectVisitor) } + } + + private object ClassObjectToDefaultObjectVisitor : JetTreeVisitorVoid() { + override fun visitObjectDeclaration(objectDeclaration: JetObjectDeclaration) { + objectDeclaration.acceptChildren(this) + if (objectDeclaration.getClassKeyword() != null) { + ClassObjectToDefaultObjectFix.classKeywordToDefaultModifier(objectDeclaration) + } + } + } + + default object Factory : JetSingleIntentionActionFactory() { + override fun createAction(diagnostic: Diagnostic) = + (diagnostic.getPsiElement() as? JetObjectDeclaration)?.let { ClassObjectToDefaultObjectInWholeProjectFix(it) } } } \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.java b/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.java index 3fcfd1ebec6..77320987546 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.java +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.java @@ -96,7 +96,8 @@ public class QuickFixRegistrar { JetSingleIntentionActionFactory removeRedundantModifierFactory = RemoveModifierFix.createRemoveModifierFactory(true); QuickFixes.factories.put(REDUNDANT_MODIFIER, removeRedundantModifierFactory); - QuickFixes.factories.put(ABSTRACT_MODIFIER_IN_TRAIT, RemoveModifierFix.createRemoveModifierFromListOwnerFactory(ABSTRACT_KEYWORD, true)); + QuickFixes.factories.put(ABSTRACT_MODIFIER_IN_TRAIT, RemoveModifierFix.createRemoveModifierFromListOwnerFactory(ABSTRACT_KEYWORD, + true)); QuickFixes.factories.put(OPEN_MODIFIER_IN_TRAIT, RemoveModifierFix.createRemoveModifierFromListOwnerFactory(OPEN_KEYWORD, true)); QuickFixes.factories.put(TRAIT_CAN_NOT_BE_FINAL, removeFinalModifierFactory); QuickFixes.factories.put(REDUNDANT_PROJECTION, RemoveModifierFix.createRemoveProjectionFactory(true)); @@ -296,5 +297,6 @@ public class QuickFixRegistrar { QuickFixes.factories.put(UNRESOLVED_REFERENCE, CreateClassFromCallWithConstructorCalleeActionFactory.INSTANCE$); QuickFixes.factories.put(DEPRECATED_CLASS_OBJECT_SYNTAX, ClassObjectToDefaultObjectFix.Factory); + QuickFixes.factories.put(DEPRECATED_CLASS_OBJECT_SYNTAX, ClassObjectToDefaultObjectInWholeProjectFix.Factory); } } diff --git a/idea/testData/quickfix/migration/classObjectToDefaultMultiple.after.data.Sample.kt b/idea/testData/quickfix/migration/classObjectToDefaultMultiple.after.data.Sample.kt new file mode 100644 index 00000000000..e208663a588 --- /dev/null +++ b/idea/testData/quickfix/migration/classObjectToDefaultMultiple.after.data.Sample.kt @@ -0,0 +1,29 @@ +class D { + default public object Named { + + } +} + +trait H { + default object { + + } +} + +class E { + default object { + class D { + default object { + class D { + default object + } + } + } + } +} + +class K { + default object Default + + class Object +} \ No newline at end of file diff --git a/idea/testData/quickfix/migration/classObjectToDefaultMultiple.after.kt b/idea/testData/quickfix/migration/classObjectToDefaultMultiple.after.kt new file mode 100644 index 00000000000..4870f704636 --- /dev/null +++ b/idea/testData/quickfix/migration/classObjectToDefaultMultiple.after.kt @@ -0,0 +1,19 @@ +// "Replace 'class' keyword with 'default' modifier in whole project" "true" + +class A { + public default object { + + } +} + +class B { + default object { + + } +} + +class C { + default object Named { + + } +} diff --git a/idea/testData/quickfix/migration/classObjectToDefaultMultiple.before.Main.kt b/idea/testData/quickfix/migration/classObjectToDefaultMultiple.before.Main.kt new file mode 100644 index 00000000000..8549616ebc9 --- /dev/null +++ b/idea/testData/quickfix/migration/classObjectToDefaultMultiple.before.Main.kt @@ -0,0 +1,19 @@ +// "Replace 'class' keyword with 'default' modifier in whole project" "true" + +class A { + public class object { + + } +} + +class B { + class object { + + } +} + +class C { + class object Named { + + } +} diff --git a/idea/testData/quickfix/migration/classObjectToDefaultMultiple.before.data.Sample.kt b/idea/testData/quickfix/migration/classObjectToDefaultMultiple.before.data.Sample.kt new file mode 100644 index 00000000000..09f47aa7ed6 --- /dev/null +++ b/idea/testData/quickfix/migration/classObjectToDefaultMultiple.before.data.Sample.kt @@ -0,0 +1,29 @@ +class D { + default public class object Named { + + } +} + +trait H { + default class object { + + } +} + +class E { + class object { + class D { + class object { + class D { + class object + } + } + } + } +} + +class K { + default object Default + + class Object +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java index ca29355a078..e78eaa15e95 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java @@ -35,6 +35,7 @@ import java.util.regex.Pattern; QuickFixMultiFileTestGenerated.AutoImports.class, QuickFixMultiFileTestGenerated.ChangeSignature.class, QuickFixMultiFileTestGenerated.CreateFromUsage.class, + QuickFixMultiFileTestGenerated.Migration.class, QuickFixMultiFileTestGenerated.Modifiers.class, QuickFixMultiFileTestGenerated.Nullables.class, QuickFixMultiFileTestGenerated.Override.class, @@ -853,6 +854,21 @@ public class QuickFixMultiFileTestGenerated extends AbstractQuickFixMultiFileTes } } + @TestMetadata("idea/testData/quickfix/migration") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Migration extends AbstractQuickFixMultiFileTest { + public void testAllFilesPresentInMigration() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/migration"), Pattern.compile("^(\\w+)\\.before\\.Main\\.kt$"), true); + } + + @TestMetadata("classObjectToDefaultMultiple.before.Main.kt") + public void testClassObjectToDefaultMultiple() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/classObjectToDefaultMultiple.before.Main.kt"); + doTestWithExtraFile(fileName); + } + } + @TestMetadata("idea/testData/quickfix/modifiers") @TestDataPath("$PROJECT_ROOT") @InnerTestClasses({