Introduce Parameter/Lambda Parameter: Parenthesize binary expressions if operation reference starts with a new line

This commit is contained in:
Alexey Sedunov
2015-12-10 14:22:10 +03:00
parent 354e1dc337
commit ae2fc19fe5
22 changed files with 187 additions and 18 deletions
@@ -248,7 +248,7 @@ public class KotlinInplaceParameterIntroducer(
return descriptor.copy(
originalRange = originalRange,
occurrencesToReplace = if (replaceAll) getOccurrences().map { it.toRange() } else originalRange.singletonList(),
newArgumentValue = getExpr()!!
argumentValue = getExpr()!!
)
}
@@ -19,14 +19,11 @@ package org.jetbrains.kotlin.idea.refactoring.introduce.introduceParameter
import com.intellij.openapi.command.impl.FinishMarkAction
import com.intellij.openapi.command.impl.StartMarkAction
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.options.ConfigurationException
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement
import com.intellij.refactoring.BaseRefactoringProcessor
import com.intellij.refactoring.ui.NameSuggestionsField
import com.intellij.refactoring.ui.RefactoringDialog
import com.intellij.ui.NonFocusableCheckBox
import com.intellij.ui.TitledSeparator
import com.intellij.usageView.BaseUsageViewDescriptor
import com.intellij.usageView.UsageInfo
import org.jetbrains.kotlin.idea.KotlinFileType
@@ -38,13 +35,11 @@ import org.jetbrains.kotlin.idea.refactoring.introduce.extractFunction.ui.Kotlin
import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.*
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.AnalyzingUtils
import org.jetbrains.kotlin.types.KotlinType
import java.awt.GridBagConstraints
import java.awt.GridBagLayout
import java.awt.Insets
import java.util.Collections
import java.util.LinkedHashMap
import java.util.*
import javax.swing.JCheckBox
import javax.swing.JComponent
import javax.swing.JLabel
@@ -301,7 +296,7 @@ public class KotlinIntroduceParameterDialog private constructor(
val descriptorToRefactor = descriptor.copy(
newParameterName = chosenName,
newParameterTypeText = chosenType,
newArgumentValue = newArgumentValue,
argumentValue = newArgumentValue,
withDefaultValue = defaultValueCheckBox!!.isSelected(),
occurrencesToReplace = with(descriptor) {
if (replaceAllCheckBox?.isSelected() ?: true) {
@@ -70,13 +70,22 @@ public data class IntroduceParameterDescriptor(
val callableDescriptor: FunctionDescriptor,
val newParameterName: String,
val newParameterTypeText: String,
val newArgumentValue: KtExpression,
val argumentValue: KtExpression,
val withDefaultValue: Boolean,
val parametersUsages: MultiMap<KtElement, KtElement>,
val occurrencesToReplace: List<KotlinPsiRange>,
val parametersToRemove: List<KtElement> = getParametersToRemove(withDefaultValue, parametersUsages, occurrencesToReplace),
val occurrenceReplacer: IntroduceParameterDescriptor.(KotlinPsiRange) -> Unit = {}
) {
val newArgumentValue: KtExpression by lazy {
if (argumentValue.mustBeParenthesizedInInitializerPosition()) {
KtPsiFactory(callable).createExpressionByPattern("($0)", argumentValue)
}
else {
argumentValue
}
}
val originalOccurrence: KotlinPsiRange
get() = occurrencesToReplace.first { it.getTextRange().intersects(originalRange.getTextRange()) }
val valVar: KotlinValVar
@@ -271,6 +280,7 @@ public open class KotlinIntroduceParameterHandler(
&& !isTestMode
&& !haveLambdaArgumentsToReplace
&& expression.extractableSubstringInfo == null
&& !expression.mustBeParenthesizedInInitializerPosition()
val originalExpression = KtPsiUtil.safeDeparenthesize(expression)
val psiFactory = KtPsiFactory(project)
@@ -282,7 +292,7 @@ public open class KotlinIntroduceParameterHandler(
callableDescriptor = functionDescriptor,
newParameterName = suggestedNames.first(),
newParameterTypeText = IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.renderType(replacementType),
newArgumentValue = originalExpression,
argumentValue = originalExpression,
withDefaultValue = false,
parametersUsages = parametersUsages,
occurrencesToReplace = occurrencesToReplace,
@@ -435,7 +445,7 @@ public open class KotlinIntroduceLambdaParameterHandler(
callableDescriptor = callableDescriptor,
newParameterName = "", // to be chosen in the dialog
newParameterTypeText = "", // to be chosen in the dialog
newArgumentValue = KtPsiFactory(project).createExpression("{}"), // substituted later
argumentValue = KtPsiFactory(project).createExpression("{}"), // substituted later
withDefaultValue = false,
parametersUsages = findInternalUsagesOfParametersAndReceiver(callable, callableDescriptor),
occurrencesToReplace = listOf(originalRange),
@@ -21,6 +21,7 @@ import com.intellij.openapi.editor.ScrollType
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Key
import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiComment
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiWhiteSpace
import com.intellij.psi.util.PsiTreeUtil
@@ -132,13 +132,6 @@ object KotlinIntroduceVariableHandler : KotlinIntroduceHandlerBase() {
return result
}
private 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') }
}
private fun runRefactoring (
expression: KtExpression,
commonContainer: PsiElement,
@@ -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(i: () -> Int = {
(1
+ 2)
}) {
foo(i())
}
@@ -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(i: () -> Int = {
(1 // abc
/*def*/ + 2)
}) {
foo(i())
}
@@ -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(i: () -> Int = {
(1
+ 2 - 3)
}) {
foo(i())
}
@@ -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(i: () -> Int = {
(1 + 2
- 3)
}) {
foo(i())
}
@@ -0,0 +1,6 @@
fun foo(i: Int) { }
fun test() {
foo(<selection>1
+ 2</selection>)
}
@@ -0,0 +1,6 @@
fun foo(i: Int) { }
fun test(i: Int = (1
+ 2)) {
foo(i)
}
@@ -0,0 +1,6 @@
fun foo(i: Int) { }
fun test() {
foo(<selection>1 // abc
/*def*/ + 2</selection>)
}
@@ -0,0 +1,6 @@
fun foo(i: Int) { }
fun test(i: Int = (1 // abc
/*def*/ + 2)) {
foo(i)
}
@@ -0,0 +1,6 @@
fun foo(i: Int) { }
fun test() {
foo(<selection>1
+ 2 - 3</selection>)
}
@@ -0,0 +1,6 @@
fun foo(i: Int) { }
fun test(i: Int = (1
+ 2 - 3)) {
foo(i)
}
@@ -0,0 +1,6 @@
fun foo(i: Int) { }
fun test() {
foo(<selection>1 + 2
- 3</selection>)
}
@@ -0,0 +1,6 @@
fun foo(i: Int) { }
fun test(i: Int = (1 + 2
- 3)) {
foo(i)
}
@@ -3502,6 +3502,39 @@ public class ExtractionTestGenerated extends AbstractExtractionTest {
doIntroduceSimpleParameterTest(fileName);
}
@TestMetadata("idea/testData/refactoring/introduceParameter/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/introduceParameter/multiline"), Pattern.compile("^(.+)\\.(kt|kts)$"), true);
}
@TestMetadata("multilineBinaryExpression.kt")
public void testMultilineBinaryExpression() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/introduceParameter/multiline/multilineBinaryExpression.kt");
doIntroduceSimpleParameterTest(fileName);
}
@TestMetadata("multilineBinaryExpressionWithComments.kt")
public void testMultilineBinaryExpressionWithComments() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/introduceParameter/multiline/multilineBinaryExpressionWithComments.kt");
doIntroduceSimpleParameterTest(fileName);
}
@TestMetadata("multilineNestedBinaryExpression1.kt")
public void testMultilineNestedBinaryExpression1() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/introduceParameter/multiline/multilineNestedBinaryExpression1.kt");
doIntroduceSimpleParameterTest(fileName);
}
@TestMetadata("multilineNestedBinaryExpression2.kt")
public void testMultilineNestedBinaryExpression2() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/introduceParameter/multiline/multilineNestedBinaryExpression2.kt");
doIntroduceSimpleParameterTest(fileName);
}
}
@TestMetadata("idea/testData/refactoring/introduceParameter/script")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -3697,6 +3730,39 @@ public class ExtractionTestGenerated extends AbstractExtractionTest {
doIntroduceLambdaParameterTest(fileName);
}
@TestMetadata("idea/testData/refactoring/introduceLambdaParameter/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/introduceLambdaParameter/multiline"), Pattern.compile("^(.+)\\.(kt|kts)$"), true);
}
@TestMetadata("multilineBinaryExpression.kt")
public void testMultilineBinaryExpression() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/introduceLambdaParameter/multiline/multilineBinaryExpression.kt");
doIntroduceLambdaParameterTest(fileName);
}
@TestMetadata("multilineBinaryExpressionWithComments.kt")
public void testMultilineBinaryExpressionWithComments() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/introduceLambdaParameter/multiline/multilineBinaryExpressionWithComments.kt");
doIntroduceLambdaParameterTest(fileName);
}
@TestMetadata("multilineNestedBinaryExpression1.kt")
public void testMultilineNestedBinaryExpression1() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/introduceLambdaParameter/multiline/multilineNestedBinaryExpression1.kt");
doIntroduceLambdaParameterTest(fileName);
}
@TestMetadata("multilineNestedBinaryExpression2.kt")
public void testMultilineNestedBinaryExpression2() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/introduceLambdaParameter/multiline/multilineNestedBinaryExpression2.kt");
doIntroduceLambdaParameterTest(fileName);
}
}
@TestMetadata("idea/testData/refactoring/introduceLambdaParameter/stringTemplates")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)