From 13776f5bbde30c27a0301afefd0705144d77c03b Mon Sep 17 00:00:00 2001 From: Alexey Sedunov Date: Tue, 7 Apr 2015 18:43:20 +0300 Subject: [PATCH] Introduce Parameter: Duplicate search & replace --- .../KotlinInplaceParameterIntroducer.kt | 35 ++++++++-- .../KotlinIntroduceParameterHandler.kt | 70 +++++++++++++------ .../classMultipleUsages1.kt | 10 +++ .../classMultipleUsages1.kt.after | 10 +++ .../classMultipleUsages2.kt | 10 +++ .../classMultipleUsages2.kt.after | 10 +++ .../classMultipleUsagesOutsideScope.kt | 10 +++ .../classMultipleUsagesOutsideScope.kt.after | 10 +++ .../classMultipleUsagesSingleReplace1.kt | 11 +++ ...classMultipleUsagesSingleReplace1.kt.after | 11 +++ .../classMultipleUsagesSingleReplace2.kt | 11 +++ ...classMultipleUsagesSingleReplace2.kt.after | 11 +++ .../classParameterUsedOutside.kt.after | 2 +- .../classUnusedParameter.kt.after | 2 +- .../classUsedParameter.kt.after | 2 +- .../defaultValueInParens.kt.after | 2 +- .../functionMultipleUnusedParameters.kt.after | 2 +- .../functionMultipleUsages.kt | 8 +++ .../functionMultipleUsages.kt.after | 8 +++ .../functionMultipleUsagesSingleReplace.kt | 9 +++ ...nctionMultipleUsagesSingleReplace.kt.after | 9 +++ .../functionUnusedParameter.kt.after | 2 +- .../functionUsedParameter.kt.after | 2 +- .../functionWithDefaultValue.kt.after | 2 +- ...ondaryConstructorWithDefaultValue.kt.after | 2 +- .../introduce/AbstractJetExtractionTest.kt | 12 +++- .../introduce/JetExtractionTestGenerated.java | 42 +++++++++++ 27 files changed, 281 insertions(+), 34 deletions(-) create mode 100644 idea/testData/refactoring/introduceParameter/classMultipleUsages1.kt create mode 100644 idea/testData/refactoring/introduceParameter/classMultipleUsages1.kt.after create mode 100644 idea/testData/refactoring/introduceParameter/classMultipleUsages2.kt create mode 100644 idea/testData/refactoring/introduceParameter/classMultipleUsages2.kt.after create mode 100644 idea/testData/refactoring/introduceParameter/classMultipleUsagesOutsideScope.kt create mode 100644 idea/testData/refactoring/introduceParameter/classMultipleUsagesOutsideScope.kt.after create mode 100644 idea/testData/refactoring/introduceParameter/classMultipleUsagesSingleReplace1.kt create mode 100644 idea/testData/refactoring/introduceParameter/classMultipleUsagesSingleReplace1.kt.after create mode 100644 idea/testData/refactoring/introduceParameter/classMultipleUsagesSingleReplace2.kt create mode 100644 idea/testData/refactoring/introduceParameter/classMultipleUsagesSingleReplace2.kt.after create mode 100644 idea/testData/refactoring/introduceParameter/functionMultipleUsages.kt create mode 100644 idea/testData/refactoring/introduceParameter/functionMultipleUsages.kt.after create mode 100644 idea/testData/refactoring/introduceParameter/functionMultipleUsagesSingleReplace.kt create mode 100644 idea/testData/refactoring/introduceParameter/functionMultipleUsagesSingleReplace.kt.after diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceParameter/KotlinInplaceParameterIntroducer.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceParameter/KotlinInplaceParameterIntroducer.kt index a67d731825b..0b4f5a62c65 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceParameter/KotlinInplaceParameterIntroducer.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceParameter/KotlinInplaceParameterIntroducer.kt @@ -36,6 +36,7 @@ import com.intellij.psi.PsiElement import com.intellij.refactoring.rename.inplace.InplaceRefactoring import com.intellij.ui.DottedBorder import com.intellij.ui.JBColor +import com.intellij.ui.NonFocusableCheckBox import org.jetbrains.kotlin.idea.JetFileType import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.refactoring.changeSignature.* @@ -49,11 +50,13 @@ import org.jetbrains.kotlin.psi.JetPsiFactory import org.jetbrains.kotlin.psi.JetPsiUtil import org.jetbrains.kotlin.psi.psiUtil.getValueParameterList import org.jetbrains.kotlin.psi.psiUtil.getValueParameters +import org.jetbrains.kotlin.psi.psiUtil.isAncestor import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.types.JetType import java.awt.BorderLayout import java.awt.Color import java.util.ArrayList +import java.util.Collections import java.util.LinkedHashSet import javax.swing.BorderFactory import javax.swing.JPanel @@ -62,21 +65,21 @@ import javax.swing.border.LineBorder import kotlin.properties.Delegates public class KotlinInplaceParameterIntroducer( - val descriptor: IntroduceParameterDescriptor, + val originalDescriptor: IntroduceParameterDescriptor, editor: Editor, project: Project ): KotlinInplaceVariableIntroducer( - descriptor.addedParameter, + originalDescriptor.addedParameter, editor, project, INTRODUCE_PARAMETER, JetExpression.EMPTY_ARRAY, null, false, - descriptor.addedParameter, + originalDescriptor.addedParameter, false, true, - descriptor.parameterType, + originalDescriptor.parameterType, false ) { companion object { @@ -112,6 +115,7 @@ public class KotlinInplaceParameterIntroducer( } } + private var descriptor = originalDescriptor private var previewer: EditorEx? = null private fun updatePreview(currentName: String?, currentType: String?) { @@ -205,6 +209,29 @@ public class KotlinInplaceParameterIntroducer( previewerPanel } + + val occurrenceCount = descriptor.occurrencesToReplace.size() + if (occurrenceCount > 1) { + addPanelControl { + val replaceAllCheckBox = NonFocusableCheckBox("Replace all occurrences ($occurrenceCount)") + replaceAllCheckBox.setSelected(true) + replaceAllCheckBox.setMnemonic('R') + replaceAllCheckBox.addActionListener { + descriptor = descriptor.copy( + occurrencesToReplace = with(originalDescriptor) { + if (replaceAllCheckBox.isSelected()) { + occurrencesToReplace + } + else { + Collections.singletonList(originalOccurrence) + } + } + ) + updatePreview(null, null) + } + replaceAllCheckBox + } + } } private var myDocumentAdapter: DocumentAdapter? = null diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceParameter/KotlinIntroduceParameterHandler.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceParameter/KotlinIntroduceParameterHandler.kt index a8307205ead..7e9a03b7cc4 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceParameter/KotlinIntroduceParameterHandler.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceParameter/KotlinIntroduceParameterHandler.kt @@ -24,6 +24,7 @@ import com.intellij.openapi.util.TextRange import com.intellij.psi.PsiDocumentManager import com.intellij.psi.PsiElement import com.intellij.psi.PsiFile +import com.intellij.psi.PsiReference import com.intellij.psi.search.LocalSearchScope import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.ClassDescriptor @@ -64,9 +65,13 @@ public data class IntroduceParameterDescriptor( val callableDescriptor: FunctionDescriptor, val addedParameter: JetParameter, val parameterType: JetType, - val parametersToRemove: List + val parametersUsages: Map>, + val occurrencesToReplace: List ) { + val originalOccurrence: JetExpression + get() = occurrencesToReplace.first { it.isAncestor(originalExpression) } val valVar: JetValVar + val parametersToRemove: List init { valVar = if (callable is JetClass) { @@ -82,9 +87,18 @@ public data class IntroduceParameterDescriptor( false } } - if (originalExpression.parents().any(modifierIsUnnecessary)) JetValVar.None else JetValVar.Val + if (occurrencesToReplace.all { it.parents().any(modifierIsUnnecessary) }) JetValVar.None else JetValVar.Val } else JetValVar.None + + val occurrenceRanges = occurrencesToReplace.map { it.getTextRange() } + parametersToRemove = parametersUsages.entrySet() + .filter { + it.value.all { paramRef -> + occurrenceRanges.any { occurrenceRange -> occurrenceRange.contains(paramRef.getElement().getTextRange()) } + } + } + .map { it.key } } } @@ -110,12 +124,15 @@ fun IntroduceParameterDescriptor.performRefactoring() { override fun performSilently(affectedFunctions: Collection): Boolean = true } if (runChangeSignature(callable.getProject(), callableDescriptor, config, callable.analyze(), callable, INTRODUCE_PARAMETER)) { - originalExpression.replace(JetPsiFactory(callable).createSimpleName(addedParameter.getName()!!)) + val paramRef = JetPsiFactory(callable).createSimpleName(addedParameter.getName()!!) + occurrencesToReplace.forEach { it.replace(paramRef) } } } } -public class KotlinIntroduceParameterHandler: KotlinIntroduceHandlerBase() { +public open class KotlinIntroduceParameterHandler: KotlinIntroduceHandlerBase() { + open fun configure(descriptor: IntroduceParameterDescriptor): IntroduceParameterDescriptor = descriptor + fun invoke(project: Project, editor: Editor, expression: JetExpression, targetParent: JetNamedDeclaration) { val psiFactory = JetPsiFactory(project) @@ -140,16 +157,28 @@ public class KotlinIntroduceParameterHandler: KotlinIntroduceHandlerBase() { val nameValidator = JetNameValidatorImpl(body, null, JetNameValidatorImpl.Target.PROPERTIES) val suggestedNames = linkedSetOf(*JetNameSuggester.suggestNames(parameterType, nameValidator, "p")) - val parametersToRemove = (parameterList?.getParameters() ?: Collections.emptyList()).filter { - if (!it.hasValOrVarNode()) { - val usages = DefaultSearchHelper() - .newRequest(UsagesSearchTarget(element = it)) - .search() - .toList() - usages.isNotEmpty() && usages.all { expression.isAncestor(it.getElement()) } - } - else false - } + val parametersUsages = targetParent.getValueParameters() + .filter { !it.hasValOrVarNode() } + .map { + it to DefaultSearchHelper() + .newRequest(UsagesSearchTarget(element = it)) + .search() + .toList() + } + .filter { it.second.isNotEmpty() } + .toMap() + + val occurrencesToReplace = expression.toRange() + .match(body, JetPsiUnifier.DEFAULT) + .map { + val matchedElement = it.range.elements.singleOrNull() + when (matchedElement) { + is JetExpression -> matchedElement + is JetStringTemplateEntryWithExpression -> matchedElement.getExpression() + else -> null + } as? JetExpression + } + .filterNotNull() project.executeCommand(INTRODUCE_PARAMETER) { val renderedType = IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.renderType(parameterType) @@ -179,12 +208,13 @@ public class KotlinIntroduceParameterHandler: KotlinIntroduceHandlerBase() { } val introduceParameterDescriptor = - IntroduceParameterDescriptor(JetPsiUtil.deparenthesize(expression)!!, - targetParent, - functionDescriptor, - addedParameter, - parameterType, - parametersToRemove) + configure(IntroduceParameterDescriptor(JetPsiUtil.deparenthesize(expression)!!, + targetParent, + functionDescriptor, + addedParameter, + parameterType, + parametersUsages, + occurrencesToReplace)) if (editor.getSettings().isVariableInplaceRenameEnabled() && !ApplicationManager.getApplication().isUnitTestMode()) { with(PsiDocumentManager.getInstance(project)) { commitDocument(editor.getDocument()) diff --git a/idea/testData/refactoring/introduceParameter/classMultipleUsages1.kt b/idea/testData/refactoring/introduceParameter/classMultipleUsages1.kt new file mode 100644 index 00000000000..1b476bf50ac --- /dev/null +++ b/idea/testData/refactoring/introduceParameter/classMultipleUsages1.kt @@ -0,0 +1,10 @@ +// TARGET: +class A(val a: Int, s: String) { + val x = a + 1 + + fun foo() = (a + 1) * 2 +} + +fun test() { + A(1, "2") +} \ No newline at end of file diff --git a/idea/testData/refactoring/introduceParameter/classMultipleUsages1.kt.after b/idea/testData/refactoring/introduceParameter/classMultipleUsages1.kt.after new file mode 100644 index 00000000000..83c86cd837e --- /dev/null +++ b/idea/testData/refactoring/introduceParameter/classMultipleUsages1.kt.after @@ -0,0 +1,10 @@ +// TARGET: +class A(val a: Int, s: String, val i: Int = a + 1) { + val x = i + + fun foo() = i * 2 +} + +fun test() { + A(1, "2") +} \ No newline at end of file diff --git a/idea/testData/refactoring/introduceParameter/classMultipleUsages2.kt b/idea/testData/refactoring/introduceParameter/classMultipleUsages2.kt new file mode 100644 index 00000000000..c258f4c70a3 --- /dev/null +++ b/idea/testData/refactoring/introduceParameter/classMultipleUsages2.kt @@ -0,0 +1,10 @@ +// TARGET: +class A(val a: Int, s: String) { + val x = a + 1 + + fun foo() = (a + 1) * 2 +} + +fun test() { + A(1, "2") +} \ No newline at end of file diff --git a/idea/testData/refactoring/introduceParameter/classMultipleUsages2.kt.after b/idea/testData/refactoring/introduceParameter/classMultipleUsages2.kt.after new file mode 100644 index 00000000000..83c86cd837e --- /dev/null +++ b/idea/testData/refactoring/introduceParameter/classMultipleUsages2.kt.after @@ -0,0 +1,10 @@ +// TARGET: +class A(val a: Int, s: String, val i: Int = a + 1) { + val x = i + + fun foo() = i * 2 +} + +fun test() { + A(1, "2") +} \ No newline at end of file diff --git a/idea/testData/refactoring/introduceParameter/classMultipleUsagesOutsideScope.kt b/idea/testData/refactoring/introduceParameter/classMultipleUsagesOutsideScope.kt new file mode 100644 index 00000000000..a1e03fd46a4 --- /dev/null +++ b/idea/testData/refactoring/introduceParameter/classMultipleUsagesOutsideScope.kt @@ -0,0 +1,10 @@ +// TARGET: +class A(val a: Int, s: String) { + val x = a + 1 + + fun foo() = (a + 1) * 2 +} + +fun test() { + val t = A(1, "2").a +} \ No newline at end of file diff --git a/idea/testData/refactoring/introduceParameter/classMultipleUsagesOutsideScope.kt.after b/idea/testData/refactoring/introduceParameter/classMultipleUsagesOutsideScope.kt.after new file mode 100644 index 00000000000..957a0306dfb --- /dev/null +++ b/idea/testData/refactoring/introduceParameter/classMultipleUsagesOutsideScope.kt.after @@ -0,0 +1,10 @@ +// TARGET: +class A(val a: Int, s: String, val i: Int = a + 1) { + val x = i + + fun foo() = i * 2 +} + +fun test() { + val t = A(1, "2").a +} \ No newline at end of file diff --git a/idea/testData/refactoring/introduceParameter/classMultipleUsagesSingleReplace1.kt b/idea/testData/refactoring/introduceParameter/classMultipleUsagesSingleReplace1.kt new file mode 100644 index 00000000000..76acbee0aa1 --- /dev/null +++ b/idea/testData/refactoring/introduceParameter/classMultipleUsagesSingleReplace1.kt @@ -0,0 +1,11 @@ +// SINGLE_REPLACE +// TARGET: +class A(val a: Int, s: String) { + val x = a + 1 + + fun foo() = (a + 1) * 2 +} + +fun test() { + A(1, "2") +} \ No newline at end of file diff --git a/idea/testData/refactoring/introduceParameter/classMultipleUsagesSingleReplace1.kt.after b/idea/testData/refactoring/introduceParameter/classMultipleUsagesSingleReplace1.kt.after new file mode 100644 index 00000000000..467b3592944 --- /dev/null +++ b/idea/testData/refactoring/introduceParameter/classMultipleUsagesSingleReplace1.kt.after @@ -0,0 +1,11 @@ +// SINGLE_REPLACE +// TARGET: +class A(val a: Int, s: String, val i: Int = a + 1) { + val x = a + 1 + + fun foo() = i * 2 +} + +fun test() { + A(1, "2") +} \ No newline at end of file diff --git a/idea/testData/refactoring/introduceParameter/classMultipleUsagesSingleReplace2.kt b/idea/testData/refactoring/introduceParameter/classMultipleUsagesSingleReplace2.kt new file mode 100644 index 00000000000..1f8e8d550ed --- /dev/null +++ b/idea/testData/refactoring/introduceParameter/classMultipleUsagesSingleReplace2.kt @@ -0,0 +1,11 @@ +// SINGLE_REPLACE +// TARGET: +class A(val a: Int, s: String) { + val x = a + 1 + + fun foo() = (a + 1) * 2 +} + +fun test() { + A(1, "2") +} \ No newline at end of file diff --git a/idea/testData/refactoring/introduceParameter/classMultipleUsagesSingleReplace2.kt.after b/idea/testData/refactoring/introduceParameter/classMultipleUsagesSingleReplace2.kt.after new file mode 100644 index 00000000000..4fb84e494f0 --- /dev/null +++ b/idea/testData/refactoring/introduceParameter/classMultipleUsagesSingleReplace2.kt.after @@ -0,0 +1,11 @@ +// SINGLE_REPLACE +// TARGET: +class A(val a: Int, s: String, i: Int = a + 1) { + val x = i + + fun foo() = (a + 1) * 2 +} + +fun test() { + A(1, "2") +} \ No newline at end of file diff --git a/idea/testData/refactoring/introduceParameter/classParameterUsedOutside.kt.after b/idea/testData/refactoring/introduceParameter/classParameterUsedOutside.kt.after index 82238f9d79b..1c62bf788dd 100644 --- a/idea/testData/refactoring/introduceParameter/classParameterUsedOutside.kt.after +++ b/idea/testData/refactoring/introduceParameter/classParameterUsedOutside.kt.after @@ -1,6 +1,6 @@ // TARGET: class A(val a: Int, s: String, val i: Int = a + 1) { - fun foo() = (i) * 2 + fun foo() = i * 2 } fun test() { diff --git a/idea/testData/refactoring/introduceParameter/classUnusedParameter.kt.after b/idea/testData/refactoring/introduceParameter/classUnusedParameter.kt.after index 2f518f190bb..25b8ed02e33 100644 --- a/idea/testData/refactoring/introduceParameter/classUnusedParameter.kt.after +++ b/idea/testData/refactoring/introduceParameter/classUnusedParameter.kt.after @@ -1,6 +1,6 @@ // TARGET: class A(val a: Int, s: String, val i: Int = a + 1) { - fun foo() = (i) * 2 + fun foo() = i * 2 } fun test() { diff --git a/idea/testData/refactoring/introduceParameter/classUsedParameter.kt.after b/idea/testData/refactoring/introduceParameter/classUsedParameter.kt.after index 8dee0121998..65170ed4837 100644 --- a/idea/testData/refactoring/introduceParameter/classUsedParameter.kt.after +++ b/idea/testData/refactoring/introduceParameter/classUsedParameter.kt.after @@ -2,7 +2,7 @@ class A(val a: Int, s: String, val i: Int = a + 1) { val x = a + 2 - fun foo() = (i) * 2 + fun foo() = i * 2 } fun test() { diff --git a/idea/testData/refactoring/introduceParameter/defaultValueInParens.kt.after b/idea/testData/refactoring/introduceParameter/defaultValueInParens.kt.after index f52bc3e9c59..1b0cb84ff63 100644 --- a/idea/testData/refactoring/introduceParameter/defaultValueInParens.kt.after +++ b/idea/testData/refactoring/introduceParameter/defaultValueInParens.kt.after @@ -1,5 +1,5 @@ fun foo(a: Int, i: Int = a + 1): Int { - val b = (i) * 2 + val b = i * 2 return a + b } diff --git a/idea/testData/refactoring/introduceParameter/functionMultipleUnusedParameters.kt.after b/idea/testData/refactoring/introduceParameter/functionMultipleUnusedParameters.kt.after index 7659c69870b..cb3367d9046 100644 --- a/idea/testData/refactoring/introduceParameter/functionMultipleUnusedParameters.kt.after +++ b/idea/testData/refactoring/introduceParameter/functionMultipleUnusedParameters.kt.after @@ -1,5 +1,5 @@ fun foo(s: String, i: Int = a + b): Int { - return (i) * 2 + return i * 2 } fun test() { diff --git a/idea/testData/refactoring/introduceParameter/functionMultipleUsages.kt b/idea/testData/refactoring/introduceParameter/functionMultipleUsages.kt new file mode 100644 index 00000000000..50927cc9697 --- /dev/null +++ b/idea/testData/refactoring/introduceParameter/functionMultipleUsages.kt @@ -0,0 +1,8 @@ +fun foo(a: Int, s: String): Int { + val t = (a + 1) * 2 + return a + 1 - t +} + +fun test() { + foo(1, "2") +} \ No newline at end of file diff --git a/idea/testData/refactoring/introduceParameter/functionMultipleUsages.kt.after b/idea/testData/refactoring/introduceParameter/functionMultipleUsages.kt.after new file mode 100644 index 00000000000..58fa970ac95 --- /dev/null +++ b/idea/testData/refactoring/introduceParameter/functionMultipleUsages.kt.after @@ -0,0 +1,8 @@ +fun foo(s: String, i: Int = a + 1): Int { + val t = i * 2 + return i - t +} + +fun test() { + foo("2") +} \ No newline at end of file diff --git a/idea/testData/refactoring/introduceParameter/functionMultipleUsagesSingleReplace.kt b/idea/testData/refactoring/introduceParameter/functionMultipleUsagesSingleReplace.kt new file mode 100644 index 00000000000..560a2084135 --- /dev/null +++ b/idea/testData/refactoring/introduceParameter/functionMultipleUsagesSingleReplace.kt @@ -0,0 +1,9 @@ +// SINGLE_REPLACE +fun foo(a: Int, s: String): Int { + val t = (a + 1) * 2 + return a + 1 - t +} + +fun test() { + foo(1, "2") +} \ No newline at end of file diff --git a/idea/testData/refactoring/introduceParameter/functionMultipleUsagesSingleReplace.kt.after b/idea/testData/refactoring/introduceParameter/functionMultipleUsagesSingleReplace.kt.after new file mode 100644 index 00000000000..80fe74a4525 --- /dev/null +++ b/idea/testData/refactoring/introduceParameter/functionMultipleUsagesSingleReplace.kt.after @@ -0,0 +1,9 @@ +// SINGLE_REPLACE +fun foo(a: Int, s: String, i: Int = a + 1): Int { + val t = (a + 1) * 2 + return i - t +} + +fun test() { + foo(1, "2") +} \ No newline at end of file diff --git a/idea/testData/refactoring/introduceParameter/functionUnusedParameter.kt.after b/idea/testData/refactoring/introduceParameter/functionUnusedParameter.kt.after index dc3fd3383dc..def86ddd096 100644 --- a/idea/testData/refactoring/introduceParameter/functionUnusedParameter.kt.after +++ b/idea/testData/refactoring/introduceParameter/functionUnusedParameter.kt.after @@ -1,5 +1,5 @@ fun foo(s: String, i: Int = a + 1): Int { - return (i) * 2 + return i * 2 } fun test() { diff --git a/idea/testData/refactoring/introduceParameter/functionUsedParameter.kt.after b/idea/testData/refactoring/introduceParameter/functionUsedParameter.kt.after index 44968b5386e..5a9d3b33c37 100644 --- a/idea/testData/refactoring/introduceParameter/functionUsedParameter.kt.after +++ b/idea/testData/refactoring/introduceParameter/functionUsedParameter.kt.after @@ -1,5 +1,5 @@ fun foo(a: Int, s: String, i: Int = a + 1): Int { - return (i) * a + return i * a } fun test() { diff --git a/idea/testData/refactoring/introduceParameter/functionWithDefaultValue.kt.after b/idea/testData/refactoring/introduceParameter/functionWithDefaultValue.kt.after index f52bc3e9c59..1b0cb84ff63 100644 --- a/idea/testData/refactoring/introduceParameter/functionWithDefaultValue.kt.after +++ b/idea/testData/refactoring/introduceParameter/functionWithDefaultValue.kt.after @@ -1,5 +1,5 @@ fun foo(a: Int, i: Int = a + 1): Int { - val b = (i) * 2 + val b = i * 2 return a + b } diff --git a/idea/testData/refactoring/introduceParameter/secondaryConstructorWithDefaultValue.kt.after b/idea/testData/refactoring/introduceParameter/secondaryConstructorWithDefaultValue.kt.after index 644cae4acff..2da0a6726d4 100644 --- a/idea/testData/refactoring/introduceParameter/secondaryConstructorWithDefaultValue.kt.after +++ b/idea/testData/refactoring/introduceParameter/secondaryConstructorWithDefaultValue.kt.after @@ -1,6 +1,6 @@ class A { constructor(a: Int, i: Int = a + 1) { - val b = (i) * 2 + val b = i * 2 val t = a + b } } diff --git a/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/AbstractJetExtractionTest.kt b/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/AbstractJetExtractionTest.kt index 1a57dfe923b..7dd4948eca4 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/AbstractJetExtractionTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/AbstractJetExtractionTest.kt @@ -33,6 +33,7 @@ import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor import org.jetbrains.kotlin.idea.refactoring.JetRefactoringUtil import org.jetbrains.kotlin.idea.refactoring.introduce.extractFunction.ExtractKotlinFunctionHandler import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.* +import org.jetbrains.kotlin.idea.refactoring.introduce.introduceParameter.IntroduceParameterDescriptor import org.jetbrains.kotlin.idea.refactoring.introduce.introduceParameter.KotlinIntroduceParameterHandler import org.jetbrains.kotlin.idea.refactoring.introduce.introduceProperty.KotlinIntroducePropertyHandler import org.jetbrains.kotlin.idea.refactoring.introduce.introduceVariable.KotlinIntroduceVariableHandler @@ -65,7 +66,16 @@ public abstract class AbstractJetExtractionTest() : JetLightCodeInsightFixtureTe protected fun doIntroduceParameterTest(path: String) { doTest(path) { file -> - with (KotlinIntroduceParameterHandler()) { + val handler = object: KotlinIntroduceParameterHandler() { + override fun configure(descriptor: IntroduceParameterDescriptor): IntroduceParameterDescriptor { + val fileText = file.getText() + val singleReplace = InTextDirectivesUtils.isDirectiveDefined(fileText, "// SINGLE_REPLACE") + return with (descriptor) { + copy(occurrencesToReplace = if (singleReplace) Collections.singletonList(originalOccurrence) else occurrencesToReplace) + } + } + } + with (handler) { val target = file.findElementByComment("// TARGET:") as? JetNamedDeclaration if (target != null) { JetRefactoringUtil.selectExpression(fixture.getEditor(), file, true) { expression -> diff --git a/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/JetExtractionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/JetExtractionTestGenerated.java index 4e7411b8657..f9ebafffc4f 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/JetExtractionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/JetExtractionTestGenerated.java @@ -2203,6 +2203,36 @@ public class JetExtractionTestGenerated extends AbstractJetExtractionTest { doIntroduceParameterTest(fileName); } + @TestMetadata("classMultipleUsages1.kt") + public void testClassMultipleUsages1() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/introduceParameter/classMultipleUsages1.kt"); + doIntroduceParameterTest(fileName); + } + + @TestMetadata("classMultipleUsages2.kt") + public void testClassMultipleUsages2() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/introduceParameter/classMultipleUsages2.kt"); + doIntroduceParameterTest(fileName); + } + + @TestMetadata("classMultipleUsagesOutsideScope.kt") + public void testClassMultipleUsagesOutsideScope() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/introduceParameter/classMultipleUsagesOutsideScope.kt"); + doIntroduceParameterTest(fileName); + } + + @TestMetadata("classMultipleUsagesSingleReplace1.kt") + public void testClassMultipleUsagesSingleReplace1() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/introduceParameter/classMultipleUsagesSingleReplace1.kt"); + doIntroduceParameterTest(fileName); + } + + @TestMetadata("classMultipleUsagesSingleReplace2.kt") + public void testClassMultipleUsagesSingleReplace2() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/introduceParameter/classMultipleUsagesSingleReplace2.kt"); + doIntroduceParameterTest(fileName); + } + @TestMetadata("classNoParams.kt") public void testClassNoParams() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/introduceParameter/classNoParams.kt"); @@ -2245,6 +2275,18 @@ public class JetExtractionTestGenerated extends AbstractJetExtractionTest { doIntroduceParameterTest(fileName); } + @TestMetadata("functionMultipleUsages.kt") + public void testFunctionMultipleUsages() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/introduceParameter/functionMultipleUsages.kt"); + doIntroduceParameterTest(fileName); + } + + @TestMetadata("functionMultipleUsagesSingleReplace.kt") + public void testFunctionMultipleUsagesSingleReplace() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/introduceParameter/functionMultipleUsagesSingleReplace.kt"); + doIntroduceParameterTest(fileName); + } + @TestMetadata("functionUnusedParameter.kt") public void testFunctionUnusedParameter() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/introduceParameter/functionUnusedParameter.kt");