diff --git a/idea/resources/inspectionDescriptions/JavaCollectionsStaticMethod.html b/idea/resources/inspectionDescriptions/JavaCollectionsStaticMethod.html
new file mode 100644
index 00000000000..ed39c8fac5d
--- /dev/null
+++ b/idea/resources/inspectionDescriptions/JavaCollectionsStaticMethod.html
@@ -0,0 +1,5 @@
+
+
+This inspection reports Java Collections static method call replaceable by Kotlin stdlib, e.g. Collections.sort(list).
+
+
diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml
index 9051626d0eb..ab9a6c75de3 100644
--- a/idea/src/META-INF/plugin.xml
+++ b/idea/src/META-INF/plugin.xml
@@ -2673,6 +2673,14 @@
language="kotlin"
/>
+
): Boolean {
+ if (!fqName.startsWith("java.util.Collections.")) return false
+ val size = args.size
+ return when (fqName) {
+ "java.util.Collections.fill" -> checkApiVersion(ApiVersion.KOTLIN_1_2, expression) && size == 2
+ "java.util.Collections.reverse" -> size == 1
+ "java.util.Collections.shuffle" -> checkApiVersion(ApiVersion.KOTLIN_1_2, expression) && (size == 1 || size == 2)
+ "java.util.Collections.sort" -> {
+ size == 1 || (size == 2 && args.getOrNull(1)?.getArgumentExpression() is KtLambdaExpression)
+ }
+ else -> false
+ }
+ }
+
+ private fun checkApiVersion(requiredVersion: ApiVersion, expression: KtDotQualifiedExpression): Boolean {
+ val module = ModuleUtilCore.findModuleForPsiElement(expression) ?: return true
+ return module.languageVersionSettings.apiVersion >= requiredVersion
+ }
+
+}
+
+private class ReplaceWithStdLibFix(private val methodName: String, private val receiver: String) : LocalQuickFix {
+ override fun getName() = "Replace with $receiver.$methodName"
+
+ override fun getFamilyName() = name
+
+ override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
+ val expression = descriptor.psiElement as? KtDotQualifiedExpression ?: return
+ val callExpression = expression.callExpression ?: return
+ val valueArguments = callExpression.valueArguments
+ val firstArg = valueArguments.getOrNull(0)?.getArgumentExpression() ?: return
+ val secondArg = valueArguments.getOrNull(1)?.getArgumentExpression()
+ val factory = KtPsiFactory(project)
+ val newExpression = if (secondArg != null) {
+ if (methodName == "sort")
+ factory.createExpressionByPattern("$0.sortWith(Comparator $1)", firstArg, secondArg.text)
+ else
+ factory.createExpressionByPattern("$0.$methodName($1)", firstArg, secondArg)
+ }
+ else
+ factory.createExpressionByPattern("$0.$methodName()", firstArg)
+ expression.replace(newExpression)
+ }
+}
diff --git a/idea/testData/inspectionsLocal/javaCollectionsStaticMethod/.inspection b/idea/testData/inspectionsLocal/javaCollectionsStaticMethod/.inspection
new file mode 100644
index 00000000000..04352475766
--- /dev/null
+++ b/idea/testData/inspectionsLocal/javaCollectionsStaticMethod/.inspection
@@ -0,0 +1 @@
+org.jetbrains.kotlin.idea.inspections.JavaCollectionsStaticMethodInspection
diff --git a/idea/testData/inspectionsLocal/javaCollectionsStaticMethod/fill.kt b/idea/testData/inspectionsLocal/javaCollectionsStaticMethod/fill.kt
new file mode 100644
index 00000000000..3a3d6434754
--- /dev/null
+++ b/idea/testData/inspectionsLocal/javaCollectionsStaticMethod/fill.kt
@@ -0,0 +1,7 @@
+// RUNTIME_WITH_FULL_JDK
+import java.util.Collections
+
+fun test() {
+ val mutableList = mutableListOf(1, 2)
+ Collections.fill(mutableList, 3)
+}
diff --git a/idea/testData/inspectionsLocal/javaCollectionsStaticMethod/fill.kt.after b/idea/testData/inspectionsLocal/javaCollectionsStaticMethod/fill.kt.after
new file mode 100644
index 00000000000..a9d633b316e
--- /dev/null
+++ b/idea/testData/inspectionsLocal/javaCollectionsStaticMethod/fill.kt.after
@@ -0,0 +1,7 @@
+// RUNTIME_WITH_FULL_JDK
+import java.util.Collections
+
+fun test() {
+ val mutableList = mutableListOf(1, 2)
+ mutableList.fill(3)
+}
diff --git a/idea/testData/inspectionsLocal/javaCollectionsStaticMethod/reverse.kt b/idea/testData/inspectionsLocal/javaCollectionsStaticMethod/reverse.kt
new file mode 100644
index 00000000000..f8f62644c3b
--- /dev/null
+++ b/idea/testData/inspectionsLocal/javaCollectionsStaticMethod/reverse.kt
@@ -0,0 +1,7 @@
+// RUNTIME_WITH_FULL_JDK
+import java.util.Collections
+
+fun test() {
+ val mutableList = mutableListOf(1, 2)
+ Collections.reverse(mutableList)
+}
diff --git a/idea/testData/inspectionsLocal/javaCollectionsStaticMethod/reverse.kt.after b/idea/testData/inspectionsLocal/javaCollectionsStaticMethod/reverse.kt.after
new file mode 100644
index 00000000000..3ea363f97db
--- /dev/null
+++ b/idea/testData/inspectionsLocal/javaCollectionsStaticMethod/reverse.kt.after
@@ -0,0 +1,7 @@
+// RUNTIME_WITH_FULL_JDK
+import java.util.Collections
+
+fun test() {
+ val mutableList = mutableListOf(1, 2)
+ mutableList.reverse()
+}
diff --git a/idea/testData/inspectionsLocal/javaCollectionsStaticMethod/reverseImmutableList.kt b/idea/testData/inspectionsLocal/javaCollectionsStaticMethod/reverseImmutableList.kt
new file mode 100644
index 00000000000..11019b7179a
--- /dev/null
+++ b/idea/testData/inspectionsLocal/javaCollectionsStaticMethod/reverseImmutableList.kt
@@ -0,0 +1,8 @@
+// RUNTIME_WITH_FULL_JDK
+// PROBLEM: none
+import java.util.Collections
+
+fun test() {
+ val list = listOf(1, 2)
+ Collections.reverse(list)
+}
diff --git a/idea/testData/inspectionsLocal/javaCollectionsStaticMethod/shuffle.kt b/idea/testData/inspectionsLocal/javaCollectionsStaticMethod/shuffle.kt
new file mode 100644
index 00000000000..c723ed256c6
--- /dev/null
+++ b/idea/testData/inspectionsLocal/javaCollectionsStaticMethod/shuffle.kt
@@ -0,0 +1,7 @@
+// RUNTIME_WITH_FULL_JDK
+import java.util.Collections
+
+fun test() {
+ val mutableList = mutableListOf(1, 2)
+ Collections.shuffle(mutableList)
+}
diff --git a/idea/testData/inspectionsLocal/javaCollectionsStaticMethod/shuffle.kt.after b/idea/testData/inspectionsLocal/javaCollectionsStaticMethod/shuffle.kt.after
new file mode 100644
index 00000000000..7848f22f3f3
--- /dev/null
+++ b/idea/testData/inspectionsLocal/javaCollectionsStaticMethod/shuffle.kt.after
@@ -0,0 +1,7 @@
+// RUNTIME_WITH_FULL_JDK
+import java.util.Collections
+
+fun test() {
+ val mutableList = mutableListOf(1, 2)
+ mutableList.shuffle()
+}
diff --git a/idea/testData/inspectionsLocal/javaCollectionsStaticMethod/shuffleRandom.kt b/idea/testData/inspectionsLocal/javaCollectionsStaticMethod/shuffleRandom.kt
new file mode 100644
index 00000000000..7b376146af0
--- /dev/null
+++ b/idea/testData/inspectionsLocal/javaCollectionsStaticMethod/shuffleRandom.kt
@@ -0,0 +1,7 @@
+// RUNTIME_WITH_FULL_JDK
+import java.util.*
+
+fun test() {
+ val mutableList = mutableListOf(1, 2)
+ Collections.shuffle(mutableList, Random(1))
+}
diff --git a/idea/testData/inspectionsLocal/javaCollectionsStaticMethod/shuffleRandom.kt.after b/idea/testData/inspectionsLocal/javaCollectionsStaticMethod/shuffleRandom.kt.after
new file mode 100644
index 00000000000..dfc67cd5abe
--- /dev/null
+++ b/idea/testData/inspectionsLocal/javaCollectionsStaticMethod/shuffleRandom.kt.after
@@ -0,0 +1,7 @@
+// RUNTIME_WITH_FULL_JDK
+import java.util.*
+
+fun test() {
+ val mutableList = mutableListOf(1, 2)
+ mutableList.shuffle(Random(1))
+}
diff --git a/idea/testData/inspectionsLocal/javaCollectionsStaticMethod/sort.kt b/idea/testData/inspectionsLocal/javaCollectionsStaticMethod/sort.kt
new file mode 100644
index 00000000000..d3656e6c5a5
--- /dev/null
+++ b/idea/testData/inspectionsLocal/javaCollectionsStaticMethod/sort.kt
@@ -0,0 +1,7 @@
+// RUNTIME_WITH_FULL_JDK
+import java.util.Collections
+
+fun test() {
+ val mutableList = mutableListOf(1, 2)
+ Collections.sort(mutableList)
+}
diff --git a/idea/testData/inspectionsLocal/javaCollectionsStaticMethod/sort.kt.after b/idea/testData/inspectionsLocal/javaCollectionsStaticMethod/sort.kt.after
new file mode 100644
index 00000000000..c69a69b2eed
--- /dev/null
+++ b/idea/testData/inspectionsLocal/javaCollectionsStaticMethod/sort.kt.after
@@ -0,0 +1,7 @@
+// RUNTIME_WITH_FULL_JDK
+import java.util.Collections
+
+fun test() {
+ val mutableList = mutableListOf(1, 2)
+ mutableList.sort()
+}
diff --git a/idea/testData/inspectionsLocal/javaCollectionsStaticMethod/sortImmutableList.kt b/idea/testData/inspectionsLocal/javaCollectionsStaticMethod/sortImmutableList.kt
new file mode 100644
index 00000000000..b5722c3be20
--- /dev/null
+++ b/idea/testData/inspectionsLocal/javaCollectionsStaticMethod/sortImmutableList.kt
@@ -0,0 +1,8 @@
+// RUNTIME_WITH_FULL_JDK
+// PROBLEM: none
+import java.util.Collections
+
+fun test() {
+ val list = listOf(1, 2)
+ Collections.sort(list)
+}
diff --git a/idea/testData/inspectionsLocal/javaCollectionsStaticMethod/sortWith.kt b/idea/testData/inspectionsLocal/javaCollectionsStaticMethod/sortWith.kt
new file mode 100644
index 00000000000..835a0ea3cf1
--- /dev/null
+++ b/idea/testData/inspectionsLocal/javaCollectionsStaticMethod/sortWith.kt
@@ -0,0 +1,7 @@
+// RUNTIME_WITH_FULL_JDK
+import java.util.Collections
+
+fun test() {
+ val mutableList = mutableListOf(1, 2)
+ Collections.sort(mutableList, { a, b -> a.compareTo(b) })
+}
diff --git a/idea/testData/inspectionsLocal/javaCollectionsStaticMethod/sortWith.kt.after b/idea/testData/inspectionsLocal/javaCollectionsStaticMethod/sortWith.kt.after
new file mode 100644
index 00000000000..8fd0b727b88
--- /dev/null
+++ b/idea/testData/inspectionsLocal/javaCollectionsStaticMethod/sortWith.kt.after
@@ -0,0 +1,7 @@
+// RUNTIME_WITH_FULL_JDK
+import java.util.Collections
+
+fun test() {
+ val mutableList = mutableListOf(1, 2)
+ mutableList.sortWith(Comparator { a, b -> a.compareTo(b) })
+}
diff --git a/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java
index 532eb9f5737..764da6cc293 100644
--- a/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java
+++ b/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java
@@ -816,6 +816,63 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest {
}
}
+ @TestMetadata("idea/testData/inspectionsLocal/javaCollectionsStaticMethod")
+ @TestDataPath("$PROJECT_ROOT")
+ @RunWith(JUnit3RunnerWithInners.class)
+ public static class JavaCollectionsStaticMethod extends AbstractLocalInspectionTest {
+ public void testAllFilesPresentInJavaCollectionsStaticMethod() throws Exception {
+ KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/inspectionsLocal/javaCollectionsStaticMethod"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), TargetBackend.ANY, true);
+ }
+
+ @TestMetadata("fill.kt")
+ public void testFill() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/javaCollectionsStaticMethod/fill.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("reverse.kt")
+ public void testReverse() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/javaCollectionsStaticMethod/reverse.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("reverseImmutableList.kt")
+ public void testReverseImmutableList() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/javaCollectionsStaticMethod/reverseImmutableList.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("shuffle.kt")
+ public void testShuffle() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/javaCollectionsStaticMethod/shuffle.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("shuffleRandom.kt")
+ public void testShuffleRandom() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/javaCollectionsStaticMethod/shuffleRandom.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("sort.kt")
+ public void testSort() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/javaCollectionsStaticMethod/sort.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("sortImmutableList.kt")
+ public void testSortImmutableList() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/javaCollectionsStaticMethod/sortImmutableList.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("sortWith.kt")
+ public void testSortWith() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/javaCollectionsStaticMethod/sortWith.kt");
+ doTest(fileName);
+ }
+ }
+
@TestMetadata("idea/testData/inspectionsLocal/kdocMissingDocumentation")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)