diff --git a/idea/resources/inspectionDescriptions/ConvertPairConstructorToToFunction.html b/idea/resources/inspectionDescriptions/ConvertPairConstructorToToFunction.html
new file mode 100644
index 00000000000..6c3374f79e2
--- /dev/null
+++ b/idea/resources/inspectionDescriptions/ConvertPairConstructorToToFunction.html
@@ -0,0 +1,5 @@
+
+
+This inspection reports Pair constructor that can be converted to 'to' function.
+
+
diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml
index c629cdd6d6c..5779c94318e 100644
--- a/idea/src/META-INF/plugin.xml
+++ b/idea/src/META-INF/plugin.xml
@@ -2734,6 +2734,15 @@
language="kotlin"
/>
+
+
diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/ConvertPairConstructorToToFunctionInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/ConvertPairConstructorToToFunctionInspection.kt
new file mode 100644
index 00000000000..efac24a2091
--- /dev/null
+++ b/idea/src/org/jetbrains/kotlin/idea/inspections/ConvertPairConstructorToToFunctionInspection.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2000-2018 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.inspections
+
+import com.intellij.codeInspection.LocalQuickFix
+import com.intellij.codeInspection.ProblemDescriptor
+import com.intellij.codeInspection.ProblemHighlightType
+import com.intellij.codeInspection.ProblemsHolder
+import com.intellij.openapi.project.Project
+import com.intellij.psi.PsiElementVisitor
+import org.jetbrains.kotlin.idea.intentions.getCallableDescriptor
+import org.jetbrains.kotlin.name.FqName
+import org.jetbrains.kotlin.psi.KtCallExpression
+import org.jetbrains.kotlin.psi.KtPsiFactory
+import org.jetbrains.kotlin.psi.callExpressionVisitor
+import org.jetbrains.kotlin.psi.createExpressionByPattern
+import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
+
+class ConvertPairConstructorToToFunctionInspection : AbstractKotlinInspection() {
+ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
+ return callExpressionVisitor { expression ->
+ if (expression.isPairConstructorCall()) {
+ holder.registerProblem(
+ expression,
+ "Can be converted to 'to'",
+ ProblemHighlightType.INFORMATION,
+ ConvertPairConstructorToToFix()
+ )
+ }
+ }
+ }
+}
+
+private class ConvertPairConstructorToToFix : LocalQuickFix {
+ override fun getName() = "Convert to 'to'"
+
+ override fun getFamilyName() = name
+
+ override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
+ val expression = descriptor.psiElement as? KtCallExpression ?: return
+ val args = expression.valueArguments.mapNotNull { it.getArgumentExpression() }.toTypedArray()
+ expression.replace(KtPsiFactory(expression).createExpressionByPattern("$0 to $1", *args))
+ }
+}
+
+private fun KtCallExpression.isPairConstructorCall(): Boolean {
+ if (valueArguments.size != 2) return false
+ if (valueArguments.mapNotNull { it.getArgumentExpression() }.size != 2) return false
+ return getCallableDescriptor()?.containingDeclaration?.fqNameSafe == FqName("kotlin.Pair")
+}
diff --git a/idea/testData/inspectionsLocal/convertPairConstructorToToFunction/.inspection b/idea/testData/inspectionsLocal/convertPairConstructorToToFunction/.inspection
new file mode 100644
index 00000000000..30d850e18fb
--- /dev/null
+++ b/idea/testData/inspectionsLocal/convertPairConstructorToToFunction/.inspection
@@ -0,0 +1 @@
+org.jetbrains.kotlin.idea.inspections.ConvertPairConstructorToToFunctionInspection
\ No newline at end of file
diff --git a/idea/testData/inspectionsLocal/convertPairConstructorToToFunction/invalidArgs.kt b/idea/testData/inspectionsLocal/convertPairConstructorToToFunction/invalidArgs.kt
new file mode 100644
index 00000000000..966bc5f6166
--- /dev/null
+++ b/idea/testData/inspectionsLocal/convertPairConstructorToToFunction/invalidArgs.kt
@@ -0,0 +1,8 @@
+// PROBLEM: none
+// WITH_RUNTIME
+// ERROR: No value passed for parameter 'second'
+// ERROR: Type inference failed: Not enough information to infer parameter B in constructor Pair(first: A, second: B)
Please specify it explicitly.
+import kotlin.Pair
+fun test() {
+ val p = Pair(1, )
+}
\ No newline at end of file
diff --git a/idea/testData/inspectionsLocal/convertPairConstructorToToFunction/simple.kt b/idea/testData/inspectionsLocal/convertPairConstructorToToFunction/simple.kt
new file mode 100644
index 00000000000..ce589caced6
--- /dev/null
+++ b/idea/testData/inspectionsLocal/convertPairConstructorToToFunction/simple.kt
@@ -0,0 +1,5 @@
+// WITH_RUNTIME
+import kotlin.Pair
+fun test() {
+ val p = Pair(1, "foo")
+}
\ No newline at end of file
diff --git a/idea/testData/inspectionsLocal/convertPairConstructorToToFunction/simple.kt.after b/idea/testData/inspectionsLocal/convertPairConstructorToToFunction/simple.kt.after
new file mode 100644
index 00000000000..62e3878d352
--- /dev/null
+++ b/idea/testData/inspectionsLocal/convertPairConstructorToToFunction/simple.kt.after
@@ -0,0 +1,5 @@
+// WITH_RUNTIME
+import kotlin.Pair
+fun test() {
+ val p = 1 to "foo"
+}
\ No newline at end of file
diff --git a/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java
index dd7ebc8aa17..5628df2e1c2 100644
--- a/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java
+++ b/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java
@@ -1213,6 +1213,27 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest {
}
}
+ @TestMetadata("idea/testData/inspectionsLocal/convertPairConstructorToToFunction")
+ @TestDataPath("$PROJECT_ROOT")
+ @RunWith(JUnit3RunnerWithInners.class)
+ public static class ConvertPairConstructorToToFunction extends AbstractLocalInspectionTest {
+ public void testAllFilesPresentInConvertPairConstructorToToFunction() throws Exception {
+ KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/inspectionsLocal/convertPairConstructorToToFunction"), Pattern.compile("^([\\w\\-_]+)\\.(kt|kts)$"), TargetBackend.ANY, true);
+ }
+
+ @TestMetadata("invalidArgs.kt")
+ public void testInvalidArgs() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/convertPairConstructorToToFunction/invalidArgs.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("simple.kt")
+ public void testSimple() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/convertPairConstructorToToFunction/simple.kt");
+ doTest(fileName);
+ }
+ }
+
@TestMetadata("idea/testData/inspectionsLocal/copyWithoutNamedArguments")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)