Extract Function: Parenthesize binary expressions if operation reference starts with a new line

This commit is contained in:
Alexey Sedunov
2015-12-10 14:28:37 +03:00
parent 1824f10f07
commit 354e1dc337
11 changed files with 105 additions and 6 deletions
@@ -31,12 +31,9 @@ import org.jetbrains.kotlin.idea.intentions.ConvertToExpressionBodyIntention
import org.jetbrains.kotlin.idea.intentions.InfixCallToOrdinaryIntention
import org.jetbrains.kotlin.idea.intentions.OperatorToFunctionIntention
import org.jetbrains.kotlin.idea.intentions.RemoveExplicitTypeArgumentsIntention
import org.jetbrains.kotlin.idea.refactoring.introduce.extractableSubstringInfo
import org.jetbrains.kotlin.idea.refactoring.introduce.*
import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.OutputValue.*
import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.OutputValueBoxer.AsTuple
import org.jetbrains.kotlin.idea.refactoring.introduce.getPhysicalTextRange
import org.jetbrains.kotlin.idea.refactoring.introduce.replaceWith
import org.jetbrains.kotlin.idea.refactoring.introduce.substringContextOrThis
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
import org.jetbrains.kotlin.idea.util.ShortenReferences
import org.jetbrains.kotlin.idea.util.psi.patternMatching.*
@@ -466,6 +463,12 @@ fun ExtractionGeneratorConfiguration.generateDeclaration(
fun adjustDeclarationBody(declaration: KtNamedDeclaration) {
val body = declaration.getGeneratedBody()
(body.blockExpressionsOrSingle().singleOrNull() as? KtExpression)?.let {
if (it.mustBeParenthesizedInInitializerPosition()) {
it.replace(psiFactory.createExpressionByPattern("($0)", it))
}
}
val jumpValue = descriptor.controlFlow.jumpOutputValue
if (jumpValue != null) {
val replacingReturn = psiFactory.createExpression(if (jumpValue.conditional) "return true" else "return")
@@ -22,10 +22,10 @@ import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Key
import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiWhiteSpace
import com.intellij.psi.util.PsiTreeUtil
import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils
import org.jetbrains.kotlin.idea.core.refactoring.chooseContainerElementIfNecessary
import org.jetbrains.kotlin.idea.core.refactoring.removeTemplateEntryBracesIfPossible
import org.jetbrains.kotlin.idea.refactoring.KotlinRefactoringBundle
import org.jetbrains.kotlin.idea.refactoring.KotlinRefactoringUtil
import org.jetbrains.kotlin.idea.util.psi.patternMatching.KotlinPsiRange
@@ -83,7 +83,7 @@ fun selectElementsWithTargetParent(
fun selectTargetContainer(elements: List<PsiElement>) {
val physicalElements = elements.map { it.substringContextOrThis }
val parent = PsiTreeUtil.findCommonParent(physicalElements)
?: throw AssertionError("Should have at least one parent: ${physicalElements.joinToString("\n")}")
?: throw AssertionError("Should have at least one parent: ${physicalElements.joinToString("\n")}")
val containers = getContainers(physicalElements, parent)
if (containers.isEmpty()) {
@@ -196,4 +196,11 @@ fun ExtractableSubstringInfo.replaceWith(replacement: KtExpression): KtExpressio
addedRefEntry.expression!!
}
}
fun KtExpression.mustBeParenthesizedInInitializerPosition(): Boolean {
if (this !is KtBinaryExpression) return false
if (left?.mustBeParenthesizedInInitializerPosition() ?: false) return true
return PsiChildRange(left, operationReference).any { (it is PsiWhiteSpace) && it.textContains('\n') }
}
@@ -0,0 +1,6 @@
fun foo(i: Int) { }
fun test() {
foo(<selection>1
+ 2</selection>)
}
@@ -0,0 +1,8 @@
fun foo(i: Int) { }
fun test() {
foo(i())
}
private fun i() = (1
+ 2)
@@ -0,0 +1,6 @@
fun foo(i: Int) { }
fun test() {
foo(<selection>1 // abc
/*def*/ + 2</selection>)
}
@@ -0,0 +1,8 @@
fun foo(i: Int) { }
fun test() {
foo(i())
}
private fun i() = (1 // abc
/*def*/ + 2)
@@ -0,0 +1,6 @@
fun foo(i: Int) { }
fun test() {
foo(<selection>1
+ 2 - 3</selection>)
}
@@ -0,0 +1,8 @@
fun foo(i: Int) { }
fun test() {
foo(i())
}
private fun i() = (1
+ 2 - 3)
@@ -0,0 +1,6 @@
fun foo(i: Int) { }
fun test() {
foo(<selection>1 + 2
- 3</selection>)
}
@@ -0,0 +1,8 @@
fun foo(i: Int) { }
fun test() {
foo(i())
}
private fun i() = (1 + 2
- 3)
@@ -2038,6 +2038,39 @@ public class ExtractionTestGenerated extends AbstractExtractionTest {
}
}
@TestMetadata("idea/testData/refactoring/extractFunction/multiline")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Multiline extends AbstractExtractionTest {
public void testAllFilesPresentInMultiline() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/refactoring/extractFunction/multiline"), Pattern.compile("^(.+)\\.(kt|kts)$"), true);
}
@TestMetadata("multilineBinaryExpression.kt")
public void testMultilineBinaryExpression() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/extractFunction/multiline/multilineBinaryExpression.kt");
doExtractFunctionTest(fileName);
}
@TestMetadata("multilineBinaryExpressionWithComments.kt")
public void testMultilineBinaryExpressionWithComments() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/extractFunction/multiline/multilineBinaryExpressionWithComments.kt");
doExtractFunctionTest(fileName);
}
@TestMetadata("multilineNestedBinaryExpression1.kt")
public void testMultilineNestedBinaryExpression1() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/extractFunction/multiline/multilineNestedBinaryExpression1.kt");
doExtractFunctionTest(fileName);
}
@TestMetadata("multilineNestedBinaryExpression2.kt")
public void testMultilineNestedBinaryExpression2() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/extractFunction/multiline/multilineNestedBinaryExpression2.kt");
doExtractFunctionTest(fileName);
}
}
@TestMetadata("idea/testData/refactoring/extractFunction/parameters")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)