From 58e5c497d078c73269329f6a26fe3502967f59b8 Mon Sep 17 00:00:00 2001 From: nd Date: Fri, 7 Jul 2017 16:34:20 +0200 Subject: [PATCH] Intention to replace add/addAll on a mutable collection with += (#1143) --- .../after.kt.template | 4 ++ .../before.kt.template | 4 ++ .../description.html | 5 ++ idea/src/META-INF/plugin.xml | 5 ++ .../ReplaceAddWithPlusAssignIntention.kt | 56 +++++++++++++++++++ .../replaceAddWithPlusAssign/.intention | 1 + .../replaceAddWithPlusAssign/add.kt | 6 ++ .../replaceAddWithPlusAssign/add.kt.after | 6 ++ .../replaceAddWithPlusAssign/addAll.kt | 6 ++ .../replaceAddWithPlusAssign/addAll.kt.after | 6 ++ .../replaceAddWithPlusAssign/addAllAtIndex.kt | 7 +++ .../replaceAddWithPlusAssign/addAllToVar.kt | 7 +++ .../replaceAddWithPlusAssign/addAtIndex.kt | 7 +++ .../replaceAddWithPlusAssign/addToVar.kt | 7 +++ .../replaceAddWithPlusAssign/nonCollection.kt | 10 ++++ .../intentions/IntentionTestGenerated.java | 51 +++++++++++++++++ 16 files changed, 188 insertions(+) create mode 100644 idea/resources/intentionDescriptions/ReplaceAddWithPlusAssignIntention/after.kt.template create mode 100644 idea/resources/intentionDescriptions/ReplaceAddWithPlusAssignIntention/before.kt.template create mode 100644 idea/resources/intentionDescriptions/ReplaceAddWithPlusAssignIntention/description.html create mode 100644 idea/src/org/jetbrains/kotlin/idea/intentions/ReplaceAddWithPlusAssignIntention.kt create mode 100644 idea/testData/intentions/replaceAddWithPlusAssign/.intention create mode 100644 idea/testData/intentions/replaceAddWithPlusAssign/add.kt create mode 100644 idea/testData/intentions/replaceAddWithPlusAssign/add.kt.after create mode 100644 idea/testData/intentions/replaceAddWithPlusAssign/addAll.kt create mode 100644 idea/testData/intentions/replaceAddWithPlusAssign/addAll.kt.after create mode 100644 idea/testData/intentions/replaceAddWithPlusAssign/addAllAtIndex.kt create mode 100644 idea/testData/intentions/replaceAddWithPlusAssign/addAllToVar.kt create mode 100644 idea/testData/intentions/replaceAddWithPlusAssign/addAtIndex.kt create mode 100644 idea/testData/intentions/replaceAddWithPlusAssign/addToVar.kt create mode 100644 idea/testData/intentions/replaceAddWithPlusAssign/nonCollection.kt diff --git a/idea/resources/intentionDescriptions/ReplaceAddWithPlusAssignIntention/after.kt.template b/idea/resources/intentionDescriptions/ReplaceAddWithPlusAssignIntention/after.kt.template new file mode 100644 index 00000000000..4ced0e10825 --- /dev/null +++ b/idea/resources/intentionDescriptions/ReplaceAddWithPlusAssignIntention/after.kt.template @@ -0,0 +1,4 @@ +fun foo() { + val a = arrayListOf(1, 2, 3) + a += 4 +} \ No newline at end of file diff --git a/idea/resources/intentionDescriptions/ReplaceAddWithPlusAssignIntention/before.kt.template b/idea/resources/intentionDescriptions/ReplaceAddWithPlusAssignIntention/before.kt.template new file mode 100644 index 00000000000..1d620fed757 --- /dev/null +++ b/idea/resources/intentionDescriptions/ReplaceAddWithPlusAssignIntention/before.kt.template @@ -0,0 +1,4 @@ +fun foo() { + val a = arrayListOf(1, 2, 3) + a.add(4) +} \ No newline at end of file diff --git a/idea/resources/intentionDescriptions/ReplaceAddWithPlusAssignIntention/description.html b/idea/resources/intentionDescriptions/ReplaceAddWithPlusAssignIntention/description.html new file mode 100644 index 00000000000..43d79f84d91 --- /dev/null +++ b/idea/resources/intentionDescriptions/ReplaceAddWithPlusAssignIntention/description.html @@ -0,0 +1,5 @@ + + +This intention replaces add() and addAll() calls in mutable collection with += + + \ No newline at end of file diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index 204cf4e45f6..63fbccb30d4 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -1603,6 +1603,11 @@ Kotlin + + org.jetbrains.kotlin.idea.intentions.ReplaceAddWithPlusAssignIntention + Kotlin + + (KtDotQualifiedExpression::class.java, "Replace with '+='") { + override fun isApplicableTo(element: KtDotQualifiedExpression): Boolean { + if (element.callExpression?.valueArguments?.size != 1) return false + + when (element.calleeName) { + "add" -> text = "Replace 'add()' with '+='" + "addAll" -> text = "Replace 'addAll()' with '+='" + else -> return false + } + + val context = element.analyze(BodyResolveMode.PARTIAL) + BindingContextUtils.extractVariableDescriptorFromReference(context, element.receiverExpression)?.let { + if (it.isVar) return false + } ?: return false + + val resolvedCall = element.getResolvedCall(context) ?: return false + val receiverClass = DescriptorUtils.getClassDescriptorForType(resolvedCall.getExplicitReceiverValue()?.type ?: return false) + return receiverClass.isSubclassOf(DefaultBuiltIns.Instance.mutableCollection) + } + + override fun applyTo(element: KtDotQualifiedExpression, editor: Editor?) { + element.replace(KtPsiFactory(element).createExpressionByPattern("$0 += $1", element.receiverExpression, + element.callExpression?.valueArguments?.get(0)?.getArgumentExpression() ?: return)) + } +} \ No newline at end of file diff --git a/idea/testData/intentions/replaceAddWithPlusAssign/.intention b/idea/testData/intentions/replaceAddWithPlusAssign/.intention new file mode 100644 index 00000000000..d755e190790 --- /dev/null +++ b/idea/testData/intentions/replaceAddWithPlusAssign/.intention @@ -0,0 +1 @@ +org.jetbrains.kotlin.idea.intentions.ReplaceAddWithPlusAssignIntention \ No newline at end of file diff --git a/idea/testData/intentions/replaceAddWithPlusAssign/add.kt b/idea/testData/intentions/replaceAddWithPlusAssign/add.kt new file mode 100644 index 00000000000..53a0357ad04 --- /dev/null +++ b/idea/testData/intentions/replaceAddWithPlusAssign/add.kt @@ -0,0 +1,6 @@ +// WITH_RUNTIME +// INTENTION_TEXT: Replace 'add()' with '+=' +fun foo() { + val a = arrayListOf(1, 2, 3) + a.add(4) +} diff --git a/idea/testData/intentions/replaceAddWithPlusAssign/add.kt.after b/idea/testData/intentions/replaceAddWithPlusAssign/add.kt.after new file mode 100644 index 00000000000..caef267e1d8 --- /dev/null +++ b/idea/testData/intentions/replaceAddWithPlusAssign/add.kt.after @@ -0,0 +1,6 @@ +// WITH_RUNTIME +// INTENTION_TEXT: Replace 'add()' with '+=' +fun foo() { + val a = arrayListOf(1, 2, 3) + a += 4 +} diff --git a/idea/testData/intentions/replaceAddWithPlusAssign/addAll.kt b/idea/testData/intentions/replaceAddWithPlusAssign/addAll.kt new file mode 100644 index 00000000000..154f4dffcda --- /dev/null +++ b/idea/testData/intentions/replaceAddWithPlusAssign/addAll.kt @@ -0,0 +1,6 @@ +// WITH_RUNTIME +// INTENTION_TEXT: Replace 'addAll()' with '+=' +fun foo() { + val a = arrayListOf(1, 2, 3) + a.addAll(arrayOf(4, 5, 6)) +} diff --git a/idea/testData/intentions/replaceAddWithPlusAssign/addAll.kt.after b/idea/testData/intentions/replaceAddWithPlusAssign/addAll.kt.after new file mode 100644 index 00000000000..139654026be --- /dev/null +++ b/idea/testData/intentions/replaceAddWithPlusAssign/addAll.kt.after @@ -0,0 +1,6 @@ +// WITH_RUNTIME +// INTENTION_TEXT: Replace 'addAll()' with '+=' +fun foo() { + val a = arrayListOf(1, 2, 3) + a += arrayOf(4, 5, 6) +} diff --git a/idea/testData/intentions/replaceAddWithPlusAssign/addAllAtIndex.kt b/idea/testData/intentions/replaceAddWithPlusAssign/addAllAtIndex.kt new file mode 100644 index 00000000000..b78f80913bc --- /dev/null +++ b/idea/testData/intentions/replaceAddWithPlusAssign/addAllAtIndex.kt @@ -0,0 +1,7 @@ +// IS_APPLICABLE: false +// WITH_RUNTIME + +fun foo() { + val a = arrayListOf(1, 2, 3) + a.addAll(1, arrayListOf(4)) +} diff --git a/idea/testData/intentions/replaceAddWithPlusAssign/addAllToVar.kt b/idea/testData/intentions/replaceAddWithPlusAssign/addAllToVar.kt new file mode 100644 index 00000000000..18b489f7b53 --- /dev/null +++ b/idea/testData/intentions/replaceAddWithPlusAssign/addAllToVar.kt @@ -0,0 +1,7 @@ +// IS_APPLICABLE: false +// WITH_RUNTIME + +fun foo() { + var a = arrayListOf(1, 2, 3) + a.addAll(arrayListOf(4)) +} diff --git a/idea/testData/intentions/replaceAddWithPlusAssign/addAtIndex.kt b/idea/testData/intentions/replaceAddWithPlusAssign/addAtIndex.kt new file mode 100644 index 00000000000..4f224a5de02 --- /dev/null +++ b/idea/testData/intentions/replaceAddWithPlusAssign/addAtIndex.kt @@ -0,0 +1,7 @@ +// IS_APPLICABLE: false +// WITH_RUNTIME + +fun foo() { + val a = arrayListOf(1, 2, 3) + a.add(1, 4) +} diff --git a/idea/testData/intentions/replaceAddWithPlusAssign/addToVar.kt b/idea/testData/intentions/replaceAddWithPlusAssign/addToVar.kt new file mode 100644 index 00000000000..66ddabdc8f7 --- /dev/null +++ b/idea/testData/intentions/replaceAddWithPlusAssign/addToVar.kt @@ -0,0 +1,7 @@ +// IS_APPLICABLE: false +// WITH_RUNTIME + +fun foo() { + var a = arrayListOf(1, 2, 3) + a.add(4) +} diff --git a/idea/testData/intentions/replaceAddWithPlusAssign/nonCollection.kt b/idea/testData/intentions/replaceAddWithPlusAssign/nonCollection.kt new file mode 100644 index 00000000000..0636bac0d75 --- /dev/null +++ b/idea/testData/intentions/replaceAddWithPlusAssign/nonCollection.kt @@ -0,0 +1,10 @@ +// IS_APPLICABLE: false + +class A { + fun add(x: Int) { + } +} + +fun foo() { + A().add(1) +} \ 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 5912b9408ef..18880df5790 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java @@ -13524,6 +13524,57 @@ public class IntentionTestGenerated extends AbstractIntentionTest { } } + @TestMetadata("idea/testData/intentions/replaceAddWithPlusAssign") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class ReplaceAddWithPlusAssign extends AbstractIntentionTest { + @TestMetadata("add.kt") + public void testAdd() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/replaceAddWithPlusAssign/add.kt"); + doTest(fileName); + } + + @TestMetadata("addAll.kt") + public void testAddAll() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/replaceAddWithPlusAssign/addAll.kt"); + doTest(fileName); + } + + @TestMetadata("addAllAtIndex.kt") + public void testAddAllAtIndex() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/replaceAddWithPlusAssign/addAllAtIndex.kt"); + doTest(fileName); + } + + @TestMetadata("addAllToVar.kt") + public void testAddAllToVar() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/replaceAddWithPlusAssign/addAllToVar.kt"); + doTest(fileName); + } + + @TestMetadata("addAtIndex.kt") + public void testAddAtIndex() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/replaceAddWithPlusAssign/addAtIndex.kt"); + doTest(fileName); + } + + @TestMetadata("addToVar.kt") + public void testAddToVar() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/replaceAddWithPlusAssign/addToVar.kt"); + doTest(fileName); + } + + public void testAllFilesPresentInReplaceAddWithPlusAssign() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/intentions/replaceAddWithPlusAssign"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("nonCollection.kt") + public void testNonCollection() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/replaceAddWithPlusAssign/nonCollection.kt"); + doTest(fileName); + } + } + @TestMetadata("idea/testData/intentions/replaceArrayEqualityOpWithArraysEquals") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class)