diff --git a/idea/resources/inspectionDescriptions/ConvertFlatMapToFlatten.html b/idea/resources/inspectionDescriptions/ConvertFlatMapToFlatten.html new file mode 100644 index 00000000000..a7cc8a528fe --- /dev/null +++ b/idea/resources/inspectionDescriptions/ConvertFlatMapToFlatten.html @@ -0,0 +1,5 @@ + + +This inspection reports flatMap call should be simplified to flatten(), e.g. flatMap { it } to flatten(). + + diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index fa7872ad09c..aa31e7b761b 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -3039,6 +3039,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 8f8d4cbdbbc..27d6c8f455d 100644 --- a/idea/src/META-INF/plugin.xml.173 +++ b/idea/src/META-INF/plugin.xml.173 @@ -3037,6 +3037,15 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio. language="kotlin" /> + + diff --git a/idea/src/META-INF/plugin.xml.181 b/idea/src/META-INF/plugin.xml.181 index 321013fc1ba..dfdd3b736b1 100644 --- a/idea/src/META-INF/plugin.xml.181 +++ b/idea/src/META-INF/plugin.xml.181 @@ -3038,6 +3038,15 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio. language="kotlin" /> + + diff --git a/idea/src/META-INF/plugin.xml.183 b/idea/src/META-INF/plugin.xml.183 index ffba4f0ff97..3af9fba0e56 100644 --- a/idea/src/META-INF/plugin.xml.183 +++ b/idea/src/META-INF/plugin.xml.183 @@ -3039,6 +3039,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 1953f7ea79b..5c3c95f81b0 100644 --- a/idea/src/META-INF/plugin.xml.as31 +++ b/idea/src/META-INF/plugin.xml.as31 @@ -3037,6 +3037,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 1922b6e246d..a987366d62e 100644 --- a/idea/src/META-INF/plugin.xml.as32 +++ b/idea/src/META-INF/plugin.xml.as32 @@ -3037,6 +3037,15 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio. language="kotlin" /> + + diff --git a/idea/src/META-INF/plugin.xml.as33 b/idea/src/META-INF/plugin.xml.as33 index 3105f883922..b988fa76aa8 100644 --- a/idea/src/META-INF/plugin.xml.as33 +++ b/idea/src/META-INF/plugin.xml.as33 @@ -3039,6 +3039,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/collections/ConvertFlatMapToFlattenInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/collections/ConvertFlatMapToFlattenInspection.kt new file mode 100644 index 00000000000..e847681fdf5 --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/collections/ConvertFlatMapToFlattenInspection.kt @@ -0,0 +1,57 @@ +/* + * 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.collections + +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 org.jetbrains.kotlin.idea.caches.resolve.analyze +import org.jetbrains.kotlin.idea.inspections.AbstractKotlinInspection +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall +import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe +import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode + +class ConvertFlatMapToFlattenInspection : AbstractKotlinInspection() { + override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean) = + qualifiedExpressionVisitor(fun(expression) { + val callExpression = expression.selectorExpression as? KtCallExpression ?: return + val calleeExpression = callExpression.calleeExpression ?: return + if (calleeExpression.text != "flatMap") return + val context = expression.analyze(BodyResolveMode.PARTIAL) + if (FqName("kotlin.collections.flatMap") != callExpression.getResolvedCall(context)?.resultingDescriptor?.fqNameSafe) return + + val argument = callExpression.valueArguments.singleOrNull() ?: return + val lambdaExpression = (argument as? KtLambdaArgument)?.getLambdaExpression() + ?: argument.getArgumentExpression() as? KtLambdaExpression + ?: return + val reference = lambdaExpression.bodyExpression?.statements?.singleOrNull() as? KtNameReferenceExpression ?: return + val lambdaParameters = lambdaExpression.valueParameters + val lambdaParameterName = if (lambdaParameters.isNotEmpty()) lambdaParameters.singleOrNull()?.name else "it" + if (reference.text != lambdaParameterName) return + + holder.registerProblem( + calleeExpression, + "flatMap call should be simplified to flatten()", + ProblemHighlightType.GENERIC_ERROR_OR_WARNING, + ConvertFlatMapToFlattenFix() + ) + }) +} + +private class ConvertFlatMapToFlattenFix : LocalQuickFix { + override fun getName() = "Convert flatMap to flatten" + + override fun getFamilyName() = name + + override fun applyFix(project: Project, descriptor: ProblemDescriptor) { + val callExpression = descriptor.psiElement.parent as? KtCallExpression ?: return + callExpression.replace(KtPsiFactory(callExpression).createExpression("flatten()")) + } +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/collections/convertFlatMapToFlatten/.inspection b/idea/testData/inspectionsLocal/collections/convertFlatMapToFlatten/.inspection new file mode 100644 index 00000000000..9803885df1a --- /dev/null +++ b/idea/testData/inspectionsLocal/collections/convertFlatMapToFlatten/.inspection @@ -0,0 +1 @@ +org.jetbrains.kotlin.idea.inspections.collections.ConvertFlatMapToFlattenInspection \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/collections/convertFlatMapToFlatten/explicitLambdaParameter.kt b/idea/testData/inspectionsLocal/collections/convertFlatMapToFlatten/explicitLambdaParameter.kt new file mode 100644 index 00000000000..de2cf09f0f5 --- /dev/null +++ b/idea/testData/inspectionsLocal/collections/convertFlatMapToFlatten/explicitLambdaParameter.kt @@ -0,0 +1,4 @@ +// WITH_RUNTIME +fun test() { + listOf(listOf(1)).flatMap { i -> i } +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/collections/convertFlatMapToFlatten/explicitLambdaParameter.kt.after b/idea/testData/inspectionsLocal/collections/convertFlatMapToFlatten/explicitLambdaParameter.kt.after new file mode 100644 index 00000000000..cd15b758727 --- /dev/null +++ b/idea/testData/inspectionsLocal/collections/convertFlatMapToFlatten/explicitLambdaParameter.kt.after @@ -0,0 +1,4 @@ +// WITH_RUNTIME +fun test() { + listOf(listOf(1)).flatten() +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/collections/convertFlatMapToFlatten/notOnlyReference.kt b/idea/testData/inspectionsLocal/collections/convertFlatMapToFlatten/notOnlyReference.kt new file mode 100644 index 00000000000..3f6ad1eecc0 --- /dev/null +++ b/idea/testData/inspectionsLocal/collections/convertFlatMapToFlatten/notOnlyReference.kt @@ -0,0 +1,5 @@ +// PROBLEM: none +// WITH_RUNTIME +fun test() { + listOf(listOf(1)).flatMap { it + 1 } +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/collections/convertFlatMapToFlatten/set.kt b/idea/testData/inspectionsLocal/collections/convertFlatMapToFlatten/set.kt new file mode 100644 index 00000000000..69df01a7dff --- /dev/null +++ b/idea/testData/inspectionsLocal/collections/convertFlatMapToFlatten/set.kt @@ -0,0 +1,4 @@ +// WITH_RUNTIME +fun test() { + setOf(setOf(1)).flatMap { it } +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/collections/convertFlatMapToFlatten/set.kt.after b/idea/testData/inspectionsLocal/collections/convertFlatMapToFlatten/set.kt.after new file mode 100644 index 00000000000..9da21c7c51b --- /dev/null +++ b/idea/testData/inspectionsLocal/collections/convertFlatMapToFlatten/set.kt.after @@ -0,0 +1,4 @@ +// WITH_RUNTIME +fun test() { + setOf(setOf(1)).flatten() +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/collections/convertFlatMapToFlatten/simple.kt b/idea/testData/inspectionsLocal/collections/convertFlatMapToFlatten/simple.kt new file mode 100644 index 00000000000..df2f5adc81a --- /dev/null +++ b/idea/testData/inspectionsLocal/collections/convertFlatMapToFlatten/simple.kt @@ -0,0 +1,4 @@ +// WITH_RUNTIME +fun test() { + listOf(listOf(1)).flatMap { it } +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/collections/convertFlatMapToFlatten/simple.kt.after b/idea/testData/inspectionsLocal/collections/convertFlatMapToFlatten/simple.kt.after new file mode 100644 index 00000000000..cd15b758727 --- /dev/null +++ b/idea/testData/inspectionsLocal/collections/convertFlatMapToFlatten/simple.kt.after @@ -0,0 +1,4 @@ +// WITH_RUNTIME +fun test() { + listOf(listOf(1)).flatten() +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/collections/convertFlatMapToFlatten/simple2.kt b/idea/testData/inspectionsLocal/collections/convertFlatMapToFlatten/simple2.kt new file mode 100644 index 00000000000..f43de75a39d --- /dev/null +++ b/idea/testData/inspectionsLocal/collections/convertFlatMapToFlatten/simple2.kt @@ -0,0 +1,4 @@ +// WITH_RUNTIME +fun test() { + listOf(listOf(1)).flatMap({ it }) +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/collections/convertFlatMapToFlatten/simple2.kt.after b/idea/testData/inspectionsLocal/collections/convertFlatMapToFlatten/simple2.kt.after new file mode 100644 index 00000000000..cd15b758727 --- /dev/null +++ b/idea/testData/inspectionsLocal/collections/convertFlatMapToFlatten/simple2.kt.after @@ -0,0 +1,4 @@ +// WITH_RUNTIME +fun test() { + listOf(listOf(1)).flatten() +} \ 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 f61a3b66dc7..7f4926cbcb6 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java @@ -953,6 +953,44 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest { } } + @TestMetadata("idea/testData/inspectionsLocal/collections/convertFlatMapToFlatten") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class ConvertFlatMapToFlatten extends AbstractLocalInspectionTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath); + } + + public void testAllFilesPresentInConvertFlatMapToFlatten() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/inspectionsLocal/collections/convertFlatMapToFlatten"), Pattern.compile("^([\\w\\-_]+)\\.(kt|kts)$"), TargetBackend.ANY, true); + } + + @TestMetadata("explicitLambdaParameter.kt") + public void testExplicitLambdaParameter() throws Exception { + runTest("idea/testData/inspectionsLocal/collections/convertFlatMapToFlatten/explicitLambdaParameter.kt"); + } + + @TestMetadata("notOnlyReference.kt") + public void testNotOnlyReference() throws Exception { + runTest("idea/testData/inspectionsLocal/collections/convertFlatMapToFlatten/notOnlyReference.kt"); + } + + @TestMetadata("set.kt") + public void testSet() throws Exception { + runTest("idea/testData/inspectionsLocal/collections/convertFlatMapToFlatten/set.kt"); + } + + @TestMetadata("simple.kt") + public void testSimple() throws Exception { + runTest("idea/testData/inspectionsLocal/collections/convertFlatMapToFlatten/simple.kt"); + } + + @TestMetadata("simple2.kt") + public void testSimple2() throws Exception { + runTest("idea/testData/inspectionsLocal/collections/convertFlatMapToFlatten/simple2.kt"); + } + } + @TestMetadata("idea/testData/inspectionsLocal/collections/simplifiableCallChain") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class)