diff --git a/idea/resources/META-INF/plugin-common.xml b/idea/resources/META-INF/plugin-common.xml index 358a1f4d37d..7ccb4fc5660 100644 --- a/idea/resources/META-INF/plugin-common.xml +++ b/idea/resources/META-INF/plugin-common.xml @@ -1747,6 +1747,11 @@ Kotlin + + org.jetbrains.kotlin.idea.intentions.ConvertCollectionConstructorToFunction + Kotlin + + arrayListOf() diff --git a/idea/resources/intentionDescriptions/ConvertCollectionConstructorToFunction/before.kt.template b/idea/resources/intentionDescriptions/ConvertCollectionConstructorToFunction/before.kt.template new file mode 100644 index 00000000000..298caa9775d --- /dev/null +++ b/idea/resources/intentionDescriptions/ConvertCollectionConstructorToFunction/before.kt.template @@ -0,0 +1,3 @@ +class Person(val name: String) + +val persons = ArrayList() diff --git a/idea/resources/intentionDescriptions/ConvertCollectionConstructorToFunction/description.html b/idea/resources/intentionDescriptions/ConvertCollectionConstructorToFunction/description.html new file mode 100644 index 00000000000..4c243e02c77 --- /dev/null +++ b/idea/resources/intentionDescriptions/ConvertCollectionConstructorToFunction/description.html @@ -0,0 +1,5 @@ + + +This intention reports explicit calls of Collection constructor calls which can be replaced by function calls from the stdlib. + + diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertCollectionConstructorToFunction.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertCollectionConstructorToFunction.kt new file mode 100644 index 00000000000..ac234352f46 --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertCollectionConstructorToFunction.kt @@ -0,0 +1,42 @@ +/* + * 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 org.jetbrains.kotlin.idea.caches.resolve.resolveToCall +import org.jetbrains.kotlin.psi.KtCallExpression +import org.jetbrains.kotlin.psi.KtPsiFactory +import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe + +class ConvertCollectionConstructorToFunction : SelfTargetingIntention( + KtCallExpression::class.java, "Convert Collection constructor to function" +) { + + private val functionMap = hashMapOf( + "java.util.ArrayList." to "arrayListOf", + "kotlin.collections.ArrayList." to "arrayListOf", + "java.util.HashMap." to "hashMapOf", + "kotlin.collections.HashMap." to "arrayListOf", + "java.util.HashSet." to "hashSetOf", + "kotlin.collections.HashSet." to "arrayListOf", + "java.util.LinkedHashMap." to "linkedMapOf", + "kotlin.collections.LinkedHashMap." to "arrayListOf", + "java.util.LinkedHashSet." to "linkedSetOf", + "kotlin.collections.LinkedHashSet." to "arrayListOf" + ) + + override fun isApplicableTo(element: KtCallExpression, caretOffset: Int): Boolean { + val fq = element.resolveToCall()?.resultingDescriptor?.fqNameSafe?.asString() ?: return false + return functionMap.containsKey(fq) && element.valueArguments.size == 0 + } + + override fun applyTo(element: KtCallExpression, editor: Editor?) { + val fq = element.resolveToCall()?.resultingDescriptor?.fqNameSafe?.asString() ?: return + val toCall = functionMap[fq] ?: return + val convertedCall = KtPsiFactory(element).createIdentifier(toCall) + element.calleeExpression?.replace(convertedCall) + } +} diff --git a/idea/testData/intentions/convertCollectionConstructorToFunction/.intention b/idea/testData/intentions/convertCollectionConstructorToFunction/.intention new file mode 100644 index 00000000000..edbd09be884 --- /dev/null +++ b/idea/testData/intentions/convertCollectionConstructorToFunction/.intention @@ -0,0 +1 @@ +org.jetbrains.kotlin.idea.intentions.ConvertCollectionConstructorToFunction diff --git a/idea/testData/intentions/convertCollectionConstructorToFunction/keepArrayListCallWithArgument.kt b/idea/testData/intentions/convertCollectionConstructorToFunction/keepArrayListCallWithArgument.kt new file mode 100644 index 00000000000..8fd1e6419f0 --- /dev/null +++ b/idea/testData/intentions/convertCollectionConstructorToFunction/keepArrayListCallWithArgument.kt @@ -0,0 +1,5 @@ +// WITH_RUNTIME +// IS_APPLICABLE: false +fun foo() { + var list: ArrayList = ArrayList(3) +} \ No newline at end of file diff --git a/idea/testData/intentions/convertCollectionConstructorToFunction/replaceArrayListCall.kt b/idea/testData/intentions/convertCollectionConstructorToFunction/replaceArrayListCall.kt new file mode 100644 index 00000000000..5753eb9fa25 --- /dev/null +++ b/idea/testData/intentions/convertCollectionConstructorToFunction/replaceArrayListCall.kt @@ -0,0 +1,4 @@ +// WITH_RUNTIME +fun foo() { + var list: ArrayList = ArrayList() +} \ No newline at end of file diff --git a/idea/testData/intentions/convertCollectionConstructorToFunction/replaceArrayListCall.kt.after b/idea/testData/intentions/convertCollectionConstructorToFunction/replaceArrayListCall.kt.after new file mode 100644 index 00000000000..2fa5b0e5011 --- /dev/null +++ b/idea/testData/intentions/convertCollectionConstructorToFunction/replaceArrayListCall.kt.after @@ -0,0 +1,4 @@ +// WITH_RUNTIME +fun foo() { + var list: ArrayList = arrayListOf() +} \ No newline at end of file diff --git a/idea/testData/intentions/convertCollectionConstructorToFunction/replaceArrayListCallWithType.kt b/idea/testData/intentions/convertCollectionConstructorToFunction/replaceArrayListCallWithType.kt new file mode 100644 index 00000000000..da1f2c7437f --- /dev/null +++ b/idea/testData/intentions/convertCollectionConstructorToFunction/replaceArrayListCallWithType.kt @@ -0,0 +1,4 @@ +// WITH_RUNTIME +fun foo() { + var list = ArrayList() +} \ No newline at end of file diff --git a/idea/testData/intentions/convertCollectionConstructorToFunction/replaceArrayListCallWithType.kt.after b/idea/testData/intentions/convertCollectionConstructorToFunction/replaceArrayListCallWithType.kt.after new file mode 100644 index 00000000000..cc13ecf133c --- /dev/null +++ b/idea/testData/intentions/convertCollectionConstructorToFunction/replaceArrayListCallWithType.kt.after @@ -0,0 +1,4 @@ +// WITH_RUNTIME +fun foo() { + var list = arrayListOf() +} \ No newline at end of file diff --git a/idea/testData/intentions/convertCollectionConstructorToFunction/replaceHashMapCall.kt b/idea/testData/intentions/convertCollectionConstructorToFunction/replaceHashMapCall.kt new file mode 100644 index 00000000000..756ac60cd53 --- /dev/null +++ b/idea/testData/intentions/convertCollectionConstructorToFunction/replaceHashMapCall.kt @@ -0,0 +1,6 @@ +// WITH_RUNTIME +import java.util.HashMap + +fun foo() { + var list: HashMap = HashMap() +} \ No newline at end of file diff --git a/idea/testData/intentions/convertCollectionConstructorToFunction/replaceHashMapCall.kt.after b/idea/testData/intentions/convertCollectionConstructorToFunction/replaceHashMapCall.kt.after new file mode 100644 index 00000000000..d16bad80874 --- /dev/null +++ b/idea/testData/intentions/convertCollectionConstructorToFunction/replaceHashMapCall.kt.after @@ -0,0 +1,6 @@ +// WITH_RUNTIME +import java.util.HashMap + +fun foo() { + var list: HashMap = hashMapOf() +} \ No newline at end of file diff --git a/idea/testData/intentions/convertCollectionConstructorToFunction/replaceHashSetCall.kt b/idea/testData/intentions/convertCollectionConstructorToFunction/replaceHashSetCall.kt new file mode 100644 index 00000000000..3ea8fdb3374 --- /dev/null +++ b/idea/testData/intentions/convertCollectionConstructorToFunction/replaceHashSetCall.kt @@ -0,0 +1,6 @@ +// WITH_RUNTIME +import java.util.HashSet + +fun foo() { + var list: HashSet = HashSet() +} \ No newline at end of file diff --git a/idea/testData/intentions/convertCollectionConstructorToFunction/replaceHashSetCall.kt.after b/idea/testData/intentions/convertCollectionConstructorToFunction/replaceHashSetCall.kt.after new file mode 100644 index 00000000000..0e71f678c3d --- /dev/null +++ b/idea/testData/intentions/convertCollectionConstructorToFunction/replaceHashSetCall.kt.after @@ -0,0 +1,6 @@ +// WITH_RUNTIME +import java.util.HashSet + +fun foo() { + var list: HashSet = hashSetOf() +} \ No newline at end of file diff --git a/idea/testData/intentions/convertCollectionConstructorToFunction/replaceLinkedHashSetCall.kt b/idea/testData/intentions/convertCollectionConstructorToFunction/replaceLinkedHashSetCall.kt new file mode 100644 index 00000000000..43125d7a480 --- /dev/null +++ b/idea/testData/intentions/convertCollectionConstructorToFunction/replaceLinkedHashSetCall.kt @@ -0,0 +1,7 @@ +// WITH_RUNTIME + +import java.util.LinkedHashSet + +fun foo() { + var list: LinkedHashSet = LinkedHashSet() +} \ No newline at end of file diff --git a/idea/testData/intentions/convertCollectionConstructorToFunction/replaceLinkedHashSetCall.kt.after b/idea/testData/intentions/convertCollectionConstructorToFunction/replaceLinkedHashSetCall.kt.after new file mode 100644 index 00000000000..641bbb5a0d0 --- /dev/null +++ b/idea/testData/intentions/convertCollectionConstructorToFunction/replaceLinkedHashSetCall.kt.after @@ -0,0 +1,7 @@ +// WITH_RUNTIME + +import java.util.LinkedHashSet + +fun foo() { + var list: LinkedHashSet = linkedSetOf() +} \ 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 b564e84fa8a..2682eaab29f 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java @@ -4913,6 +4913,49 @@ public class IntentionTestGenerated extends AbstractIntentionTest { } } + @TestMetadata("idea/testData/intentions/convertCollectionConstructorToFunction") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class ConvertCollectionConstructorToFunction extends AbstractIntentionTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath); + } + + public void testAllFilesPresentInConvertCollectionConstructorToFunction() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/intentions/convertCollectionConstructorToFunction"), Pattern.compile("^([\\w\\-_]+)\\.(kt|kts)$"), TargetBackend.ANY, true); + } + + @TestMetadata("keepArrayListCallWithArgument.kt") + public void testKeepArrayListCallWithArgument() throws Exception { + runTest("idea/testData/intentions/convertCollectionConstructorToFunction/keepArrayListCallWithArgument.kt"); + } + + @TestMetadata("replaceArrayListCall.kt") + public void testReplaceArrayListCall() throws Exception { + runTest("idea/testData/intentions/convertCollectionConstructorToFunction/replaceArrayListCall.kt"); + } + + @TestMetadata("replaceArrayListCallWithType.kt") + public void testReplaceArrayListCallWithType() throws Exception { + runTest("idea/testData/intentions/convertCollectionConstructorToFunction/replaceArrayListCallWithType.kt"); + } + + @TestMetadata("replaceHashMapCall.kt") + public void testReplaceHashMapCall() throws Exception { + runTest("idea/testData/intentions/convertCollectionConstructorToFunction/replaceHashMapCall.kt"); + } + + @TestMetadata("replaceHashSetCall.kt") + public void testReplaceHashSetCall() throws Exception { + runTest("idea/testData/intentions/convertCollectionConstructorToFunction/replaceHashSetCall.kt"); + } + + @TestMetadata("replaceLinkedHashSetCall.kt") + public void testReplaceLinkedHashSetCall() throws Exception { + runTest("idea/testData/intentions/convertCollectionConstructorToFunction/replaceLinkedHashSetCall.kt"); + } + } + @TestMetadata("idea/testData/intentions/convertEnumToSealedClass") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class)