diff --git a/idea/resources/inspectionDescriptions/FromClosedRangeMigration.html b/idea/resources/inspectionDescriptions/FromClosedRangeMigration.html
new file mode 100644
index 00000000000..932db285d0e
--- /dev/null
+++ b/idea/resources/inspectionDescriptions/FromClosedRangeMigration.html
@@ -0,0 +1,8 @@
+
+
+
+ Since Kotlin 1.3 it's prohibited to call IntProgression.fromClosedRange() and LongProgression.fromClosedRange() with
+ MIN_VALUE step. All such calls should be checked during migration to Kotlin 1.3+.
+
+
+
diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml
index 98500f3e5f2..12200cc0362 100644
--- a/idea/src/META-INF/plugin.xml
+++ b/idea/src/META-INF/plugin.xml
@@ -2908,6 +2908,15 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
language="kotlin"
/>
+
+
diff --git a/idea/src/META-INF/plugin.xml.172 b/idea/src/META-INF/plugin.xml.172
index 49e8676d089..55def149811 100644
--- a/idea/src/META-INF/plugin.xml.172
+++ b/idea/src/META-INF/plugin.xml.172
@@ -2905,6 +2905,15 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
language="kotlin"
/>
+
+
diff --git a/idea/src/META-INF/plugin.xml.173 b/idea/src/META-INF/plugin.xml.173
index faec942abe3..d609db88c74 100644
--- a/idea/src/META-INF/plugin.xml.173
+++ b/idea/src/META-INF/plugin.xml.173
@@ -2908,6 +2908,15 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
language="kotlin"
/>
+
+
diff --git a/idea/src/META-INF/plugin.xml.182 b/idea/src/META-INF/plugin.xml.182
index 31f698f7c4c..74767785abd 100644
--- a/idea/src/META-INF/plugin.xml.182
+++ b/idea/src/META-INF/plugin.xml.182
@@ -2909,6 +2909,15 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
language="kotlin"
/>
+
+
diff --git a/idea/src/META-INF/plugin.xml.as31 b/idea/src/META-INF/plugin.xml.as31
index 723fff3c575..12f01eed3df 100644
--- a/idea/src/META-INF/plugin.xml.as31
+++ b/idea/src/META-INF/plugin.xml.as31
@@ -2908,6 +2908,15 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
language="kotlin"
/>
+
+
diff --git a/idea/src/META-INF/plugin.xml.as32 b/idea/src/META-INF/plugin.xml.as32
index 115bf1b8046..b5d4ca3b7bb 100644
--- a/idea/src/META-INF/plugin.xml.as32
+++ b/idea/src/META-INF/plugin.xml.as32
@@ -2908,6 +2908,15 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
language="kotlin"
/>
+
+
diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/migration/FromClosedRangeMigrationInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/migration/FromClosedRangeMigrationInspection.kt
new file mode 100644
index 00000000000..c734617cfd0
--- /dev/null
+++ b/idea/src/org/jetbrains/kotlin/idea/inspections/migration/FromClosedRangeMigrationInspection.kt
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2010-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.migration
+
+import com.intellij.codeInspection.ProblemHighlightType
+import com.intellij.codeInspection.ProblemsHolder
+import com.intellij.openapi.application.ApplicationManager
+import org.jetbrains.kotlin.config.LanguageVersion
+import org.jetbrains.kotlin.descriptors.CallableDescriptor
+import org.jetbrains.kotlin.idea.caches.resolve.analyze
+import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall
+import org.jetbrains.kotlin.idea.inspections.AbstractKotlinInspection
+import org.jetbrains.kotlin.idea.project.languageVersionSettings
+import org.jetbrains.kotlin.idea.references.resolveMainReferenceToDescriptors
+import org.jetbrains.kotlin.psi.KtCallExpression
+import org.jetbrains.kotlin.psi.KtSimpleNameExpression
+import org.jetbrains.kotlin.psi.simpleNameExpressionVisitor
+import org.jetbrains.kotlin.resolve.calls.model.ExpressionValueArgument
+import org.jetbrains.kotlin.resolve.constants.TypedCompileTimeConstant
+import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
+import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull
+import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
+
+class FromClosedRangeMigrationInspection : AbstractKotlinInspection() {
+ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean) =
+ simpleNameExpressionVisitor(fun(simpleNameExpression) {
+ val callExpression = simpleNameExpression.parent as? KtCallExpression ?: return
+ if (simpleNameExpression.text != SHORT_NAME) return
+
+ run {
+ val versionAtLeast13 = simpleNameExpression.languageVersionSettings.languageVersion >= LanguageVersion.KOTLIN_1_3
+ if (!versionAtLeast13 && !ApplicationManager.getApplication().isUnitTestMode) {
+ return
+ }
+ }
+
+ val descriptor = simpleNameExpression.resolveMainReferenceToDescriptors().firstOrNull() ?: return
+ val callableDescriptor = descriptor as? CallableDescriptor ?: return
+
+ val resolvedToFqName = callableDescriptor.fqNameOrNull()?.asString() ?: return
+ if (resolvedToFqName != INT_FROM_CLOSE_RANGE_FQNAME && resolvedToFqName != LONG_FROM_CLOSE_RANGE_FQNAME) {
+ return
+ }
+
+ val stepParameter = callableDescriptor.valueParameters.getOrNull(2) ?: return
+ if (stepParameter.name.asString() != "step") return
+
+ val resolvedCall = callExpression.resolveToCall() ?: return
+ val resolvedValueArgument = resolvedCall.valueArguments[stepParameter] as? ExpressionValueArgument ?: return
+ val argumentExpression = resolvedValueArgument.valueArgument?.getArgumentExpression() ?: return
+
+ val constant = ConstantExpressionEvaluator.getConstant(argumentExpression, argumentExpression.analyze(BodyResolveMode.PARTIAL))
+ if (constant != null) {
+ val value = (constant as? TypedCompileTimeConstant<*>)?.constantValue?.value
+ if (value != null) {
+ if ((resolvedToFqName == INT_FROM_CLOSE_RANGE_FQNAME && Int.MIN_VALUE == value) ||
+ (resolvedToFqName == LONG_FROM_CLOSE_RANGE_FQNAME && Long.MIN_VALUE == value)
+ ) {
+ report(holder, simpleNameExpression, resolvedToFqName, isOnTheFly, isError = true)
+ return
+ }
+ }
+
+ // Don't report for constants other than MIN_VALUE
+ return
+ }
+
+ report(holder, simpleNameExpression, resolvedToFqName, isOnTheFly, isError = false)
+ })
+
+ private fun report(
+ holder: ProblemsHolder,
+ simpleNameExpression: KtSimpleNameExpression,
+ resolvedToFqName: String,
+ isOnTheFly: Boolean,
+ isError: Boolean
+ ) {
+ val desc = when (resolvedToFqName) {
+ INT_FROM_CLOSE_RANGE_FQNAME -> INT_FROM_CLOSE_RANGE_DESC
+ LONG_FROM_CLOSE_RANGE_FQNAME -> LONG_FROM_CLOSE_RANGE_DESC
+ else -> throw IllegalArgumentException("Can't process $resolvedToFqName")
+ }
+
+ val problemDescriptor = holder.manager.createProblemDescriptor(
+ simpleNameExpression,
+ simpleNameExpression,
+ "It's prohibited to call $desc with MIN_VALUE step since 1.3",
+ if (isError) ProblemHighlightType.ERROR else ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
+ isOnTheFly
+ )
+
+ holder.registerProblem(problemDescriptor)
+ }
+
+ companion object {
+ private const val SHORT_NAME = "fromClosedRange"
+
+ private const val INT_FROM_CLOSE_RANGE_FQNAME = "kotlin.ranges.IntProgression.Companion.fromClosedRange"
+ private const val INT_FROM_CLOSE_RANGE_DESC = "IntProgression.fromClosedRange()"
+
+ private const val LONG_FROM_CLOSE_RANGE_FQNAME = "kotlin.ranges.LongProgression.Companion.fromClosedRange"
+ private const val LONG_FROM_CLOSE_RANGE_DESC = "LongProgression.fromClosedRange()"
+ }
+}
diff --git a/idea/testData/inspections/migrationFromClosedRange/inspectionData/expected.xml b/idea/testData/inspections/migrationFromClosedRange/inspectionData/expected.xml
new file mode 100644
index 00000000000..f493e15e6aa
--- /dev/null
+++ b/idea/testData/inspections/migrationFromClosedRange/inspectionData/expected.xml
@@ -0,0 +1,22 @@
+
+
+ test.kt
+ 6
+ It's prohibited to call IntProgression.fromClosedRange() with MIN_VALUE step since 1.3
+
+
+ test.kt
+ 7
+ It's prohibited to call IntProgression.fromClosedRange() with MIN_VALUE step since 1.3
+
+
+ test.kt
+ 14
+ It's prohibited to call LongProgression.fromClosedRange() with MIN_VALUE step since 1.3
+
+
+ test.kt
+ 15
+ It's prohibited to call LongProgression.fromClosedRange() with MIN_VALUE step since 1.3
+
+
diff --git a/idea/testData/inspections/migrationFromClosedRange/inspectionData/inspections.test b/idea/testData/inspections/migrationFromClosedRange/inspectionData/inspections.test
new file mode 100644
index 00000000000..3ddfde35744
--- /dev/null
+++ b/idea/testData/inspections/migrationFromClosedRange/inspectionData/inspections.test
@@ -0,0 +1 @@
+// INSPECTION_CLASS: org.jetbrains.kotlin.idea.inspections.migration.FromClosedRangeMigrationInspection
\ No newline at end of file
diff --git a/idea/testData/inspections/migrationFromClosedRange/test.kt b/idea/testData/inspections/migrationFromClosedRange/test.kt
new file mode 100644
index 00000000000..87a15178b47
--- /dev/null
+++ b/idea/testData/inspections/migrationFromClosedRange/test.kt
@@ -0,0 +1,22 @@
+package fromClosedRange
+
+import kotlin.ranges.IntProgression.Companion.fromClosedRange
+
+fun testInt(rangeStart: Int, rangeEnd: Int, step: Int) {
+ fromClosedRange(12, 143, step) // report
+ fromClosedRange(12, 143, Int.MIN_VALUE) // report
+
+ fromClosedRange(step = 12, rangeEnd = rangeEnd, rangeStart = rangeStart) // do not report
+ fromClosedRange(12, 143, 2) // do not report
+}
+
+fun testLong(rangeStart: Long, rangeEnd: Long, step: Long) {
+ LongProgression.fromClosedRange(12, 143, step) // report
+ LongProgression.fromClosedRange(12, 143, Long.MIN_VALUE) // report
+
+ LongProgression.fromClosedRange(12, 143, 2.toLong()) // do no report
+ LongProgression.fromClosedRange(step = 12, rangeEnd = rangeEnd, rangeStart = rangeStart) // do not report
+ LongProgression.fromClosedRange(12, 143, 2) // do not report
+ LongProgression.fromClosedRange(12, 143, 2L) // do not report
+ LongProgression.fromClosedRange(12, 143, Int.MIN_VALUE) // do not report
+}
\ No newline at end of file
diff --git a/idea/tests/org/jetbrains/kotlin/idea/codeInsight/InspectionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/codeInsight/InspectionTestGenerated.java
index 7795fc663e0..36b86ddacfb 100644
--- a/idea/tests/org/jetbrains/kotlin/idea/codeInsight/InspectionTestGenerated.java
+++ b/idea/tests/org/jetbrains/kotlin/idea/codeInsight/InspectionTestGenerated.java
@@ -204,6 +204,11 @@ public class InspectionTestGenerated extends AbstractInspectionTest {
runTest("idea/testData/inspections/memberVisibilityCanBePrivate/inspectionData/inspections.test");
}
+ @TestMetadata("migrationFromClosedRange/inspectionData/inspections.test")
+ public void testMigrationFromClosedRange_inspectionData_Inspections_test() throws Exception {
+ runTest("idea/testData/inspections/migrationFromClosedRange/inspectionData/inspections.test");
+ }
+
@TestMetadata("naming/class/inspectionData/inspections.test")
public void testNaming_class_inspectionData_Inspections_test() throws Exception {
runTest("idea/testData/inspections/naming/class/inspectionData/inspections.test");