fix for change signature when the order of named arguments is non-trivial

This commit is contained in:
Alexander Kirillin
2013-05-07 20:07:01 +04:00
parent c90b398398
commit 5499bea181
8 changed files with 142 additions and 45 deletions
@@ -23,6 +23,7 @@ import com.intellij.refactoring.changeSignature.ChangeInfo;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.jetbrains.jet.lang.descriptors.Visibilities;
import org.jetbrains.jet.lang.descriptors.Visibility;
import org.jetbrains.jet.lang.psi.JetFunction;
@@ -31,7 +32,9 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import org.jetbrains.jet.lexer.JetTokens;
import org.jetbrains.jet.plugin.JetLanguage;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class JetChangeInfo implements ChangeInfo {
private final JetFunctionPlatformDescriptor oldDescriptor;
@@ -43,6 +46,7 @@ public class JetChangeInfo implements ChangeInfo {
private final PsiElement context;
private final JetGeneratedInfo generatedInfo;
private Boolean parameterNamesChanged;
private Map<String, Integer> oldNameToParameterIndex;
public JetChangeInfo(
JetFunctionPlatformDescriptor oldDescriptor,
@@ -119,6 +123,22 @@ public class JetChangeInfo implements ChangeInfo {
return false;
}
private Map<String, Integer> initOldNameToParameterIndex() {
Map<String, Integer> map = new HashMap<String, Integer>();
FunctionDescriptor descriptor = oldDescriptor.getDescriptor();
if (descriptor != null) {
List<ValueParameterDescriptor> parameters = descriptor.getValueParameters();
for (int i = 0; i < parameters.size(); i++) {
ValueParameterDescriptor oldParameter = parameters.get(i);
map.put(oldParameter.getName().getName(), i);
}
}
return map;
}
@NotNull
@Override
public JetParameterInfo[] getNewParameters() {
@@ -141,6 +161,14 @@ public class JetChangeInfo implements ChangeInfo {
return parameterNamesChanged;
}
@Nullable
public Integer getOldParameterIndex(String oldParameterName) {
if (oldNameToParameterIndex == null)
oldNameToParameterIndex = initOldNameToParameterIndex();
return oldNameToParameterIndex.get(oldParameterName);
}
@Override
public boolean isParameterTypesChanged() {
return true;
@@ -110,7 +110,8 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
for (PsiReference reference : ReferencesSearch.search(oldParam, oldParam.getUseScope())) {
PsiElement element = reference.getElement();
if (element.getParent() instanceof JetSimpleNameExpression)
if (element.getParent() instanceof JetSimpleNameExpression &&
!(element.getParent().getParent() instanceof JetValueArgumentName)) // Usages in named arguments of the calls usage will be changed when the function call is changed
result.add(new JetParameterUsage((JetSimpleNameExpression) element.getParent(), parameterInfo, functionPsi, isInherited));
}
}
@@ -75,6 +75,10 @@ public class JetFunctionPlatformDescriptorImpl implements JetFunctionPlatformDes
parameters.remove(index);
}
public void clearParameters() {
parameters.clear();
}
@Override
public int getParametersCount() {
return funDescriptor.getValueParameters().size();
@@ -22,7 +22,9 @@ import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.plugin.refactoring.changeSignature.JetChangeInfo;
import org.jetbrains.jet.plugin.refactoring.changeSignature.JetParameterInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class JetFunctionCallUsage extends JetUsageInfo<JetCallElement> {
private final PsiElement function;
@@ -48,51 +50,103 @@ public class JetFunctionCallUsage extends JetUsageInfo<JetCallElement> {
if (arguments != null) {
List<JetValueArgument> oldArguments = arguments.getArguments();
if (changeInfo.isParameterSetOrOrderChanged()) {
StringBuilder parametersBuilder = new StringBuilder("(");
boolean isFirst = true;
for (JetParameterInfo parameterInfo : changeInfo.getNewParameters()) {
if (isFirst)
isFirst = false;
else
parametersBuilder.append(',');
String defaultValueText = parameterInfo.getDefaultValueText();
parametersBuilder.append(defaultValueText.isEmpty() ? '0' : defaultValueText);
}
parametersBuilder.append(')');
JetValueArgumentList newArguments = JetPsiFactory.createCallArguments(getProject(), parametersBuilder.toString());
int argIndex = 0;
for (JetValueArgument newArgument : newArguments.getArguments()) {
JetParameterInfo parameterInfo = changeInfo.getNewParameters()[argIndex++];
int oldIndex = parameterInfo.getOldIndex();
if (oldIndex >= 0 && oldIndex < oldArguments.size())
newArgument.replace(oldArguments.get(oldIndex));
else if (parameterInfo.getDefaultValueText().isEmpty())
newArgument.delete();
}
arguments.replace(newArguments);
}
else {
for (JetParameterInfo parameterInfo : changeInfo.getNewParameters()) {
JetValueArgument argument = parameterInfo.getOldIndex() < oldArguments.size() ? oldArguments.get(parameterInfo.getOldIndex()) : null;
JetValueArgumentName argumentName = argument != null ? argument.getArgumentName() : null;
JetSimpleNameExpression argumentNameExpression = argumentName != null ? argumentName.getReferenceExpression() : null;
PsiElement identifier = argumentNameExpression != null ? argumentNameExpression.getIdentifier() : null;
if (identifier != null) {
String newName = parameterInfo.getInheritedName(isInherited, function, changeInfo.getFunctionDescriptor());
identifier.replace(JetPsiFactory.createIdentifier(getProject(), newName));
}
}
}
if (changeInfo.isParameterSetOrOrderChanged())
arguments.replace(generateNewArgumentList(changeInfo, oldArguments));
else
changeArgumentNames(changeInfo, oldArguments);
}
return true;
}
private JetValueArgumentList generateNewArgumentList(JetChangeInfo changeInfo, List<JetValueArgument> oldArguments) {
boolean isNamedCall = oldArguments.size() > 1 && oldArguments.get(0).getArgumentName() != null;
StringBuilder parametersBuilder = new StringBuilder("(");
boolean isFirst = true;
for (JetParameterInfo parameterInfo : changeInfo.getNewParameters()) {
if (isFirst)
isFirst = false;
else
parametersBuilder.append(',');
String defaultValueText = parameterInfo.getDefaultValueText();
if (isNamedCall) {
String newName = parameterInfo.getInheritedName(isInherited, function, changeInfo.getFunctionDescriptor());
parametersBuilder.append(newName).append('=');
}
parametersBuilder.append(defaultValueText.isEmpty() ? '0' : defaultValueText);
}
parametersBuilder.append(')');
JetValueArgumentList newArguments = JetPsiFactory.createCallArguments(getProject(), parametersBuilder.toString());
Map<Integer, JetValueArgument> argumentMap = getParamIndexToArgumentMap(changeInfo, oldArguments);
int argIndex = 0;
for (JetValueArgument newArgument : newArguments.getArguments()) {
JetParameterInfo parameterInfo = changeInfo.getNewParameters()[argIndex++];
JetValueArgument oldArgument = argumentMap.get(parameterInfo.getOldIndex());
if (oldArgument != null) {
JetValueArgumentName argumentName = oldArgument.getArgumentName();
JetSimpleNameExpression argumentNameExpression = argumentName != null ? argumentName.getReferenceExpression() : null;
changeArgumentName(changeInfo, argumentNameExpression, parameterInfo);
newArgument.replace(oldArgument);
}
else if (parameterInfo.getDefaultValueText().isEmpty())
newArgument.delete();
}
return newArguments;
}
private static Map<Integer, JetValueArgument> getParamIndexToArgumentMap(JetChangeInfo changeInfo, List<JetValueArgument> oldArguments) {
Map<Integer, JetValueArgument> argumentMap = new HashMap<Integer, JetValueArgument>();
for (int i = 0; i < oldArguments.size(); i++) {
JetValueArgument argument = oldArguments.get(i);
JetValueArgumentName argumentName = argument.getArgumentName();
JetSimpleNameExpression argumentNameExpression = argumentName != null ? argumentName.getReferenceExpression() : null;
String oldParameterName = argumentNameExpression != null ? argumentNameExpression.getReferencedName() : null;
if (oldParameterName != null) {
Integer oldParameterIndex = changeInfo.getOldParameterIndex(oldParameterName);
if (oldParameterIndex != null)
argumentMap.put(oldParameterIndex, argument);
}
else
argumentMap.put(i, argument);
}
return argumentMap;
}
private void changeArgumentNames(JetChangeInfo changeInfo, List<JetValueArgument> oldArguments) {
for (JetValueArgument argument : oldArguments) {
JetValueArgumentName argumentName = argument.getArgumentName();
JetSimpleNameExpression argumentNameExpression = argumentName != null ? argumentName.getReferenceExpression() : null;
if (argumentNameExpression != null) {
Integer oldParameterIndex = changeInfo.getOldParameterIndex(argumentNameExpression.getReferencedName());
if (oldParameterIndex != null) {
JetParameterInfo parameterInfo = changeInfo.getNewParameters()[oldParameterIndex];
changeArgumentName(changeInfo, argumentNameExpression, parameterInfo);
}
}
}
}
private void changeArgumentName(JetChangeInfo changeInfo, JetSimpleNameExpression argumentNameExpression, JetParameterInfo parameterInfo) {
PsiElement identifier = argumentNameExpression != null ? argumentNameExpression.getIdentifier() : null;
if (identifier != null) {
String newName = parameterInfo.getInheritedName(isInherited, function, changeInfo.getFunctionDescriptor());
identifier.replace(JetPsiFactory.createIdentifier(getProject(), newName));
}
}
}
@@ -5,8 +5,11 @@ fun foo(x0: Any?,
val y1 = x1;
val y2 = x2;
val y3 = x3;
foo(x0 = null, x1 = 4, x2 = 5.5);
}
fun bar() {
foo(null, x1 = 2, x2 = 3.5);
foo(x0 = null, x1 = 2, x2 = 3.5);
foo(x0 = null, x1 = 3, x2 = 4.5);
foo(x0 = null, x1 = 4, x2 = 5.5);
}
@@ -3,8 +3,11 @@ protected fun foo(x1: Int = 1, x2: Float, x3: ((Int) -> Int)?) {
val y1 = x1;
val y2 = x2;
val y3 = x3;
foo(x3 = null, x2 = 5.5, x1 = 4);
}
fun bar() {
foo(x1 = 2, x2 = 3.5, x3 = null);
foo(x3 = null, x1 = 3, x2 = 4.5);
foo(x3 = null, x2 = 5.5, x1 = 4);
}
@@ -3,8 +3,10 @@ public fun foo(_x1: Int = 1, _x2: Float?, _x3: ((Int) -> Int)?) {
val y1 = _x1;
val y2 = _x2;
val y3 = _x3;
foo(_x3 = null, _x1 = 2, _x2 = 3.5);
}
fun bar() {
foo(_x1 = 2, _x2 = 3.5, _x3 = null);
foo(_x3 = null, _x1 = 2, _x2 = 3.5);
}
@@ -3,8 +3,10 @@ fun foo(<caret>x1: Int = 1, x2: Float, x3: ((Int) -> Int)?) {
val y1 = x1;
val y2 = x2;
val y3 = x3;
foo(x3 = null, x1 = 2, x2 = 3.5);
}
fun bar() {
foo(x1 = 2, x2 = 3.5, x3 = null);
foo(x3 = null, x1 = 2, x2 = 3.5);
}