diff --git a/idea/resources/inspectionDescriptions/OldStdlibApi.html b/idea/resources/inspectionDescriptions/OldStdlibApi.html
new file mode 100644
index 00000000000..6ad0f3fba94
--- /dev/null
+++ b/idea/resources/inspectionDescriptions/OldStdlibApi.html
@@ -0,0 +1,5 @@
+
+
+This inspection located pre-1.0 usages of the Kotlin standard library APIs from Java code and replaces them with up-to-date APIs.
+
+
diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml
index 55e1e8b9716..8df3e7acd13 100644
--- a/idea/src/META-INF/plugin.xml
+++ b/idea/src/META-INF/plugin.xml
@@ -1301,6 +1301,13 @@
enabledByDefault="true"
level="WARNING"/>
+
+
diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/OldStdlibApiInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/OldStdlibApiInspection.kt
new file mode 100644
index 00000000000..cdff160a6ad
--- /dev/null
+++ b/idea/src/org/jetbrains/kotlin/idea/inspections/OldStdlibApiInspection.kt
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2010-2015 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jetbrains.kotlin.idea.inspections
+
+import com.intellij.codeInspection.*
+import com.intellij.openapi.module.ModuleUtil
+import com.intellij.openapi.project.Project
+import com.intellij.psi.*
+import com.intellij.psi.codeStyle.JavaCodeStyleManager
+import com.intellij.psi.search.GlobalSearchScope
+import org.jetbrains.kotlin.idea.KotlinLanguage
+import org.jetbrains.kotlin.idea.search.allScope
+import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
+
+class OldStdlibApiInspection : AbstractKotlinInspection(), CleanupLocalInspectionTool {
+ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession): PsiElementVisitor {
+ return object : PsiElementVisitor() {
+ override fun visitElement(element: PsiElement) {
+ if (element.language == KotlinLanguage.INSTANCE) return
+ val importStatement = element.getParentOfType(false)
+ if (importStatement != null) return
+
+ for (reference in element.references) {
+ checkReference(reference)?.let {
+ holder.registerProblem(element, "Usage of the Kotlin standard library through a deprecated qualified name",
+ ProblemHighlightType.LIKE_DEPRECATED, it)
+
+ }
+ }
+ }
+ }
+ }
+
+ private fun checkReference(reference: PsiReference): LocalQuickFix? {
+ val resolveResult = reference.resolve()
+ if (resolveResult is PsiClass) {
+ val fqName = resolveResult.qualifiedName
+ val newFqName = StdlibMigrationMap.classMap[fqName]
+ if (newFqName != null) {
+ return OldStdlibApiFix { project, scope ->
+ JavaPsiFacade.getInstance(project).findClass(newFqName, scope)
+ }
+ }
+ }
+ else if (resolveResult is PsiMethod) {
+ val containingClass = resolveResult.containingClass ?: return null
+ val fqName = MethodFQName(containingClass.qualifiedName ?: return null, resolveResult.name)
+ val newFqName = StdlibMigrationMap.methodMap[fqName]
+ if (newFqName != null) {
+ return OldStdlibApiFix { project, scope ->
+ JavaPsiFacade.getInstance(project).findClass(newFqName.className, scope)
+ ?.findMethodsByName(newFqName.methodName, false)
+ ?.singleOrNull()
+ }
+ }
+ }
+ return null
+ }
+}
+
+public class OldStdlibApiFix(val newElementCallback: (Project, GlobalSearchScope) -> PsiElement?) : LocalQuickFix {
+ override fun getName(): String = "Replace with new qualified name"
+ override fun getFamilyName(): String = name
+
+ override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
+ val element = descriptor.psiElement
+ val reference = element.reference ?: return
+ val module = ModuleUtil.findModuleForPsiElement(element)
+ val scope = module?.moduleWithLibrariesScope ?: project.allScope()
+
+ val newElement = newElementCallback(project, scope) ?: return
+ val newReference = reference.bindToElement(newElement)
+
+ val javaFile = newReference.containingFile as? PsiJavaFile
+ if (javaFile != null) {
+ JavaCodeStyleManager.getInstance(project).removeRedundantImports(javaFile)
+ }
+
+ JavaCodeStyleManager.getInstance(project).shortenClassReferences(newReference)
+ }
+}
diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/StdlibMigrationMap.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/StdlibMigrationMap.kt
new file mode 100644
index 00000000000..18da5683134
--- /dev/null
+++ b/idea/src/org/jetbrains/kotlin/idea/inspections/StdlibMigrationMap.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2010-2015 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jetbrains.kotlin.idea.inspections
+
+data class MethodFQName(val className: String, val methodName: String)
+
+object StdlibMigrationMap {
+ val methodMap = hashMapOf(
+ MethodFQName("kotlin.jvm.ClassMapping", "getKotlin") to MethodFQName("kotlin.jvm.JvmClassMappingKt", "getKotlinClass"),
+ MethodFQName("kotlin.jvm.ClassMapping", "getJava") to MethodFQName("kotlin.jvm.JvmClassMappingKt", "getJavaClass")
+ )
+
+ val classMap = hashMapOf(
+ "kotlin.ArraysKt" to "kotlin.collections.ArraysKt",
+ "kotlin.CharsKt" to "kotlin.text.CharsKt",
+ "kotlin.CollectionsKt" to "kotlin.collections.CollectionsKt",
+ "kotlin.MapsKt" to "kotlin.collections.MapsKt",
+ "kotlin.RangesKt" to "kotlin.ranges.RangesKt",
+ "kotlin.SequencesKt" to "kotlin.sequences.SequencesKt",
+ "kotlin.SetsKt" to "kotlin.collections.SetsKt",
+ "kotlin.StringsKt" to "kotlin.text.StringsKt",
+ "kotlin.support.AbstractIterator" to "kotlin.collections.AbstractIterator"
+ )
+}
diff --git a/idea/testData/quickfix/migration/stdlib/.inspection b/idea/testData/quickfix/migration/stdlib/.inspection
new file mode 100644
index 00000000000..b4534997f49
--- /dev/null
+++ b/idea/testData/quickfix/migration/stdlib/.inspection
@@ -0,0 +1 @@
+org.jetbrains.kotlin.idea.inspections.OldStdlibApiInspection
\ No newline at end of file
diff --git a/idea/testData/quickfix/migration/stdlib/basic.after.java b/idea/testData/quickfix/migration/stdlib/basic.after.java
new file mode 100644
index 00000000000..b27da5cee60
--- /dev/null
+++ b/idea/testData/quickfix/migration/stdlib/basic.after.java
@@ -0,0 +1,10 @@
+// "Replace with new qualified name" "true"
+// WITH_RUNTIME
+
+import kotlin.collections.ArraysKt;
+
+class C {
+ public void foo(byte[] bytes) {
+ ArraysKt.component1(bytes);
+ }
+}
\ No newline at end of file
diff --git a/idea/testData/quickfix/migration/stdlib/basic.before.Main.java b/idea/testData/quickfix/migration/stdlib/basic.before.Main.java
new file mode 100644
index 00000000000..4191a1c4e45
--- /dev/null
+++ b/idea/testData/quickfix/migration/stdlib/basic.before.Main.java
@@ -0,0 +1,10 @@
+// "Replace with new qualified name" "true"
+// WITH_RUNTIME
+
+import kotlin.ArraysKt;
+
+class C {
+ public void foo(byte[] bytes) {
+ ArraysKt.component1(bytes);
+ }
+}
\ No newline at end of file
diff --git a/idea/testData/quickfix/migration/stdlib/importStatic.after.java b/idea/testData/quickfix/migration/stdlib/importStatic.after.java
new file mode 100644
index 00000000000..cc134c14b3b
--- /dev/null
+++ b/idea/testData/quickfix/migration/stdlib/importStatic.after.java
@@ -0,0 +1,10 @@
+// "Replace with new qualified name" "true"
+// WITH_RUNTIME
+
+import static kotlin.collections.ArraysKt.component1;
+
+class C {
+ public void foo(byte[] bytes) {
+ component1(bytes);
+ }
+}
\ No newline at end of file
diff --git a/idea/testData/quickfix/migration/stdlib/importStatic.before.Main.java b/idea/testData/quickfix/migration/stdlib/importStatic.before.Main.java
new file mode 100644
index 00000000000..5162e175ba6
--- /dev/null
+++ b/idea/testData/quickfix/migration/stdlib/importStatic.before.Main.java
@@ -0,0 +1,10 @@
+// "Replace with new qualified name" "true"
+// WITH_RUNTIME
+
+import static kotlin.ArraysKt.component1;
+
+class C {
+ public void foo(byte[] bytes) {
+ component1(bytes);
+ }
+}
\ No newline at end of file
diff --git a/idea/testData/quickfix/migration/stdlib/method.after.java b/idea/testData/quickfix/migration/stdlib/method.after.java
new file mode 100644
index 00000000000..cbe2298b0e4
--- /dev/null
+++ b/idea/testData/quickfix/migration/stdlib/method.after.java
@@ -0,0 +1,10 @@
+// "Replace with new qualified name" "true"
+// WITH_RUNTIME
+
+import kotlin.jvm.JvmClassMappingKt;
+
+class C {
+ public void foo(Class cls) {
+ JvmClassMappingKt.getKotlinClass(cls);
+ }
+}
\ No newline at end of file
diff --git a/idea/testData/quickfix/migration/stdlib/method.before.Main.java b/idea/testData/quickfix/migration/stdlib/method.before.Main.java
new file mode 100644
index 00000000000..566e1d2490b
--- /dev/null
+++ b/idea/testData/quickfix/migration/stdlib/method.before.Main.java
@@ -0,0 +1,10 @@
+// "Replace with new qualified name" "true"
+// WITH_RUNTIME
+
+import kotlin.jvm.ClassMapping;
+
+class C {
+ public void foo(Class cls) {
+ ClassMapping.getKotlin(cls);
+ }
+}
\ 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 a2b2625c5c4..9d465b30a81 100644
--- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java
+++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java
@@ -1387,6 +1387,33 @@ public class QuickFixMultiFileTestGenerated extends AbstractQuickFixMultiFileTes
}
}
+ @TestMetadata("idea/testData/quickfix/migration/stdlib")
+ @TestDataPath("$PROJECT_ROOT")
+ @RunWith(JUnit3RunnerWithInners.class)
+ public static class Stdlib extends AbstractQuickFixMultiFileTest {
+ public void testAllFilesPresentInStdlib() throws Exception {
+ KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/migration/stdlib"), Pattern.compile("^(\\w+)\\.((before\\.Main\\.\\w+)|(test))$"), true);
+ }
+
+ @TestMetadata("basic.before.Main.java")
+ public void testBasic() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/migration/stdlib/basic.before.Main.java");
+ doTestWithExtraFile(fileName);
+ }
+
+ @TestMetadata("importStatic.before.Main.java")
+ public void testImportStatic() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/migration/stdlib/importStatic.before.Main.java");
+ doTestWithExtraFile(fileName);
+ }
+
+ @TestMetadata("method.before.Main.java")
+ public void testMethod() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/migration/stdlib/method.before.Main.java");
+ doTestWithExtraFile(fileName);
+ }
+ }
+
}
@TestMetadata("idea/testData/quickfix/modifiers")