Change Signature: val/var parameter support
This commit is contained in:
@@ -150,7 +150,7 @@ public abstract class CallableRefactoring<T: CallableDescriptor>(
|
||||
return true
|
||||
}
|
||||
|
||||
if (closestModifiableDescriptors.size() == 1 && deepestSuperDeclarations == closestModifiableDescriptors) {
|
||||
if (closestModifiableDescriptors.size() == 1 && deepestSuperDeclarations.subtract(closestModifiableDescriptors).isEmpty()) {
|
||||
performRefactoring(closestModifiableDescriptors)
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -104,7 +104,7 @@ public class JetChangeInfo(
|
||||
fun getNonReceiverParametersCount(): Int = newParameters.size() - (if (receiverParameterInfo != null) 1 else 0)
|
||||
|
||||
fun getNonReceiverParameters(): List<JetParameterInfo> {
|
||||
if (methodDescriptor.baseDeclaration is JetProperty) return emptyList()
|
||||
methodDescriptor.baseDeclaration.let { if (it is JetProperty || it is JetParameter) return emptyList() }
|
||||
return receiverParameterInfo?.let { receiver -> newParameters.filter { it != receiver } } ?: newParameters
|
||||
}
|
||||
|
||||
@@ -309,7 +309,7 @@ public class JetChangeInfo(
|
||||
when (method) {
|
||||
is JetFunction, is JetClassOrObject ->
|
||||
createJavaChangeInfoForFunctionOrGetter(originalPsiMethod, currentPsiMethod, false)
|
||||
is JetProperty -> {
|
||||
is JetProperty, is JetParameter -> {
|
||||
val accessorName = originalPsiMethod.getName()
|
||||
when {
|
||||
accessorName.startsWith(JvmAbi.GETTER_PREFIX) ->
|
||||
|
||||
+32
-29
@@ -51,7 +51,7 @@ public class JetChangePropertySignatureDialog(
|
||||
)
|
||||
private val nameField = EditorTextField(methodDescriptor.getName())
|
||||
private var returnTypeField: EditorTextField by Delegates.notNull()
|
||||
private var receiverTypeCheckBox: JCheckBox by Delegates.notNull()
|
||||
private var receiverTypeCheckBox: JCheckBox? = null
|
||||
var receiverTypeLabel: JLabel by Delegates.notNull()
|
||||
private var receiverTypeField: EditorTextField by Delegates.notNull()
|
||||
var receiverDefaultValueLabel: JLabel? = null
|
||||
@@ -66,7 +66,7 @@ public class JetChangePropertySignatureDialog(
|
||||
|
||||
override fun createCenterPanel(): JComponent? {
|
||||
fun updateReceiverUI() {
|
||||
val withReceiver = receiverTypeCheckBox.isSelected()
|
||||
val withReceiver = receiverTypeCheckBox!!.isSelected()
|
||||
receiverTypeLabel.setEnabled(withReceiver)
|
||||
receiverTypeField.setEnabled(withReceiver)
|
||||
receiverDefaultValueLabel?.setEnabled(withReceiver)
|
||||
@@ -77,7 +77,8 @@ public class JetChangePropertySignatureDialog(
|
||||
val psiFactory = JetPsiFactory(myProject)
|
||||
|
||||
return with(FormBuilder.createFormBuilder()) {
|
||||
if (!((methodDescriptor.baseDeclaration as? JetProperty)?.isLocal() ?: false)) {
|
||||
val baseDeclaration = methodDescriptor.baseDeclaration
|
||||
if (!((baseDeclaration as? JetProperty)?.isLocal() ?: false)) {
|
||||
visibilityCombo.setSelectedItem(methodDescriptor.getVisibility())
|
||||
addLabeledComponent("&Visibility: ", visibilityCombo)
|
||||
}
|
||||
@@ -85,38 +86,40 @@ public class JetChangePropertySignatureDialog(
|
||||
addLabeledComponent("&Name: ", nameField)
|
||||
|
||||
val returnTypeCodeFragment = psiFactory.createTypeCodeFragment(methodDescriptor.renderOriginalReturnType(),
|
||||
methodDescriptor.baseDeclaration)
|
||||
baseDeclaration)
|
||||
returnTypeField = EditorTextField(documentManager.getDocument(returnTypeCodeFragment), myProject, JetFileType.INSTANCE)
|
||||
addLabeledComponent("&Type: ", returnTypeField)
|
||||
|
||||
addSeparator()
|
||||
if (baseDeclaration is JetProperty) {
|
||||
addSeparator()
|
||||
|
||||
val receiverTypeCheckBox = JCheckBox("Extension property: ")
|
||||
receiverTypeCheckBox.setMnemonic('x')
|
||||
receiverTypeCheckBox.addActionListener { updateReceiverUI() }
|
||||
receiverTypeCheckBox.setSelected(methodDescriptor.receiver != null)
|
||||
addComponent(receiverTypeCheckBox)
|
||||
this@JetChangePropertySignatureDialog.receiverTypeCheckBox = receiverTypeCheckBox
|
||||
val receiverTypeCheckBox = JCheckBox("Extension property: ")
|
||||
receiverTypeCheckBox.setMnemonic('x')
|
||||
receiverTypeCheckBox.addActionListener { updateReceiverUI() }
|
||||
receiverTypeCheckBox.setSelected(methodDescriptor.receiver != null)
|
||||
addComponent(receiverTypeCheckBox)
|
||||
this@JetChangePropertySignatureDialog.receiverTypeCheckBox = receiverTypeCheckBox
|
||||
|
||||
val receiverTypeCodeFragment = psiFactory.createTypeCodeFragment(methodDescriptor.renderOriginalReceiverType() ?: "",
|
||||
methodDescriptor.baseDeclaration)
|
||||
receiverTypeField = EditorTextField(documentManager.getDocument(receiverTypeCodeFragment), myProject, JetFileType.INSTANCE)
|
||||
receiverTypeLabel = JLabel("Receiver type: ")
|
||||
receiverTypeLabel.setDisplayedMnemonic('t')
|
||||
addLabeledComponent(receiverTypeLabel, receiverTypeField)
|
||||
val receiverTypeCodeFragment = psiFactory.createTypeCodeFragment(methodDescriptor.renderOriginalReceiverType() ?: "",
|
||||
methodDescriptor.baseDeclaration)
|
||||
receiverTypeField = EditorTextField(documentManager.getDocument(receiverTypeCodeFragment), myProject, JetFileType.INSTANCE)
|
||||
receiverTypeLabel = JLabel("Receiver type: ")
|
||||
receiverTypeLabel.setDisplayedMnemonic('t')
|
||||
addLabeledComponent(receiverTypeLabel, receiverTypeField)
|
||||
|
||||
if (methodDescriptor.receiver == null) {
|
||||
val receiverDefaultValueCodeFragment = psiFactory.createExpressionCodeFragment("", methodDescriptor.baseDeclaration)
|
||||
receiverDefaultValueField = EditorTextField(documentManager.getDocument(receiverDefaultValueCodeFragment),
|
||||
myProject,
|
||||
JetFileType.INSTANCE)
|
||||
receiverDefaultValueLabel = JLabel("Default receiver value: ")
|
||||
receiverDefaultValueLabel!!.setDisplayedMnemonic('D')
|
||||
addLabeledComponent(receiverDefaultValueLabel, receiverDefaultValueField!!)
|
||||
if (methodDescriptor.receiver == null) {
|
||||
val receiverDefaultValueCodeFragment = psiFactory.createExpressionCodeFragment("", methodDescriptor.baseDeclaration)
|
||||
receiverDefaultValueField = EditorTextField(documentManager.getDocument(receiverDefaultValueCodeFragment),
|
||||
myProject,
|
||||
JetFileType.INSTANCE)
|
||||
receiverDefaultValueLabel = JLabel("Default receiver value: ")
|
||||
receiverDefaultValueLabel!!.setDisplayedMnemonic('D')
|
||||
addLabeledComponent(receiverDefaultValueLabel, receiverDefaultValueField!!)
|
||||
}
|
||||
|
||||
updateReceiverUI()
|
||||
}
|
||||
|
||||
updateReceiverUI()
|
||||
|
||||
getPanel()
|
||||
}
|
||||
}
|
||||
@@ -131,7 +134,7 @@ public class JetChangePropertySignatureDialog(
|
||||
|
||||
psiFactory.createSimpleName(nameField.getText()).validateElement("Invalid name")
|
||||
psiFactory.createType(returnTypeField.getText()).validateElement("Invalid return type")
|
||||
if (receiverTypeCheckBox.isSelected()) {
|
||||
if (receiverTypeCheckBox?.isSelected() ?: false) {
|
||||
psiFactory.createType(receiverTypeField.getText()).validateElement("Invalid receiver type")
|
||||
}
|
||||
getDefaultReceiverValue()?.validateElement("Invalid default receiver value")
|
||||
@@ -140,7 +143,7 @@ public class JetChangePropertySignatureDialog(
|
||||
override fun doAction() {
|
||||
val descriptor = (methodDescriptor as? JetMutableMethodDescriptor)?.original ?: methodDescriptor
|
||||
|
||||
val receiver = if (receiverTypeCheckBox.isSelected()) {
|
||||
val receiver = if (receiverTypeCheckBox?.isSelected() ?: false) {
|
||||
descriptor.receiver ?: JetParameterInfo(callableDescriptor = descriptor.baseDescriptor,
|
||||
name = "receiver",
|
||||
defaultValueForCall = getDefaultReceiverValue())
|
||||
|
||||
+3
-2
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
|
||||
import org.jetbrains.kotlin.idea.refactoring.CallableRefactoring
|
||||
import org.jetbrains.kotlin.psi.JetClass
|
||||
import org.jetbrains.kotlin.psi.JetFunction
|
||||
import org.jetbrains.kotlin.psi.JetParameter
|
||||
import org.jetbrains.kotlin.psi.JetProperty
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
@@ -79,7 +80,7 @@ public class JetChangeSignature(project: Project,
|
||||
is JetFunction, is JetClass -> {
|
||||
JetChangeSignatureDialog.createRefactoringProcessorForSilentChangeSignature(project, commandName, descriptor, defaultValueContext)
|
||||
}
|
||||
is JetProperty -> {
|
||||
is JetProperty, is JetParameter -> {
|
||||
JetChangePropertySignatureDialog.createProcessorForSilentRefactoring(project, commandName, descriptor)
|
||||
}
|
||||
else -> throw AssertionError("Unexpected declaration: ${descriptor.baseDeclaration.getElementTextWithContext()}")
|
||||
@@ -90,7 +91,7 @@ public class JetChangeSignature(project: Project,
|
||||
private fun runInteractiveRefactoring(descriptor: JetMethodDescriptor) {
|
||||
val dialog = when (descriptor.baseDeclaration) {
|
||||
is JetFunction, is JetClass -> JetChangeSignatureDialog(project, descriptor, defaultValueContext, commandName)
|
||||
is JetProperty -> JetChangePropertySignatureDialog(project, descriptor, commandName)
|
||||
is JetProperty, is JetParameter -> JetChangePropertySignatureDialog(project, descriptor, commandName)
|
||||
else -> throw AssertionError("Unexpected declaration: ${descriptor.baseDeclaration.getElementTextWithContext()}")
|
||||
}
|
||||
|
||||
|
||||
+18
-9
@@ -53,6 +53,22 @@ import static org.jetbrains.kotlin.idea.refactoring.changeSignature.ChangeSignat
|
||||
public class JetChangeSignatureHandler implements ChangeSignatureHandler {
|
||||
@Nullable
|
||||
public static PsiElement findTargetForRefactoring(@NotNull PsiElement element) {
|
||||
PsiElement elementParent = element.getParent();
|
||||
if ((elementParent instanceof JetNamedFunction || elementParent instanceof JetClass || elementParent instanceof JetProperty)
|
||||
&& ((JetNamedDeclaration) elementParent).getNameIdentifier() == element) return elementParent;
|
||||
|
||||
if (elementParent instanceof JetParameter) {
|
||||
JetParameter parameter = (JetParameter) elementParent;
|
||||
JetPrimaryConstructor primaryConstructor = PsiTreeUtil.getParentOfType(parameter, JetPrimaryConstructor.class);
|
||||
if (parameter.hasValOrVar()
|
||||
&& (parameter.getNameIdentifier() == element || parameter.getValOrVarKeyword() == element)
|
||||
&& primaryConstructor != null
|
||||
&& primaryConstructor.getValueParameterList() == parameter.getParent()) return parameter;
|
||||
}
|
||||
|
||||
if (elementParent instanceof JetSecondaryConstructor &&
|
||||
((JetSecondaryConstructor) elementParent).getConstructorKeyword() == element) return elementParent;
|
||||
|
||||
if (PsiTreeUtil.getParentOfType(element, JetParameterList.class) != null) {
|
||||
return PsiTreeUtil.getParentOfType(element, JetFunction.class, JetProperty.class, JetClass.class);
|
||||
}
|
||||
@@ -62,13 +78,6 @@ public class JetChangeSignatureHandler implements ChangeSignatureHandler {
|
||||
return PsiTreeUtil.getParentOfType(typeParameterList, JetFunction.class, JetProperty.class, JetClass.class);
|
||||
}
|
||||
|
||||
PsiElement elementParent = element.getParent();
|
||||
if ((elementParent instanceof JetNamedFunction || elementParent instanceof JetClass || elementParent instanceof JetProperty)
|
||||
&& ((JetNamedDeclaration) elementParent).getNameIdentifier() == element) return elementParent;
|
||||
|
||||
if (elementParent instanceof JetSecondaryConstructor &&
|
||||
((JetSecondaryConstructor) elementParent).getConstructorKeyword() == element) return elementParent;
|
||||
|
||||
JetExpression calleeExpr;
|
||||
JetCallElement call = PsiTreeUtil.getParentOfType(element,
|
||||
JetCallExpression.class,
|
||||
@@ -241,8 +250,8 @@ public class JetChangeSignatureHandler implements ChangeSignatureHandler {
|
||||
|
||||
return (FunctionDescriptor) descriptor;
|
||||
}
|
||||
else if (descriptor instanceof PropertyDescriptor) {
|
||||
return (PropertyDescriptor) descriptor;
|
||||
else if (descriptor instanceof PropertyDescriptor || descriptor instanceof ValueParameterDescriptor) {
|
||||
return (CallableDescriptor) descriptor;
|
||||
}
|
||||
else {
|
||||
String message = RefactoringBundle.getCannotRefactorMessage(JetRefactoringBundle.message(
|
||||
|
||||
+2
-1
@@ -155,7 +155,8 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
|
||||
if (parent instanceof JetConstructorCalleeExpression && parent.getParent() instanceof JetDelegatorToSuperCall)
|
||||
result.add(new JetFunctionCallUsage((JetDelegatorToSuperCall)parent.getParent(), functionUsageInfo));
|
||||
}
|
||||
else if (element instanceof JetSimpleNameExpression && functionPsi instanceof JetProperty) {
|
||||
else if (element instanceof JetSimpleNameExpression
|
||||
&& (functionPsi instanceof JetProperty || functionPsi instanceof JetParameter)) {
|
||||
result.add(new JetPropertyCallUsage((JetSimpleNameExpression) element));
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -151,7 +151,7 @@ public class JetCallableDefinitionUsage<T extends PsiElement> extends JetUsageIn
|
||||
if (currentCallableDescriptor == null) {
|
||||
PsiElement element = getDeclaration();
|
||||
|
||||
if (element instanceof JetFunction || element instanceof JetProperty) {
|
||||
if (element instanceof JetFunction || element instanceof JetProperty || element instanceof JetParameter) {
|
||||
currentCallableDescriptor = (CallableDescriptor) ResolvePackage.resolveToDescriptor((JetDeclaration) element);
|
||||
}
|
||||
else if (element instanceof JetClass) {
|
||||
@@ -227,7 +227,7 @@ public class JetCallableDefinitionUsage<T extends PsiElement> extends JetUsageIn
|
||||
callable.getTypeReference() != null);
|
||||
}
|
||||
else {
|
||||
returnTypeIsNeeded = element instanceof JetProperty;
|
||||
returnTypeIsNeeded = element instanceof JetProperty || element instanceof JetParameter;
|
||||
}
|
||||
|
||||
if (changeInfo.isReturnTypeChanged() && returnTypeIsNeeded) {
|
||||
@@ -273,7 +273,7 @@ public class JetCallableDefinitionUsage<T extends PsiElement> extends JetUsageIn
|
||||
canReplaceEntireList = true;
|
||||
}
|
||||
}
|
||||
else if (!(element instanceof JetProperty)) {
|
||||
else if (!(element instanceof JetProperty || element instanceof JetParameter)) {
|
||||
newParameterList = psiFactory.createParameterList(changeInfo.getNewParametersSignature(
|
||||
(JetCallableDefinitionUsage<PsiElement>) this)
|
||||
);
|
||||
|
||||
+2
-1
@@ -117,7 +117,8 @@ public class JetFunctionCallUsage extends JetUsageInfo<JetCallElement> {
|
||||
}
|
||||
|
||||
private boolean isPropertyJavaUsage() {
|
||||
return this.callee.getElement() instanceof JetProperty
|
||||
PsiElement calleeElement = this.callee.getElement();
|
||||
return (calleeElement instanceof JetProperty || calleeElement instanceof JetParameter)
|
||||
&& resolvedCall != null && resolvedCall.getResultingDescriptor() instanceof JavaMethodDescriptor;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.Override;
|
||||
|
||||
class J extends A {
|
||||
private int p;
|
||||
|
||||
public J() {
|
||||
super(0);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getS() {
|
||||
return p;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setS(@NotNull String value) {
|
||||
p = value;
|
||||
}
|
||||
}
|
||||
|
||||
class Test {
|
||||
static void test() {
|
||||
new A(0).getS();
|
||||
new A(0).setS(1);
|
||||
|
||||
new B(0).getS();
|
||||
new B(0).setS(2);
|
||||
|
||||
new C().getS();
|
||||
new C().setS(3);
|
||||
|
||||
new J().getS();
|
||||
new J().setS(4);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
open class A(open var <caret>s: String)
|
||||
|
||||
class B(override var s: String): A(s)
|
||||
|
||||
class C: A(0) {
|
||||
override var s: String = 1
|
||||
}
|
||||
|
||||
fun test() {
|
||||
val t1 = A(0).s
|
||||
A(0).s = 1
|
||||
|
||||
val t2 = B(0).s
|
||||
B(0).s = 2
|
||||
|
||||
val t3 = C().s
|
||||
C().s = 3
|
||||
|
||||
val t4 = J().getS()
|
||||
J().setS(4)
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
import java.lang.Override;
|
||||
|
||||
class J extends A {
|
||||
private int p;
|
||||
|
||||
public J() {
|
||||
super(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getP() {
|
||||
return p;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setP(int value) {
|
||||
p = value;
|
||||
}
|
||||
}
|
||||
|
||||
class Test {
|
||||
static void test() {
|
||||
new A(0).getP();
|
||||
new A(0).setP(1);
|
||||
|
||||
new B(0).getP();
|
||||
new B(0).setP(2);
|
||||
|
||||
new C().getP();
|
||||
new C().setP(3);
|
||||
|
||||
new J().getP();
|
||||
new J().setP(4);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
open class A(open var <caret>p: Int)
|
||||
|
||||
class B(override var p: Int): A(p)
|
||||
|
||||
class C: A(0) {
|
||||
override var p: Int = 1
|
||||
}
|
||||
|
||||
fun test() {
|
||||
val t1 = A(0).p
|
||||
A(0).p = 1
|
||||
|
||||
val t2 = B(0).p
|
||||
B(0).p = 2
|
||||
|
||||
val t3 = C().p
|
||||
C().p = 3
|
||||
|
||||
val t4 = J().getP()
|
||||
J().setP(4)
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
open class C1 protected (<caret>val x1: Int = 1, var x2: Float, x3: ((Int) -> Int)?) {
|
||||
open class C1 protected <caret>(val x1: Int = 1, var x2: Float, x3: ((Int) -> Int)?) {
|
||||
fun bar() {
|
||||
val y1 = x1;
|
||||
val y2 = x2;
|
||||
|
||||
+7
@@ -1056,6 +1056,13 @@ public class JetChangeSignatureTest extends KotlinCodeInsightTestCase {
|
||||
doTest(changeInfo);
|
||||
}
|
||||
|
||||
public void testChangeClassParameter() throws Exception {
|
||||
JetChangeInfo changeInfo = getChangeInfo();
|
||||
changeInfo.setNewName("s");
|
||||
changeInfo.setNewReturnTypeText("String");
|
||||
doTest(changeInfo);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected String getTestDataPath() {
|
||||
|
||||
Reference in New Issue
Block a user