Introduce Parameter: Initial support
This commit is contained in:
@@ -676,6 +676,7 @@ fun main(args: Array<String>) {
|
|||||||
model("refactoring/introduceVariable", extension = "kt", testMethod = "doIntroduceVariableTest")
|
model("refactoring/introduceVariable", extension = "kt", testMethod = "doIntroduceVariableTest")
|
||||||
model("refactoring/extractFunction", extension = "kt", testMethod = "doExtractFunctionTest")
|
model("refactoring/extractFunction", extension = "kt", testMethod = "doExtractFunctionTest")
|
||||||
model("refactoring/introduceProperty", extension = "kt", testMethod = "doIntroducePropertyTest")
|
model("refactoring/introduceProperty", extension = "kt", testMethod = "doIntroducePropertyTest")
|
||||||
|
model("refactoring/introduceParameter", extension = "kt", testMethod = "doIntroduceParameterTest")
|
||||||
}
|
}
|
||||||
|
|
||||||
testClass(javaClass<AbstractSelectExpressionForDebuggerTest>()) {
|
testClass(javaClass<AbstractSelectExpressionForDebuggerTest>()) {
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ public abstract class CallableRefactoring<T: CallableDescriptor>(
|
|||||||
|
|
||||||
protected abstract fun performRefactoring(descriptorsForChange: Collection<CallableDescriptor>)
|
protected abstract fun performRefactoring(descriptorsForChange: Collection<CallableDescriptor>)
|
||||||
|
|
||||||
public fun run() {
|
public fun run(): Boolean {
|
||||||
fun buttonPressed(code: Int, dialogButtons: List<String>, button: String): Boolean {
|
fun buttonPressed(code: Int, dialogButtons: List<String>, button: String): Boolean {
|
||||||
return code == dialogButtons indexOf button && button in dialogButtons
|
return code == dialogButtons indexOf button && button in dialogButtons
|
||||||
}
|
}
|
||||||
@@ -134,7 +134,7 @@ public abstract class CallableRefactoring<T: CallableDescriptor>(
|
|||||||
|
|
||||||
if (kind == SYNTHESIZED) {
|
if (kind == SYNTHESIZED) {
|
||||||
LOG.error("Change signature refactoring should not be called for synthesized member " + callableDescriptor)
|
LOG.error("Change signature refactoring should not be called for synthesized member " + callableDescriptor)
|
||||||
return
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
val closestModifiableDescriptors = getClosestModifiableDescriptors()
|
val closestModifiableDescriptors = getClosestModifiableDescriptors()
|
||||||
@@ -144,12 +144,12 @@ public abstract class CallableRefactoring<T: CallableDescriptor>(
|
|||||||
?: Collections.singletonList(callableDescriptor)
|
?: Collections.singletonList(callableDescriptor)
|
||||||
if (ApplicationManager.getApplication()!!.isUnitTestMode()) {
|
if (ApplicationManager.getApplication()!!.isUnitTestMode()) {
|
||||||
performRefactoring(deepestSuperDeclarations)
|
performRefactoring(deepestSuperDeclarations)
|
||||||
return
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (closestModifiableDescriptors.size() == 1 && deepestSuperDeclarations == closestModifiableDescriptors) {
|
if (closestModifiableDescriptors.size() == 1 && deepestSuperDeclarations == closestModifiableDescriptors) {
|
||||||
performRefactoring(closestModifiableDescriptors)
|
performRefactoring(closestModifiableDescriptors)
|
||||||
return
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
val isSingleFunctionSelected = closestModifiableDescriptors.size() == 1
|
val isSingleFunctionSelected = closestModifiableDescriptors.size() == 1
|
||||||
@@ -165,8 +165,10 @@ public abstract class CallableRefactoring<T: CallableDescriptor>(
|
|||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
//do nothing
|
//do nothing
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ cannot.refactor.not.expression.to.extract=Cannot find an expression to extract
|
|||||||
expressions.title=Expressions
|
expressions.title=Expressions
|
||||||
introduce.variable=Introduce Variable
|
introduce.variable=Introduce Variable
|
||||||
introduce.property=Introduce Property
|
introduce.property=Introduce Property
|
||||||
|
introduce.parameter=Introduce Parameter
|
||||||
cannot.refactor.no.container=Cannot refactor in this place
|
cannot.refactor.no.container=Cannot refactor in this place
|
||||||
cannot.refactor.no.expression=Cannot perform refactoring without an expression
|
cannot.refactor.no.expression=Cannot perform refactoring without an expression
|
||||||
cannot.refactor.expression.has.unit.type=Cannot introduce expression of unit type
|
cannot.refactor.expression.has.unit.type=Cannot introduce expression of unit type
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetChangeSignatureHandler;
|
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetChangeSignatureHandler;
|
||||||
import org.jetbrains.kotlin.idea.refactoring.introduce.extractFunction.ExtractKotlinFunctionHandler;
|
import org.jetbrains.kotlin.idea.refactoring.introduce.extractFunction.ExtractKotlinFunctionHandler;
|
||||||
|
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.introduceProperty.KotlinIntroducePropertyHandler;
|
||||||
import org.jetbrains.kotlin.idea.refactoring.introduce.introduceVariable.KotlinIntroduceVariableHandler;
|
import org.jetbrains.kotlin.idea.refactoring.introduce.introduceVariable.KotlinIntroduceVariableHandler;
|
||||||
import org.jetbrains.kotlin.idea.refactoring.safeDelete.SafeDeletePackage;
|
import org.jetbrains.kotlin.idea.refactoring.safeDelete.SafeDeletePackage;
|
||||||
@@ -40,6 +41,12 @@ public class JetRefactoringSupportProvider extends RefactoringSupportProvider {
|
|||||||
return new KotlinIntroduceVariableHandler();
|
return new KotlinIntroduceVariableHandler();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public RefactoringActionHandler getIntroduceParameterHandler() {
|
||||||
|
return new KotlinIntroduceParameterHandler();
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public RefactoringActionHandler getIntroducePropertyHandler() {
|
public RefactoringActionHandler getIntroducePropertyHandler() {
|
||||||
return new KotlinIntroducePropertyHandler();
|
return new KotlinIntroducePropertyHandler();
|
||||||
|
|||||||
+2
-2
@@ -56,8 +56,8 @@ public fun runChangeSignature(project: Project,
|
|||||||
configuration: JetChangeSignatureConfiguration,
|
configuration: JetChangeSignatureConfiguration,
|
||||||
bindingContext: BindingContext,
|
bindingContext: BindingContext,
|
||||||
defaultValueContext: PsiElement,
|
defaultValueContext: PsiElement,
|
||||||
commandName: String? = null) {
|
commandName: String? = null): Boolean {
|
||||||
JetChangeSignature(project, functionDescriptor, configuration, bindingContext, defaultValueContext, commandName).run()
|
return JetChangeSignature(project, functionDescriptor, configuration, bindingContext, defaultValueContext, commandName).run()
|
||||||
}
|
}
|
||||||
|
|
||||||
public class JetChangeSignature(project: Project,
|
public class JetChangeSignature(project: Project,
|
||||||
|
|||||||
+4
@@ -33,6 +33,10 @@ public class JetMutableMethodDescriptor(val original: JetMethodDescriptor): JetM
|
|||||||
parameters.add(parameter)
|
parameters.add(parameter)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public fun setParameter(index: Int, parameter: JetParameterInfo) {
|
||||||
|
parameters[index] = parameter
|
||||||
|
}
|
||||||
|
|
||||||
public fun removeParameter(index: Int) {
|
public fun removeParameter(index: Int) {
|
||||||
parameters.remove(index)
|
parameters.remove(index)
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-2
@@ -156,8 +156,15 @@ public class JetFunctionCallUsage extends JetUsageInfo<JetCallElement> {
|
|||||||
? psiFactory.createArgument(oldArgument.getArgumentExpression())
|
? psiFactory.createArgument(oldArgument.getArgumentExpression())
|
||||||
: oldArgument.asElement());
|
: oldArgument.asElement());
|
||||||
}
|
}
|
||||||
else if (parameterInfo.getDefaultValueForCall().isEmpty())
|
// TODO: process default arguments in the middle
|
||||||
newArgument.delete();
|
else if (parameterInfo.getDefaultValueForCall().isEmpty()) {
|
||||||
|
if (parameterInfo.getDefaultValueForParameter() != null) {
|
||||||
|
JetPsiUtil.deleteElementWithDelimiters(newArgument);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
newArgument.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<JetFunctionLiteralArgument> lambdaArguments = element.getFunctionLiteralArguments();
|
List<JetFunctionLiteralArgument> lambdaArguments = element.getFunctionLiteralArguments();
|
||||||
|
|||||||
+239
@@ -0,0 +1,239 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2015 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.idea.refactoring.introduce.introduceParameter
|
||||||
|
|
||||||
|
import com.intellij.codeInsight.template.impl.TemplateManagerImpl
|
||||||
|
import com.intellij.openapi.diagnostic.Logger
|
||||||
|
import com.intellij.openapi.editor.Editor
|
||||||
|
import com.intellij.openapi.editor.EditorFactory
|
||||||
|
import com.intellij.openapi.editor.colors.EditorColors
|
||||||
|
import com.intellij.openapi.editor.event.DocumentAdapter
|
||||||
|
import com.intellij.openapi.editor.event.DocumentEvent
|
||||||
|
import com.intellij.openapi.editor.ex.EditorEx
|
||||||
|
import com.intellij.openapi.editor.impl.DocumentMarkupModel
|
||||||
|
import com.intellij.openapi.editor.markup.EffectType
|
||||||
|
import com.intellij.openapi.editor.markup.HighlighterTargetArea
|
||||||
|
import com.intellij.openapi.editor.markup.MarkupModel
|
||||||
|
import com.intellij.openapi.editor.markup.TextAttributes
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.openapi.util.TextRange
|
||||||
|
import com.intellij.psi.PsiDocumentManager
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.refactoring.rename.inplace.InplaceRefactoring
|
||||||
|
import com.intellij.ui.DottedBorder
|
||||||
|
import com.intellij.ui.JBColor
|
||||||
|
import org.jetbrains.kotlin.idea.JetFileType
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||||
|
import org.jetbrains.kotlin.idea.refactoring.changeSignature.*
|
||||||
|
import org.jetbrains.kotlin.idea.refactoring.introduce.introduceVariable.KotlinInplaceVariableIntroducer
|
||||||
|
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
||||||
|
import org.jetbrains.kotlin.idea.util.application.executeCommand
|
||||||
|
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||||
|
import org.jetbrains.kotlin.psi.JetExpression
|
||||||
|
import org.jetbrains.kotlin.psi.JetParameter
|
||||||
|
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.resolve.BindingContext
|
||||||
|
import org.jetbrains.kotlin.types.JetType
|
||||||
|
import java.awt.BorderLayout
|
||||||
|
import java.awt.Color
|
||||||
|
import java.util.ArrayList
|
||||||
|
import java.util.LinkedHashSet
|
||||||
|
import javax.swing.BorderFactory
|
||||||
|
import javax.swing.JPanel
|
||||||
|
import javax.swing.border.EmptyBorder
|
||||||
|
import javax.swing.border.LineBorder
|
||||||
|
import kotlin.properties.Delegates
|
||||||
|
|
||||||
|
public class KotlinInplaceParameterIntroducer(
|
||||||
|
val descriptor: IntroduceParameterDescriptor,
|
||||||
|
editor: Editor,
|
||||||
|
project: Project
|
||||||
|
): KotlinInplaceVariableIntroducer<JetParameter>(
|
||||||
|
descriptor.addedParameter,
|
||||||
|
editor,
|
||||||
|
project,
|
||||||
|
INTRODUCE_PARAMETER,
|
||||||
|
JetExpression.EMPTY_ARRAY,
|
||||||
|
null,
|
||||||
|
false,
|
||||||
|
descriptor.addedParameter,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
descriptor.parameterType,
|
||||||
|
false
|
||||||
|
) {
|
||||||
|
companion object {
|
||||||
|
private val LOG = Logger.getInstance(javaClass<KotlinInplaceParameterIntroducer>())
|
||||||
|
}
|
||||||
|
|
||||||
|
object PreviewDecorator {
|
||||||
|
protected val textAttributes: TextAttributes = with(TextAttributes()) {
|
||||||
|
setEffectType(EffectType.ROUNDED_BOX)
|
||||||
|
setEffectColor(JBColor.RED)
|
||||||
|
this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun applyToRange(range: TextRange, markupModel: MarkupModel) {
|
||||||
|
markupModel.addRangeHighlighter(range.getStartOffset(),
|
||||||
|
range.getEndOffset(),
|
||||||
|
0,
|
||||||
|
textAttributes,
|
||||||
|
HighlighterTargetArea.EXACT_RANGE
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var previewer: EditorEx? = null
|
||||||
|
|
||||||
|
private fun updatePreview(currentName: String?, currentType: String?) {
|
||||||
|
with (descriptor) {
|
||||||
|
var addedRange: TextRange? = null
|
||||||
|
val builder = StringBuilder()
|
||||||
|
|
||||||
|
builder.append(callable.getName())
|
||||||
|
|
||||||
|
val parameters = callable.getValueParameters()
|
||||||
|
builder.append("(")
|
||||||
|
for (i in parameters.indices) {
|
||||||
|
val parameter = parameters[i]
|
||||||
|
|
||||||
|
val parameterText = if (parameter == addedParameter){
|
||||||
|
val parameterName = currentName ?: parameter.getName()
|
||||||
|
val parameterType = currentType ?: parameter.getTypeReference()!!.getText()
|
||||||
|
val modifier = if (valVar != JetValVar.None) "${valVar.name} " else ""
|
||||||
|
|
||||||
|
"$modifier$parameterName: $parameterType"
|
||||||
|
}
|
||||||
|
else parameter.getText()
|
||||||
|
|
||||||
|
builder.append(parameterText)
|
||||||
|
|
||||||
|
val range = TextRange(builder.length() - parameterText.length(), builder.length())
|
||||||
|
if (parameter == addedParameter) {
|
||||||
|
addedRange = range
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i < parameters.lastIndex) {
|
||||||
|
builder.append(", ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
builder.append(")")
|
||||||
|
|
||||||
|
if (addedRange == null) {
|
||||||
|
LOG.error("Added parameter not found: ${JetPsiUtil.getElementTextWithContext(callable)}")
|
||||||
|
}
|
||||||
|
|
||||||
|
val document = previewer!!.getDocument()
|
||||||
|
runWriteAction { document.setText(builder.toString()) }
|
||||||
|
|
||||||
|
val markupModel = DocumentMarkupModel.forDocument(document, myProject, true)
|
||||||
|
markupModel.removeAllHighlighters()
|
||||||
|
addedRange?.let { PreviewDecorator.applyToRange(it, markupModel) }
|
||||||
|
}
|
||||||
|
revalidate()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun initPanelControls() {
|
||||||
|
addPanelControl {
|
||||||
|
val previewer = EditorFactory.getInstance().createEditor(EditorFactory.getInstance().createDocument(""),
|
||||||
|
myProject,
|
||||||
|
JetFileType.INSTANCE,
|
||||||
|
true) as EditorEx
|
||||||
|
this.previewer = previewer
|
||||||
|
previewer.setOneLineMode(true)
|
||||||
|
|
||||||
|
with(previewer.getSettings()) {
|
||||||
|
setAdditionalLinesCount(0)
|
||||||
|
setAdditionalColumnsCount(1)
|
||||||
|
setRightMarginShown(false)
|
||||||
|
setFoldingOutlineShown(false)
|
||||||
|
setLineNumbersShown(false)
|
||||||
|
setLineMarkerAreaShown(false)
|
||||||
|
setIndentGuidesShown(false)
|
||||||
|
setVirtualSpace(false)
|
||||||
|
setLineCursorWidth(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
previewer.setHorizontalScrollbarVisible(false)
|
||||||
|
previewer.setVerticalScrollbarVisible(false)
|
||||||
|
previewer.setCaretEnabled(false)
|
||||||
|
|
||||||
|
|
||||||
|
val bg = previewer.getColorsScheme().getColor(EditorColors.CARET_ROW_COLOR)
|
||||||
|
previewer.setBackgroundColor(bg)
|
||||||
|
previewer.setBorder(BorderFactory.createCompoundBorder(DottedBorder(Color.gray), LineBorder(bg, 2)))
|
||||||
|
|
||||||
|
updatePreview(null, null)
|
||||||
|
|
||||||
|
val previewerPanel = JPanel(BorderLayout())
|
||||||
|
previewerPanel.add(previewer.getComponent(), BorderLayout.CENTER)
|
||||||
|
previewerPanel.setBorder(EmptyBorder(2, 2, 6, 2))
|
||||||
|
|
||||||
|
previewerPanel
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var myDocumentAdapter: DocumentAdapter? = null
|
||||||
|
|
||||||
|
fun startRefactoring(suggestedNames: LinkedHashSet<String>): Boolean {
|
||||||
|
if (!performInplaceRefactoring(suggestedNames)) return false
|
||||||
|
|
||||||
|
myDocumentAdapter = object : DocumentAdapter() {
|
||||||
|
override fun documentChanged(e: DocumentEvent?) {
|
||||||
|
if (previewer == null) return
|
||||||
|
val templateState = TemplateManagerImpl.getTemplateState(myEditor)
|
||||||
|
if (templateState != null) {
|
||||||
|
val name = templateState.getVariableValue(KotlinInplaceVariableIntroducer.PRIMARY_VARIABLE_NAME)?.getText()
|
||||||
|
val typeRefText = templateState.getVariableValue(KotlinInplaceVariableIntroducer.TYPE_REFERENCE_VARIABLE_NAME)?.getText()
|
||||||
|
updatePreview(name, typeRefText)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
myEditor.getDocument().addDocumentListener(myDocumentAdapter!!)
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun finish(success: Boolean) {
|
||||||
|
super.finish(success)
|
||||||
|
myDocumentAdapter?.let { myEditor.getDocument().removeDocumentListener(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun checkLocalScope(): PsiElement? {
|
||||||
|
return descriptor.callable
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun performRefactoring(): Boolean {
|
||||||
|
descriptor.performRefactoring()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun performCleanup() {
|
||||||
|
runWriteAction { JetPsiUtil.deleteElementWithDelimiters(descriptor.addedParameter) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun releaseResources() {
|
||||||
|
super.releaseResources()
|
||||||
|
previewer?.let {
|
||||||
|
EditorFactory.getInstance().releaseEditor(it)
|
||||||
|
previewer = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+211
@@ -0,0 +1,211 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2015 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.idea.refactoring.introduce.introduceParameter
|
||||||
|
|
||||||
|
import com.intellij.openapi.actionSystem.DataContext
|
||||||
|
import com.intellij.openapi.application.ApplicationManager
|
||||||
|
import com.intellij.openapi.editor.Editor
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.openapi.util.TextRange
|
||||||
|
import com.intellij.psi.PsiDocumentManager
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.psi.PsiFile
|
||||||
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||||
|
import org.jetbrains.kotlin.idea.core.refactoring.JetNameSuggester
|
||||||
|
import org.jetbrains.kotlin.idea.refactoring.JetNameValidatorImpl
|
||||||
|
import org.jetbrains.kotlin.idea.refactoring.JetRefactoringBundle
|
||||||
|
import org.jetbrains.kotlin.idea.refactoring.changeSignature.*
|
||||||
|
import org.jetbrains.kotlin.idea.refactoring.introduce.KotlinIntroduceHandlerBase
|
||||||
|
import org.jetbrains.kotlin.idea.refactoring.introduce.selectElementsWithTargetParent
|
||||||
|
import org.jetbrains.kotlin.idea.refactoring.introduce.showErrorHintByKey
|
||||||
|
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
||||||
|
import org.jetbrains.kotlin.idea.util.application.executeCommand
|
||||||
|
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||||
|
import org.jetbrains.kotlin.idea.util.approximateWithResolvableType
|
||||||
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.getParentOfTypeAndBranch
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.getValueParameterList
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.parents
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.JetScopeUtils
|
||||||
|
import org.jetbrains.kotlin.types.JetType
|
||||||
|
import kotlin.test.fail
|
||||||
|
|
||||||
|
public data class IntroduceParameterDescriptor(
|
||||||
|
val originalExpression: JetExpression,
|
||||||
|
val callable: JetNamedDeclaration,
|
||||||
|
val callableDescriptor: FunctionDescriptor,
|
||||||
|
val addedParameter: JetParameter,
|
||||||
|
val parameterType: JetType
|
||||||
|
) {
|
||||||
|
val valVar: JetValVar
|
||||||
|
|
||||||
|
init {
|
||||||
|
valVar = if (callable is JetClass) {
|
||||||
|
val modifierIsUnnecessary: (PsiElement) -> Boolean = {
|
||||||
|
when {
|
||||||
|
it.getParent() != callable.getBody() ->
|
||||||
|
false
|
||||||
|
it is JetClassInitializer ->
|
||||||
|
true
|
||||||
|
it is JetProperty && it.getInitializer()?.getTextRange()?.intersects(originalExpression.getTextRange()) ?: false ->
|
||||||
|
true
|
||||||
|
else ->
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (originalExpression.parents().any(modifierIsUnnecessary)) JetValVar.None else JetValVar.Val
|
||||||
|
}
|
||||||
|
else JetValVar.None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun IntroduceParameterDescriptor.performRefactoring() {
|
||||||
|
runWriteAction {
|
||||||
|
JetPsiUtil.deleteElementWithDelimiters(addedParameter)
|
||||||
|
|
||||||
|
val config = object: JetChangeSignatureConfiguration {
|
||||||
|
override fun configure(originalDescriptor: JetMethodDescriptor, bindingContext: BindingContext): JetMethodDescriptor {
|
||||||
|
return originalDescriptor.modify {
|
||||||
|
val parameterInfo = JetParameterInfo(name = addedParameter.getName()!!,
|
||||||
|
type = parameterType,
|
||||||
|
defaultValueForParameter = JetPsiUtil.deparenthesize(originalExpression),
|
||||||
|
valOrVar = valVar)
|
||||||
|
parameterInfo.currentTypeText = addedParameter.getTypeReference()?.getText() ?: "Any"
|
||||||
|
addParameter(parameterInfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun performSilently(affectedFunctions: Collection<PsiElement>): Boolean = true
|
||||||
|
}
|
||||||
|
if (runChangeSignature(callable.getProject(), callableDescriptor, config, callable.analyze(), callable, INTRODUCE_PARAMETER)) {
|
||||||
|
originalExpression.replace(JetPsiFactory(callable).createSimpleName(addedParameter.getName()!!))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class KotlinIntroduceParameterHandler: KotlinIntroduceHandlerBase() {
|
||||||
|
public fun invoke(project: Project, editor: Editor, expression: JetExpression, targetParent: JetNamedDeclaration) {
|
||||||
|
val psiFactory = JetPsiFactory(project)
|
||||||
|
|
||||||
|
val parameterList = targetParent.getValueParameterList()
|
||||||
|
|
||||||
|
val context = expression.analyze()
|
||||||
|
val descriptor = context[BindingContext.DECLARATION_TO_DESCRIPTOR, targetParent]
|
||||||
|
val functionDescriptor: FunctionDescriptor =
|
||||||
|
when (descriptor) {
|
||||||
|
is FunctionDescriptor -> descriptor : FunctionDescriptor
|
||||||
|
is ClassDescriptor -> descriptor.getUnsubstitutedPrimaryConstructor()
|
||||||
|
else -> null
|
||||||
|
} ?: throw AssertionError("Unexpected element type: ${JetPsiUtil.getElementTextWithContext(targetParent)}")
|
||||||
|
val expressionType = context[BindingContext.EXPRESSION_TYPE, expression] ?: KotlinBuiltIns.getInstance().getAnyType()
|
||||||
|
val parameterType = expressionType.approximateWithResolvableType(JetScopeUtils.getResolutionScope(targetParent, context), false)
|
||||||
|
|
||||||
|
val validatorContainer =
|
||||||
|
when (targetParent) {
|
||||||
|
is JetFunction -> targetParent.getBodyExpression()
|
||||||
|
is JetClass -> targetParent.getBody()
|
||||||
|
else -> null
|
||||||
|
} ?: throw AssertionError("Body element is not found: ${JetPsiUtil.getElementTextWithContext(targetParent)}")
|
||||||
|
val nameValidator = JetNameValidatorImpl(validatorContainer, null, JetNameValidatorImpl.Target.PROPERTIES)
|
||||||
|
val suggestedNames = linkedSetOf(*JetNameSuggester.suggestNames(parameterType, nameValidator, "p"))
|
||||||
|
|
||||||
|
project.executeCommand(INTRODUCE_PARAMETER) {
|
||||||
|
val renderedType = IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.renderType(parameterType)
|
||||||
|
val newParameter = psiFactory.createParameter("${suggestedNames.first()}: $renderedType")
|
||||||
|
|
||||||
|
val addedParameter = runWriteAction {
|
||||||
|
val newParameterList =
|
||||||
|
if (parameterList == null) {
|
||||||
|
val klass = targetParent as? JetClass
|
||||||
|
val anchor = klass?.getTypeParameterList() ?: klass?.getNameIdentifier()
|
||||||
|
assert(anchor != null, "Invalid declaration: ${JetPsiUtil.getElementTextWithContext(targetParent)}")
|
||||||
|
|
||||||
|
val constructor = targetParent.addAfter(psiFactory.createPrimaryConstructor(), anchor) as JetPrimaryConstructor
|
||||||
|
constructor.getValueParameterList()!!
|
||||||
|
}
|
||||||
|
else parameterList
|
||||||
|
|
||||||
|
val lastParameter = newParameterList.getChildren().lastOrNull { it is JetParameter } as? JetParameter
|
||||||
|
if (lastParameter != null) {
|
||||||
|
val comma = newParameterList.addAfter(psiFactory.createComma(), lastParameter)
|
||||||
|
newParameterList.addAfter(newParameter, comma) as JetParameter
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
val singleParameterList = psiFactory.createParameterList("(${newParameter.getText()})")
|
||||||
|
(newParameterList.replace(singleParameterList) as JetParameterList).getParameters().first()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val introduceParameterDescriptor =
|
||||||
|
IntroduceParameterDescriptor(JetPsiUtil.deparenthesize(expression)!!,
|
||||||
|
targetParent,
|
||||||
|
functionDescriptor,
|
||||||
|
addedParameter,
|
||||||
|
parameterType)
|
||||||
|
if (editor.getSettings().isVariableInplaceRenameEnabled() && !ApplicationManager.getApplication().isUnitTestMode()) {
|
||||||
|
with(PsiDocumentManager.getInstance(project)) {
|
||||||
|
commitDocument(editor.getDocument())
|
||||||
|
doPostponedOperationsAndUnblockDocument(editor.getDocument())
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!KotlinInplaceParameterIntroducer(introduceParameterDescriptor, editor, project).startRefactoring(suggestedNames)) {
|
||||||
|
introduceParameterDescriptor.performRefactoring()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
introduceParameterDescriptor.performRefactoring()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun invoke(project: Project, editor: Editor, file: PsiFile, dataContext: DataContext?) {
|
||||||
|
if (file !is JetFile) return
|
||||||
|
selectElementsWithTargetParent(
|
||||||
|
operationName = INTRODUCE_PARAMETER,
|
||||||
|
editor = editor,
|
||||||
|
file = file,
|
||||||
|
getContainers = { elements, parent ->
|
||||||
|
parent.parents(withItself = false)
|
||||||
|
.filter {
|
||||||
|
((it is JetClass && !it.isTrait() && it !is JetEnumEntry) || it is JetNamedFunction || it is JetSecondaryConstructor) &&
|
||||||
|
((it as JetNamedDeclaration).getValueParameterList() != null || it.getNameIdentifier() != null)
|
||||||
|
}
|
||||||
|
.toList()
|
||||||
|
},
|
||||||
|
continuation = { elements, targetParent ->
|
||||||
|
val expression = ((elements.singleOrNull() as? JetBlockExpression)?.getStatements() ?: elements).singleOrNull()
|
||||||
|
if (expression is JetExpression) {
|
||||||
|
invoke(project, editor, expression, targetParent as JetNamedDeclaration)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
showErrorHintByKey(project, editor, "cannot.refactor.no.expression", INTRODUCE_PARAMETER)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun invoke(project: Project, elements: Array<out PsiElement>, dataContext: DataContext?) {
|
||||||
|
fail("$INTRODUCE_PARAMETER can only be invoked from editor")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val INTRODUCE_PARAMETER: String = JetRefactoringBundle.message("introduce.property")
|
||||||
+16
-1
@@ -26,6 +26,7 @@ import com.intellij.openapi.command.WriteCommandAction;
|
|||||||
import com.intellij.openapi.editor.Editor;
|
import com.intellij.openapi.editor.Editor;
|
||||||
import com.intellij.openapi.editor.markup.RangeHighlighter;
|
import com.intellij.openapi.editor.markup.RangeHighlighter;
|
||||||
import com.intellij.openapi.project.Project;
|
import com.intellij.openapi.project.Project;
|
||||||
|
import com.intellij.openapi.ui.popup.Balloon;
|
||||||
import com.intellij.openapi.util.Pair;
|
import com.intellij.openapi.util.Pair;
|
||||||
import com.intellij.openapi.util.Pass;
|
import com.intellij.openapi.util.Pass;
|
||||||
import com.intellij.openapi.util.Ref;
|
import com.intellij.openapi.util.Ref;
|
||||||
@@ -35,6 +36,7 @@ import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
|
|||||||
import com.intellij.psi.search.SearchScope;
|
import com.intellij.psi.search.SearchScope;
|
||||||
import com.intellij.refactoring.introduce.inplace.InplaceVariableIntroducer;
|
import com.intellij.refactoring.introduce.inplace.InplaceVariableIntroducer;
|
||||||
import com.intellij.ui.NonFocusableCheckBox;
|
import com.intellij.ui.NonFocusableCheckBox;
|
||||||
|
import com.intellij.util.ui.PositionTracker;
|
||||||
import kotlin.Function0;
|
import kotlin.Function0;
|
||||||
import kotlin.Function1;
|
import kotlin.Function1;
|
||||||
import kotlin.KotlinPackage;
|
import kotlin.KotlinPackage;
|
||||||
@@ -56,6 +58,9 @@ import java.util.LinkedHashSet;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class KotlinInplaceVariableIntroducer<D extends JetCallableDeclaration> extends InplaceVariableIntroducer<JetExpression> {
|
public class KotlinInplaceVariableIntroducer<D extends JetCallableDeclaration> extends InplaceVariableIntroducer<JetExpression> {
|
||||||
|
public static final String TYPE_REFERENCE_VARIABLE_NAME = "TypeReferenceVariable";
|
||||||
|
public static final String PRIMARY_VARIABLE_NAME = "PrimaryVariable";
|
||||||
|
|
||||||
private static final Function0<Boolean> TRUE = new Function0<Boolean>() {
|
private static final Function0<Boolean> TRUE = new Function0<Boolean>() {
|
||||||
@Override
|
@Override
|
||||||
public Boolean invoke() {
|
public Boolean invoke() {
|
||||||
@@ -329,10 +334,20 @@ public class KotlinInplaceVariableIntroducer<D extends JetCallableDeclaration> e
|
|||||||
return nameSuggestions;
|
return nameSuggestions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void revalidate() {
|
||||||
|
getContentPanel().revalidate();
|
||||||
|
if (myTarget != null) {
|
||||||
|
myBalloon.revalidate(new PositionTracker.Static<Balloon>(myTarget));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected void addTypeReferenceVariable(TemplateBuilderImpl builder) {
|
protected void addTypeReferenceVariable(TemplateBuilderImpl builder) {
|
||||||
JetTypeReference typeReference = myDeclaration.getTypeReference();
|
JetTypeReference typeReference = myDeclaration.getTypeReference();
|
||||||
if (typeReference != null) {
|
if (typeReference != null) {
|
||||||
builder.replaceElement(typeReference, SpecifyTypeExplicitlyAction.createTypeExpressionForTemplate(myExprType));
|
builder.replaceElement(typeReference,
|
||||||
|
TYPE_REFERENCE_VARIABLE_NAME,
|
||||||
|
SpecifyTypeExplicitlyAction.createTypeExpressionForTemplate(myExprType),
|
||||||
|
false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
class A(a: Int) {
|
||||||
|
init {
|
||||||
|
val t = <selection>1 + 2</selection>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
A(1)
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
class A(a: Int, i: Int = 1 + 2) {
|
||||||
|
init {
|
||||||
|
val t = i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
A(1)
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
class A(a: Int) {
|
||||||
|
val x = <selection>1 + 2</selection>
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
A(1)
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
class A(a: Int, i: Int = 1 + 2) {
|
||||||
|
val x = i
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
A(1)
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
class A {
|
||||||
|
val a = <selection>1 + 2</selection>
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
A()
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
class A(i: Int = 1 + 2) {
|
||||||
|
val a = i
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
A()
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
// TARGET:
|
||||||
|
class A(a: Int) {
|
||||||
|
fun foo() = <selection>1 + 2</selection>
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
A(1)
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
// TARGET:
|
||||||
|
class A(a: Int, val i: Int = 1 + 2) {
|
||||||
|
fun foo() = i
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
A(1)
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
fun foo(a: Int): Int {
|
||||||
|
val b = <selection>(a + 1)</selection> * 2
|
||||||
|
return a + b
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
foo(1)
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
fun foo(a: Int, i: Int = a + 1): Int {
|
||||||
|
val b = (i) * 2
|
||||||
|
return a + b
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
foo(1)
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
trait T
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
val a = <selection>object: T {}</selection>
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
trait T
|
||||||
|
|
||||||
|
fun foo(t: T = object : T {}) {
|
||||||
|
val a = t
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
fun foo(a: Int): Int {
|
||||||
|
val b = (<selection>a + 1</selection>) * 2
|
||||||
|
return a + b
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
foo(1)
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
fun foo(a: Int, i: Int = a + 1): Int {
|
||||||
|
val b = (i) * 2
|
||||||
|
return a + b
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
foo(1)
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
var foo: Int = 1
|
||||||
|
set(m: Int) {
|
||||||
|
val t = <selection>m + 1</selection>
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Cannot refactor in this place
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
class A {
|
||||||
|
constructor(a: Int) {
|
||||||
|
val b = (<selection>a + 1</selection>) * 2
|
||||||
|
val t = a + b
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
A(1)
|
||||||
|
}
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
class A {
|
||||||
|
constructor(a: Int, i: Int = a + 1) {
|
||||||
|
val b = (i) * 2
|
||||||
|
val t = a + b
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
A(1)
|
||||||
|
}
|
||||||
+22
-4
@@ -25,16 +25,18 @@ import com.intellij.psi.util.PsiTreeUtil
|
|||||||
import com.intellij.refactoring.BaseRefactoringProcessor.ConflictsInTestsException
|
import com.intellij.refactoring.BaseRefactoringProcessor.ConflictsInTestsException
|
||||||
import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture
|
import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture
|
||||||
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
|
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
import org.jetbrains.kotlin.idea.JetLightCodeInsightFixtureTestCase
|
import org.jetbrains.kotlin.idea.JetLightCodeInsightFixtureTestCase
|
||||||
import org.jetbrains.kotlin.idea.PluginTestCaseBase
|
import org.jetbrains.kotlin.idea.PluginTestCaseBase
|
||||||
|
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.extractFunction.ExtractKotlinFunctionHandler
|
||||||
import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.*
|
import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.*
|
||||||
|
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.introduceProperty.KotlinIntroducePropertyHandler
|
||||||
import org.jetbrains.kotlin.idea.refactoring.introduce.introduceVariable.KotlinIntroduceVariableHandler
|
import org.jetbrains.kotlin.idea.refactoring.introduce.introduceVariable.KotlinIntroduceVariableHandler
|
||||||
import org.jetbrains.kotlin.psi.JetDeclaration
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.JetFile
|
|
||||||
import org.jetbrains.kotlin.psi.JetPackageDirective
|
|
||||||
import org.jetbrains.kotlin.psi.JetTreeVisitorVoid
|
|
||||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||||
import org.jetbrains.kotlin.test.ConfigLibraryUtil
|
import org.jetbrains.kotlin.test.ConfigLibraryUtil
|
||||||
import org.jetbrains.kotlin.test.InTextDirectivesUtils
|
import org.jetbrains.kotlin.test.InTextDirectivesUtils
|
||||||
@@ -61,6 +63,22 @@ public abstract class AbstractJetExtractionTest() : JetLightCodeInsightFixtureTe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected fun doIntroduceParameterTest(path: String) {
|
||||||
|
doTest(path) { file ->
|
||||||
|
with (KotlinIntroduceParameterHandler()) {
|
||||||
|
val target = file.findElementByComment("// TARGET:") as? JetNamedDeclaration
|
||||||
|
if (target != null) {
|
||||||
|
JetRefactoringUtil.selectExpression(fixture.getEditor(), file, true) { expression ->
|
||||||
|
invoke(fixture.getProject(), fixture.getEditor(), expression!!, target)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
invoke(fixture.getProject(), fixture.getEditor(), file, null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected fun doIntroducePropertyTest(path: String) {
|
protected fun doIntroducePropertyTest(path: String) {
|
||||||
doTest(path) { file ->
|
doTest(path) { file ->
|
||||||
val extractionTarget = propertyTargets.single {
|
val extractionTarget = propertyTargets.single {
|
||||||
|
|||||||
+64
@@ -32,6 +32,7 @@ import java.util.regex.Pattern;
|
|||||||
JetExtractionTestGenerated.IntroduceVariable.class,
|
JetExtractionTestGenerated.IntroduceVariable.class,
|
||||||
JetExtractionTestGenerated.ExtractFunction.class,
|
JetExtractionTestGenerated.ExtractFunction.class,
|
||||||
JetExtractionTestGenerated.IntroduceProperty.class,
|
JetExtractionTestGenerated.IntroduceProperty.class,
|
||||||
|
JetExtractionTestGenerated.IntroduceParameter.class,
|
||||||
})
|
})
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
public class JetExtractionTestGenerated extends AbstractJetExtractionTest {
|
public class JetExtractionTestGenerated extends AbstractJetExtractionTest {
|
||||||
@@ -2181,4 +2182,67 @@ public class JetExtractionTestGenerated extends AbstractJetExtractionTest {
|
|||||||
doIntroducePropertyTest(fileName);
|
doIntroducePropertyTest(fileName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("idea/testData/refactoring/introduceParameter")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class IntroduceParameter extends AbstractJetExtractionTest {
|
||||||
|
public void testAllFilesPresentInIntroduceParameter() throws Exception {
|
||||||
|
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/refactoring/introduceParameter"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("classInAnonymousInitializer.kt")
|
||||||
|
public void testClassInAnonymousInitializer() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/introduceParameter/classInAnonymousInitializer.kt");
|
||||||
|
doIntroduceParameterTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("classInPropertyInitializer.kt")
|
||||||
|
public void testClassInPropertyInitializer() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/introduceParameter/classInPropertyInitializer.kt");
|
||||||
|
doIntroduceParameterTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("classNoParams.kt")
|
||||||
|
public void testClassNoParams() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/introduceParameter/classNoParams.kt");
|
||||||
|
doIntroduceParameterTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("classParameterInFunctionBody.kt")
|
||||||
|
public void testClassParameterInFunctionBody() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/introduceParameter/classParameterInFunctionBody.kt");
|
||||||
|
doIntroduceParameterTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("defaultValueInParens.kt")
|
||||||
|
public void testDefaultValueInParens() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/introduceParameter/defaultValueInParens.kt");
|
||||||
|
doIntroduceParameterTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("functionWithApproximatedType.kt")
|
||||||
|
public void testFunctionWithApproximatedType() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/introduceParameter/functionWithApproximatedType.kt");
|
||||||
|
doIntroduceParameterTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("functionWithDefaultValue.kt")
|
||||||
|
public void testFunctionWithDefaultValue() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/introduceParameter/functionWithDefaultValue.kt");
|
||||||
|
doIntroduceParameterTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("propertyAccessor.kt")
|
||||||
|
public void testPropertyAccessor() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/introduceParameter/propertyAccessor.kt");
|
||||||
|
doIntroduceParameterTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("secondaryConstructorWithDefaultValue.kt")
|
||||||
|
public void testSecondaryConstructorWithDefaultValue() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/introduceParameter/secondaryConstructorWithDefaultValue.kt");
|
||||||
|
doIntroduceParameterTest(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user