From fbb4914bfb6830d61ee76a6136effbdfcca4fe24 Mon Sep 17 00:00:00 2001 From: Alexey Sedunov Date: Tue, 29 May 2018 20:59:21 +0300 Subject: [PATCH] Intentions: Fix insertion of necessary lambda parameter for run/let and apply/also conversions #KT-22931 Fixed --- .../ScopeFunctionConversionInspection.kt | 24 +++++++------------ .../scopeFunctions/applyToAlso/capturedIt.kt | 11 +++++++++ .../applyToAlso/capturedIt.kt.after | 11 +++++++++ .../scopeFunctions/runToLet/capturedIt.kt | 11 +++++++++ .../runToLet/capturedIt.kt.after | 11 +++++++++ .../LocalInspectionTestGenerated.java | 10 ++++++++ 6 files changed, 63 insertions(+), 15 deletions(-) create mode 100644 idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/capturedIt.kt create mode 100644 idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/capturedIt.kt.after create mode 100644 idea/testData/inspectionsLocal/scopeFunctions/runToLet/capturedIt.kt create mode 100644 idea/testData/inspectionsLocal/scopeFunctions/runToLet/capturedIt.kt.after diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/ScopeFunctionConversionInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/ScopeFunctionConversionInspection.kt index 36438331d48..8d94803d53b 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/ScopeFunctionConversionInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/ScopeFunctionConversionInspection.kt @@ -114,28 +114,24 @@ class Replacement private constructor( get() = elementPointer.element!!.endOffset } -class ReplacementCollection { - private lateinit var project: Project +class ReplacementCollection(private val project: Project) { private val replacements = mutableListOf>() var createParameter: KtPsiFactory.() -> PsiElement? = { null } var elementToRename: PsiElement? = null fun add(element: T, replacementFactory: KtPsiFactory.(T) -> PsiElement) { - project = element.project replacements.add(Replacement.create(element, replacementFactory)) } fun apply() { - if (replacements.isNotEmpty()) { - val factory = KtPsiFactory(project) - elementToRename = factory.createParameter() + val factory = KtPsiFactory(project) + elementToRename = factory.createParameter() - // Calls need to be processed in outside-in order - replacements.sortBy { it.endOffset } + // Calls need to be processed in outside-in order + replacements.sortBy { it.endOffset } - for (replacement in replacements) { - replacement.apply(factory) - } + for (replacement in replacements) { + replacement.apply(factory) } } @@ -157,12 +153,10 @@ abstract class ConvertScopeFunctionFix(private val counterpartName: String) : Lo functionLiteral.valueParameterList?.delete() functionLiteral.arrow?.delete() - val replacements = ReplacementCollection() + val replacements = ReplacementCollection(project) analyzeLambda(bindingContext, lambda, lambdaDescriptor, replacements) callee.replace(KtPsiFactory(project).createExpression(counterpartName) as KtNameReferenceExpression) - if (replacements.isNotEmpty()) { - replacements.apply() - } + replacements.apply() postprocessLambda(lambda) if (replacements.isNotEmpty() && replacements.elementToRename != null && !ApplicationManager.getApplication().isUnitTestMode) { diff --git a/idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/capturedIt.kt b/idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/capturedIt.kt new file mode 100644 index 00000000000..33aeda1b320 --- /dev/null +++ b/idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/capturedIt.kt @@ -0,0 +1,11 @@ +// WITH_RUNTIME +// FIX: Convert to 'also' +class Employee(val firstName: String, val manager: Employee?) + +fun test(employee: Employee) { + val person = employee.also { + it.manager?.apply { + println("${it.firstName} has a manager") + } + } +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/capturedIt.kt.after b/idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/capturedIt.kt.after new file mode 100644 index 00000000000..c9e1df2b704 --- /dev/null +++ b/idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/capturedIt.kt.after @@ -0,0 +1,11 @@ +// WITH_RUNTIME +// FIX: Convert to 'also' +class Employee(val firstName: String, val manager: Employee?) + +fun test(employee: Employee) { + val person = employee.also { + it.manager?.also { employee1 -> + println("${it.firstName} has a manager") + } + } +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/scopeFunctions/runToLet/capturedIt.kt b/idea/testData/inspectionsLocal/scopeFunctions/runToLet/capturedIt.kt new file mode 100644 index 00000000000..c7156aa9836 --- /dev/null +++ b/idea/testData/inspectionsLocal/scopeFunctions/runToLet/capturedIt.kt @@ -0,0 +1,11 @@ +// WITH_RUNTIME +// FIX: Convert to 'let' +class Employee(val firstName: String, val manager: Employee?) + +fun test(employee: Employee) { + val person = employee.also { + it.manager?.run { + println("${it.firstName} has a manager") + } + } +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/scopeFunctions/runToLet/capturedIt.kt.after b/idea/testData/inspectionsLocal/scopeFunctions/runToLet/capturedIt.kt.after new file mode 100644 index 00000000000..2b6825b0d17 --- /dev/null +++ b/idea/testData/inspectionsLocal/scopeFunctions/runToLet/capturedIt.kt.after @@ -0,0 +1,11 @@ +// WITH_RUNTIME +// FIX: Convert to 'let' +class Employee(val firstName: String, val manager: Employee?) + +fun test(employee: Employee) { + val person = employee.also { + it.manager?.let { employee1 -> + println("${it.firstName} has a manager") + } + } +} \ 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 b79c86c42ad..62b5d34f65e 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java @@ -4040,6 +4040,11 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest { runTest("idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/arrow.kt"); } + @TestMetadata("capturedIt.kt") + public void testCapturedIt() throws Exception { + runTest("idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/capturedIt.kt"); + } + @TestMetadata("doubleNestedLambdas.kt") public void testDoubleNestedLambdas() throws Exception { runTest("idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/doubleNestedLambdas.kt"); @@ -4146,6 +4151,11 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/inspectionsLocal/scopeFunctions/runToLet"), Pattern.compile("^([\\w\\-_]+)\\.(kt|kts)$"), TargetBackend.ANY, true); } + @TestMetadata("capturedIt.kt") + public void testCapturedIt() throws Exception { + runTest("idea/testData/inspectionsLocal/scopeFunctions/runToLet/capturedIt.kt"); + } + @TestMetadata("simple.kt") public void testSimple() throws Exception { runTest("idea/testData/inspectionsLocal/scopeFunctions/runToLet/simple.kt");