Extract Function: Generate named argument for extracted lambda (when necessary)

This commit is contained in:
Alexey Sedunov
2014-09-18 18:28:36 +04:00
parent 6a76ca1066
commit 40761dfc4c
7 changed files with 31 additions and 7 deletions
@@ -305,6 +305,7 @@ fun ControlFlow.toDefault(): ControlFlow =
data class ExtractableCodeDescriptor(
val extractionData: ExtractionData,
val originalContext: BindingContext,
val name: String,
val visibility: String,
val parameters: List<Parameter>,
@@ -729,6 +729,7 @@ fun ExtractionData.performAnalysis(): AnalysisResult {
return AnalysisResult(
ExtractableCodeDescriptor(
this,
bindingContext,
functionName,
if (isVisibilityApplicable()) "private" else "",
adjustedParameters.sortBy { it.name },
@@ -193,7 +193,7 @@ fun ExtractableCodeDescriptor.findDuplicates(): List<DuplicateInfo> {
}
private fun makeCall(
name: String,
extractableDescriptor: ExtractableCodeDescriptor,
declaration: JetNamedDeclaration,
controlFlow: ControlFlow,
rangeToReplace: JetPsiRange,
@@ -202,8 +202,7 @@ private fun makeCall(
val firstExpression = rangeToReplace.elements.firstOrNull { it is JetExpression } as? JetExpression
if (firstExpression?.isFunctionLiteralOutsideParentheses() ?: false) {
val functionLiteralArgument = PsiTreeUtil.getParentOfType(firstExpression, javaClass<JetFunctionLiteralArgument>())!!
//todo use the right binding context
functionLiteralArgument.moveInsideParenthesesAndReplaceWith(wrappedCall, BindingContext.EMPTY)
functionLiteralArgument.moveInsideParenthesesAndReplaceWith(wrappedCall, extractableDescriptor.originalContext)
return
}
anchor.replace(wrappedCall)
@@ -223,8 +222,8 @@ private fun makeCall(
val callText = when (declaration) {
is JetNamedFunction ->
arguments.joinToString(separator = ", ", prefix = "${name}(", postfix = ")")
else -> name
arguments.joinToString(separator = ", ", prefix = "${extractableDescriptor.name}(", postfix = ")")
else -> extractableDescriptor.name
}
val anchorInBlock = stream(anchor) { it.getParent() }.firstOrNull { it.getParent() is JetBlockExpression }
@@ -512,9 +511,9 @@ fun ExtractableCodeDescriptor.generateDeclaration(options: ExtractionGeneratorOp
if (options.inTempFile) return ExtractionResult(declaration, Collections.emptyMap(), nameByOffset)
makeCall(name, declaration, controlFlow, extractionData.originalRange, parameters.map { it.argumentText })
makeCall(this, declaration, controlFlow, extractionData.originalRange, parameters.map { it.argumentText })
ShortenReferences.process(declaration)
val duplicateReplacers = duplicates.map { it.range to { makeCall(name, declaration, it.controlFlow, it.range, it.arguments) } }.toMap()
val duplicateReplacers = duplicates.map { it.range to { makeCall(this, declaration, it.controlFlow, it.range, it.arguments) } }.toMap()
return ExtractionResult(declaration, duplicateReplacers, nameByOffset)
}
@@ -258,6 +258,7 @@ public class KotlinExtractFunctionDialog extends DialogWrapper {
return new ExtractableCodeDescriptor(
descriptor.getExtractionData(),
descriptor.getOriginalContext(),
getFunctionName(),
getVisibility(),
ContainerUtil.newArrayList(oldToNewParameters.values()),
@@ -0,0 +1,6 @@
fun <T> Array<T>.check(a: Int, b: Int, f: (T) -> Boolean): Boolean = false
// SIBLING:
fun foo(t: Array<Int>) {
t.check(a = 1, b = 2) <selection>{ it + 1 > 1 }</selection>
}
@@ -0,0 +1,10 @@
fun <T> Array<T>.check(a: Int, b: Int, f: (T) -> Boolean): Boolean = false
// SIBLING:
fun foo(t: Array<Int>) {
t.check(a = 1, b = 2, f = function())
}
private fun function(): (Int) -> Boolean {
return { it + 1 > 1 }
}
@@ -665,6 +665,12 @@ public class JetExtractionTestGenerated extends AbstractJetExtractionTest {
doExtractFunctionTest(fileName);
}
@TestMetadata("trailingLambdaNonEmptyArgListWithNamedArgs.kt")
public void testTrailingLambdaNonEmptyArgListWithNamedArgs() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/trailingLambdaNonEmptyArgListWithNamedArgs.kt");
doExtractFunctionTest(fileName);
}
}
@TestMetadata("idea/testData/refactoring/extractFunction/controlFlow/initializer")