Intentions: Fix insertion of necessary lambda parameter for run/let and apply/also conversions

#KT-22931 Fixed
This commit is contained in:
Alexey Sedunov
2018-05-29 20:59:21 +03:00
parent f17053f970
commit fbb4914bfb
6 changed files with 63 additions and 15 deletions
@@ -114,28 +114,24 @@ class Replacement<T : PsiElement> private constructor(
get() = elementPointer.element!!.endOffset
}
class ReplacementCollection {
private lateinit var project: Project
class ReplacementCollection(private val project: Project) {
private val replacements = mutableListOf<Replacement<out PsiElement>>()
var createParameter: KtPsiFactory.() -> PsiElement? = { null }
var elementToRename: PsiElement? = null
fun <T : PsiElement> 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) {
@@ -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?.<caret>apply {
println("${it.firstName} has a manager")
}
}
}
@@ -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?.<caret>also { employee1 ->
println("${it.firstName} has a manager")
}
}
}
@@ -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?.<caret>run {
println("${it.firstName} has a manager")
}
}
}
@@ -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?.<caret>let { employee1 ->
println("${it.firstName} has a manager")
}
}
}
@@ -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");