Extract Function: Generate variables when boxing multiline expressions
This commit is contained in:
+6
@@ -155,6 +155,8 @@ abstract class OutputValueBoxer(val outputValues: List<OutputValue>) {
|
||||
|
||||
protected abstract fun getBoxingExpressionText(arguments: List<String>): String?
|
||||
|
||||
abstract val boxingRequired: Boolean
|
||||
|
||||
fun getReturnExpression(arguments: List<String>, psiFactory: JetPsiFactory): JetReturnExpression? {
|
||||
return getBoxingExpressionText(arguments)?.let { psiFactory.createReturn(it) }
|
||||
}
|
||||
@@ -208,6 +210,8 @@ abstract class OutputValueBoxer(val outputValues: List<OutputValue>) {
|
||||
getType()
|
||||
}
|
||||
|
||||
override val boxingRequired: Boolean = outputValues.size > 1
|
||||
|
||||
override fun getBoxingExpressionText(arguments: List<String>): String? {
|
||||
return when (arguments.size) {
|
||||
0 -> null
|
||||
@@ -245,6 +249,8 @@ abstract class OutputValueBoxer(val outputValues: List<OutputValue>) {
|
||||
)
|
||||
}
|
||||
|
||||
override val boxingRequired: Boolean = outputValues.size > 0
|
||||
|
||||
override fun getBoxingExpressionText(arguments: List<String>): String? {
|
||||
if (arguments.isEmpty()) return null
|
||||
return arguments.joinToString(prefix = "kotlin.listOf(", separator = ", ", postfix = ")")
|
||||
|
||||
@@ -43,7 +43,6 @@ import org.jetbrains.jet.lang.psi.psiUtil.prependElement
|
||||
import org.jetbrains.jet.lang.psi.psiUtil.appendElement
|
||||
import org.jetbrains.jet.lang.psi.psiUtil.replaced
|
||||
import org.jetbrains.jet.plugin.intentions.declarations.DeclarationUtils
|
||||
import org.jetbrains.jet.lang.psi.psiUtil.getParentByTypesAndPredicate
|
||||
import org.jetbrains.jet.lang.psi.JetBlockExpression
|
||||
import org.jetbrains.jet.plugin.refactoring.extractFunction.OutputValue.ParameterUpdate
|
||||
import org.jetbrains.jet.plugin.refactoring.extractFunction.OutputValue.Jump
|
||||
@@ -52,6 +51,7 @@ import org.jetbrains.jet.plugin.refactoring.extractFunction.OutputValue.Expressi
|
||||
import org.jetbrains.jet.lang.psi.JetReturnExpression
|
||||
import org.jetbrains.jet.plugin.refactoring.JetNameValidatorImpl
|
||||
import org.jetbrains.jet.plugin.refactoring.JetNameSuggester
|
||||
import org.jetbrains.jet.plugin.refactoring.isMultiLine
|
||||
|
||||
fun ExtractableCodeDescriptor.getDeclarationText(
|
||||
options: ExtractionGeneratorOptions = ExtractionGeneratorOptions.DEFAULT,
|
||||
@@ -140,7 +140,8 @@ fun ExtractableCodeDescriptor.generateDeclaration(options: ExtractionGeneratorOp
|
||||
|
||||
fun replaceWithReturn(
|
||||
originalExpression: JetExpression,
|
||||
replacingExpression: JetReturnExpression
|
||||
replacingExpression: JetReturnExpression,
|
||||
expressionToUnifyWith: JetExpression?
|
||||
) {
|
||||
val currentResultExpression =
|
||||
if (originalExpression is JetReturnExpression) originalExpression.getReturnedExpression() else originalExpression
|
||||
@@ -154,7 +155,7 @@ fun ExtractableCodeDescriptor.generateDeclaration(options: ExtractionGeneratorOp
|
||||
throw AssertionError("Can' replace '${originalExpression.getText()}' with '${replacingExpression.getText()}'")
|
||||
}
|
||||
|
||||
val counterpartMap = createNameCounterpartMap(currentResultExpression, newResultExpression)
|
||||
val counterpartMap = createNameCounterpartMap(currentResultExpression, expressionToUnifyWith ?: newResultExpression)
|
||||
nameByOffset.entrySet().forEach { e -> counterpartMap[e.getValue()]?.let { e.setValue(it) } }
|
||||
}
|
||||
|
||||
@@ -225,19 +226,32 @@ fun ExtractableCodeDescriptor.generateDeclaration(options: ExtractionGeneratorOp
|
||||
}
|
||||
}
|
||||
|
||||
val defaultValue = controlFlow.defaultOutputValue
|
||||
|
||||
val lastExpression = body.getStatements().lastOrNull() as? JetExpression
|
||||
if (lastExpression is JetReturnExpression) return
|
||||
|
||||
val returnExpression = controlFlow.outputValueBoxer.getReturnExpression(getReturnArguments(lastExpression), psiFactory)
|
||||
val (defaultExpression, expressionToUnifyWith) =
|
||||
if (!options.inTempFile && defaultValue != null && controlFlow.outputValueBoxer.boxingRequired && lastExpression!!.isMultiLine()) {
|
||||
val varNameValidator = JetNameValidatorImpl(body, lastExpression, JetNameValidatorImpl.Target.PROPERTIES)
|
||||
val resultVal = JetNameSuggester.suggestNames(defaultValue.valueType, varNameValidator, null).first()
|
||||
val newDecl = body.addBefore(psiFactory.createDeclaration("val $resultVal = ${lastExpression!!.getText()}"), lastExpression) as JetProperty
|
||||
body.addBefore(psiFactory.createNewLine(), lastExpression)
|
||||
psiFactory.createExpression(resultVal) to newDecl.getInitializer()!!
|
||||
}
|
||||
else {
|
||||
lastExpression to null
|
||||
}
|
||||
|
||||
val returnExpression = controlFlow.outputValueBoxer.getReturnExpression(getReturnArguments(defaultExpression), psiFactory)
|
||||
if (returnExpression == null) return
|
||||
|
||||
val defaultValue = controlFlow.defaultOutputValue
|
||||
when {
|
||||
defaultValue == null ->
|
||||
body.appendElement(returnExpression)
|
||||
|
||||
!defaultValue.callSiteReturn ->
|
||||
replaceWithReturn(lastExpression!!, returnExpression)
|
||||
replaceWithReturn(lastExpression!!, returnExpression, expressionToUnifyWith)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -386,13 +400,12 @@ fun ExtractableCodeDescriptor.generateDeclaration(options: ExtractionGeneratorOp
|
||||
}
|
||||
}
|
||||
|
||||
val declaration = createDeclaration()
|
||||
val declaration = createDeclaration().let { if (options.inTempFile) it else insertDeclaration(it) }
|
||||
adjustDeclarationBody(declaration)
|
||||
|
||||
if (options.inTempFile) return ExtractionResult(declaration, nameByOffset)
|
||||
|
||||
val declarationInPlace = insertDeclaration(declaration)
|
||||
makeCall(declarationInPlace)
|
||||
ShortenReferences.process(declarationInPlace)
|
||||
makeCall(declaration)
|
||||
ShortenReferences.process(declaration)
|
||||
return ExtractionResult(declaration, nameByOffset)
|
||||
}
|
||||
@@ -271,18 +271,7 @@ fun PsiElement.getLineCount(): Int {
|
||||
return endLine - startLine
|
||||
}
|
||||
|
||||
var lineCount = 1
|
||||
accept(
|
||||
object: JetTreeVisitorVoid() {
|
||||
override fun visitWhiteSpace(space: PsiWhiteSpace) {
|
||||
if ("\n" in space.getText() ?: "") {
|
||||
lineCount++
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
return lineCount
|
||||
return (getText() ?: "").count { it == '\n' } + 1
|
||||
}
|
||||
|
||||
fun PsiElement.isMultiLine(): Boolean = getLineCount() > 1
|
||||
+3
-2
@@ -17,8 +17,9 @@ fun foo(a: Int): Int {
|
||||
|
||||
private fun pair(a: Int, b: Int): Pair<Int, Int> {
|
||||
var b1 = b
|
||||
return Pair(if (a > 0) {
|
||||
val i = if (a > 0) {
|
||||
b1 += a
|
||||
a + 1
|
||||
} else a, b1)
|
||||
} else a
|
||||
return Pair(i, b1)
|
||||
}
|
||||
+3
-2
@@ -17,10 +17,11 @@ fun foo(a: Int): Int {
|
||||
|
||||
private fun pair(a: Int, b: Int): Pair<Int, Int> {
|
||||
var b1 = b
|
||||
return Pair(if (a > 0) {
|
||||
val i = if (a > 0) {
|
||||
b1 += a
|
||||
b1
|
||||
} else {
|
||||
a
|
||||
}, b1)
|
||||
}
|
||||
return Pair(i, b1)
|
||||
}
|
||||
+3
-2
@@ -22,11 +22,12 @@ fun foo(a: Int): Int {
|
||||
private fun triple(a: Int, b: Int, c: Int): Triple<Int, Int, Int> {
|
||||
var b1 = b
|
||||
var c1 = c
|
||||
return Triple(if (a > 0) {
|
||||
val i = if (a > 0) {
|
||||
b1 += a
|
||||
c1 -= b1
|
||||
b1
|
||||
} else {
|
||||
a
|
||||
}, b1, c1)
|
||||
}
|
||||
return Triple(i, b1, c1)
|
||||
}
|
||||
+2
-1
@@ -747,7 +747,8 @@ public class JetExtractionTestGenerated extends AbstractJetExtractionTest {
|
||||
|
||||
@TestMetadata("outputValueWithSingleLineExpression.kt")
|
||||
public void testOutputValueWithSingleLineExpression() throws Exception {
|
||||
doExtractFunctionTest("idea/testData/refactoring/extractFunction/controlFlow/outputValues/outputValueWithSingleLineExpression.kt");
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/extractFunction/controlFlow/outputValues/outputValueWithSingleLineExpression.kt");
|
||||
doExtractFunctionTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("outputValuesWithExpression.kt")
|
||||
|
||||
Reference in New Issue
Block a user