From e340af51df73e97e60a8609a90d00027d2e11011 Mon Sep 17 00:00:00 2001 From: Toshiaki Kameyama Date: Wed, 6 Feb 2019 23:53:27 +0900 Subject: [PATCH] Add "Rename class to containing file name" intention #KT-25262 Fixed --- idea/resources/META-INF/plugin-common.xml | 5 +++ .../after.kt.template | 4 ++ .../before.kt.template | 4 ++ .../description.html | 5 +++ ...enameClassToContainingFileNameIntention.kt | 40 +++++++++++++++++ .../.intention | 1 + .../renameClassToContainingFileName/Basic.kt | 1 + .../Basic.kt.after | 1 + .../renameClassToContainingFileName/Basic2.kt | 1 + .../Basic2.kt.after | 1 + .../HasSameNameClass.kt | 4 ++ .../HasSameNameObject.kt | 4 ++ .../SameName.kt | 2 + .../startWithLowerCase.kt | 2 + .../intentions/IntentionTestGenerated.java | 43 +++++++++++++++++++ 15 files changed, 118 insertions(+) create mode 100644 idea/resources/intentionDescriptions/RenameClassToContainingFileNameIntention/after.kt.template create mode 100644 idea/resources/intentionDescriptions/RenameClassToContainingFileNameIntention/before.kt.template create mode 100644 idea/resources/intentionDescriptions/RenameClassToContainingFileNameIntention/description.html create mode 100644 idea/src/org/jetbrains/kotlin/idea/intentions/RenameClassToContainingFileNameIntention.kt create mode 100644 idea/testData/intentions/renameClassToContainingFileName/.intention create mode 100644 idea/testData/intentions/renameClassToContainingFileName/Basic.kt create mode 100644 idea/testData/intentions/renameClassToContainingFileName/Basic.kt.after create mode 100644 idea/testData/intentions/renameClassToContainingFileName/Basic2.kt create mode 100644 idea/testData/intentions/renameClassToContainingFileName/Basic2.kt.after create mode 100644 idea/testData/intentions/renameClassToContainingFileName/HasSameNameClass.kt create mode 100644 idea/testData/intentions/renameClassToContainingFileName/HasSameNameObject.kt create mode 100644 idea/testData/intentions/renameClassToContainingFileName/SameName.kt create mode 100644 idea/testData/intentions/renameClassToContainingFileName/startWithLowerCase.kt diff --git a/idea/resources/META-INF/plugin-common.xml b/idea/resources/META-INF/plugin-common.xml index d858b03ee53..cc029cabf06 100644 --- a/idea/resources/META-INF/plugin-common.xml +++ b/idea/resources/META-INF/plugin-common.xml @@ -1732,6 +1732,11 @@ Kotlin + + org.jetbrains.kotlin.idea.intentions.RenameClassToContainingFileNameIntention + Kotlin + + Bar { +} \ No newline at end of file diff --git a/idea/resources/intentionDescriptions/RenameClassToContainingFileNameIntention/before.kt.template b/idea/resources/intentionDescriptions/RenameClassToContainingFileNameIntention/before.kt.template new file mode 100644 index 00000000000..b41029b4800 --- /dev/null +++ b/idea/resources/intentionDescriptions/RenameClassToContainingFileNameIntention/before.kt.template @@ -0,0 +1,4 @@ +// Bar.kt + +class Foo { +} \ No newline at end of file diff --git a/idea/resources/intentionDescriptions/RenameClassToContainingFileNameIntention/description.html b/idea/resources/intentionDescriptions/RenameClassToContainingFileNameIntention/description.html new file mode 100644 index 00000000000..89aa9f8eb08 --- /dev/null +++ b/idea/resources/intentionDescriptions/RenameClassToContainingFileNameIntention/description.html @@ -0,0 +1,5 @@ + + +This intention renames the class to containing file name. + + \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/RenameClassToContainingFileNameIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/RenameClassToContainingFileNameIntention.kt new file mode 100644 index 00000000000..66ea6929246 --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/RenameClassToContainingFileNameIntention.kt @@ -0,0 +1,40 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.idea.intentions + +import com.intellij.openapi.editor.Editor +import com.intellij.openapi.util.TextRange +import com.intellij.openapi.util.io.FileUtil +import com.intellij.refactoring.RefactoringSettings +import com.intellij.refactoring.rename.RenameProcessor +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi.KtClassOrObject +import org.jetbrains.kotlin.renderer.render + +class RenameClassToContainingFileNameIntention : SelfTargetingRangeIntention( + KtClassOrObject::class.java, "Rename class to containing file name" +) { + override fun startInWriteAction() = false + + override fun applicabilityRange(element: KtClassOrObject): TextRange? { + if (!element.isTopLevel()) return null + val fileName = FileUtil.getNameWithoutExtension(element.containingKtFile.name) + if (fileName == element.name + || fileName[0].isLowerCase() + || !Name.isValidIdentifier(fileName) + || Name.identifier(fileName).render() != fileName + || element.containingKtFile.declarations.any { it is KtClassOrObject && it.name == fileName } + ) return null + text = "Rename class to $fileName" + return element.nameIdentifier?.textRange + } + + override fun applyTo(element: KtClassOrObject, editor: Editor?) { + val file = element.containingKtFile + val fileName = FileUtil.getNameWithoutExtension(element.containingKtFile.name) + RenameProcessor(file.project, element, fileName, false, false).run() + } +} \ No newline at end of file diff --git a/idea/testData/intentions/renameClassToContainingFileName/.intention b/idea/testData/intentions/renameClassToContainingFileName/.intention new file mode 100644 index 00000000000..140bcf8492e --- /dev/null +++ b/idea/testData/intentions/renameClassToContainingFileName/.intention @@ -0,0 +1 @@ +org.jetbrains.kotlin.idea.intentions.RenameClassToContainingFileNameIntention diff --git a/idea/testData/intentions/renameClassToContainingFileName/Basic.kt b/idea/testData/intentions/renameClassToContainingFileName/Basic.kt new file mode 100644 index 00000000000..2689a664dcc --- /dev/null +++ b/idea/testData/intentions/renameClassToContainingFileName/Basic.kt @@ -0,0 +1 @@ +class Foo \ No newline at end of file diff --git a/idea/testData/intentions/renameClassToContainingFileName/Basic.kt.after b/idea/testData/intentions/renameClassToContainingFileName/Basic.kt.after new file mode 100644 index 00000000000..db46da87f1b --- /dev/null +++ b/idea/testData/intentions/renameClassToContainingFileName/Basic.kt.after @@ -0,0 +1 @@ +class Basic \ No newline at end of file diff --git a/idea/testData/intentions/renameClassToContainingFileName/Basic2.kt b/idea/testData/intentions/renameClassToContainingFileName/Basic2.kt new file mode 100644 index 00000000000..efbbd4f785f --- /dev/null +++ b/idea/testData/intentions/renameClassToContainingFileName/Basic2.kt @@ -0,0 +1 @@ +object Foo \ No newline at end of file diff --git a/idea/testData/intentions/renameClassToContainingFileName/Basic2.kt.after b/idea/testData/intentions/renameClassToContainingFileName/Basic2.kt.after new file mode 100644 index 00000000000..78cbe5815e0 --- /dev/null +++ b/idea/testData/intentions/renameClassToContainingFileName/Basic2.kt.after @@ -0,0 +1 @@ +object Basic2 \ No newline at end of file diff --git a/idea/testData/intentions/renameClassToContainingFileName/HasSameNameClass.kt b/idea/testData/intentions/renameClassToContainingFileName/HasSameNameClass.kt new file mode 100644 index 00000000000..c3e085cb778 --- /dev/null +++ b/idea/testData/intentions/renameClassToContainingFileName/HasSameNameClass.kt @@ -0,0 +1,4 @@ +// IS_APPLICABLE: false +class Foo + +class HasSameNameClass \ No newline at end of file diff --git a/idea/testData/intentions/renameClassToContainingFileName/HasSameNameObject.kt b/idea/testData/intentions/renameClassToContainingFileName/HasSameNameObject.kt new file mode 100644 index 00000000000..401a352b194 --- /dev/null +++ b/idea/testData/intentions/renameClassToContainingFileName/HasSameNameObject.kt @@ -0,0 +1,4 @@ +// IS_APPLICABLE: false +class Foo + +object HasSameNameObject \ No newline at end of file diff --git a/idea/testData/intentions/renameClassToContainingFileName/SameName.kt b/idea/testData/intentions/renameClassToContainingFileName/SameName.kt new file mode 100644 index 00000000000..baf22b6e310 --- /dev/null +++ b/idea/testData/intentions/renameClassToContainingFileName/SameName.kt @@ -0,0 +1,2 @@ +// IS_APPLICABLE: false +class SameName \ No newline at end of file diff --git a/idea/testData/intentions/renameClassToContainingFileName/startWithLowerCase.kt b/idea/testData/intentions/renameClassToContainingFileName/startWithLowerCase.kt new file mode 100644 index 00000000000..fead0993d3b --- /dev/null +++ b/idea/testData/intentions/renameClassToContainingFileName/startWithLowerCase.kt @@ -0,0 +1,2 @@ +// IS_APPLICABLE: false +class Foo \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java index 1a7122a60f8..e44d5f0be66 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java @@ -14837,6 +14837,49 @@ public class IntentionTestGenerated extends AbstractIntentionTest { } } + @TestMetadata("idea/testData/intentions/renameClassToContainingFileName") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class RenameClassToContainingFileName extends AbstractIntentionTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath); + } + + public void testAllFilesPresentInRenameClassToContainingFileName() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/intentions/renameClassToContainingFileName"), Pattern.compile("^([\\w\\-_]+)\\.(kt|kts)$"), TargetBackend.ANY, true); + } + + @TestMetadata("Basic.kt") + public void testBasic() throws Exception { + runTest("idea/testData/intentions/renameClassToContainingFileName/Basic.kt"); + } + + @TestMetadata("Basic2.kt") + public void testBasic2() throws Exception { + runTest("idea/testData/intentions/renameClassToContainingFileName/Basic2.kt"); + } + + @TestMetadata("HasSameNameClass.kt") + public void testHasSameNameClass() throws Exception { + runTest("idea/testData/intentions/renameClassToContainingFileName/HasSameNameClass.kt"); + } + + @TestMetadata("HasSameNameObject.kt") + public void testHasSameNameObject() throws Exception { + runTest("idea/testData/intentions/renameClassToContainingFileName/HasSameNameObject.kt"); + } + + @TestMetadata("SameName.kt") + public void testSameName() throws Exception { + runTest("idea/testData/intentions/renameClassToContainingFileName/SameName.kt"); + } + + @TestMetadata("startWithLowerCase.kt") + public void testStartWithLowerCase() throws Exception { + runTest("idea/testData/intentions/renameClassToContainingFileName/startWithLowerCase.kt"); + } + } + @TestMetadata("idea/testData/intentions/replaceAddWithPlusAssign") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class)