fixes & tests

This commit is contained in:
Maxim Medvedev
2010-05-30 17:28:36 +04:00
parent 06dc46d6cd
commit 9b56725bd0
20 changed files with 401 additions and 173 deletions
@@ -19,6 +19,7 @@ import com.intellij.codeInsight.ExceptionUtil;
import com.intellij.lang.StdLanguages;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
@@ -123,7 +124,7 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr
else if (usage instanceof MethodCallUsageInfo) {
final MethodCallUsageInfo methodCallInfo = (MethodCallUsageInfo)usage;
processMethodUsage(methodCallInfo.getElement(), (JavaChangeInfo)changeInfo, methodCallInfo.isToChangeArguments(),
methodCallInfo.isToCatchExceptions(), methodCallInfo.getReferencedMethod(), usages);
methodCallInfo.isToCatchExceptions(), methodCallInfo.getReferencedMethod(), methodCallInfo.getSubstitutor(), usages);
return true;
}
else if (usage instanceof ChangeSignatureParameterUsageInfo) {
@@ -137,7 +138,7 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr
return true;
}
else if (element instanceof PsiEnumConstant) {
fixActualArgumentsList(((PsiEnumConstant)element).getArgumentList(), (JavaChangeInfo)changeInfo, true);
fixActualArgumentsList(((PsiEnumConstant)element).getArgumentList(), (JavaChangeInfo)changeInfo, true, PsiSubstitutor.EMPTY);
return true;
}
else if (!(usage instanceof OverriderUsageInfo)) {
@@ -179,7 +180,9 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr
final PsiElement parent = aClass.getParent();
if (parent instanceof PsiNewExpression) {
final PsiExpressionList argumentList = ((PsiNewExpression)parent).getArgumentList();
fixActualArgumentsList(argumentList, changeInfo, true);
final PsiClass baseClass = changeInfo.getMethod().getContainingClass();
final PsiSubstitutor substitutor = TypeConversionUtil.getSuperClassSubstitutor(baseClass, aClass, PsiSubstitutor.EMPTY);
fixActualArgumentsList(argumentList, changeInfo, true, substitutor);
}
}
}
@@ -198,14 +201,17 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr
superCall = (PsiExpressionStatement)body.add(superCall);
}
PsiMethodCallExpression callExpression = (PsiMethodCallExpression)superCall.getExpression();
processMethodUsage(callExpression.getMethodExpression(), changeInfo, true, false, callee, usages);
final PsiClass aClass = constructor.getContainingClass();
final PsiClass baseClass = changeInfo.getMethod().getContainingClass();
final PsiSubstitutor substitutor = TypeConversionUtil.getSuperClassSubstitutor(baseClass, aClass, PsiSubstitutor.EMPTY);
processMethodUsage(callExpression.getMethodExpression(), changeInfo, true, false, callee, substitutor, usages);
}
private static void processMethodUsage(PsiElement ref,
JavaChangeInfo changeInfo,
boolean toChangeArguments,
boolean toCatchExceptions,
PsiMethod callee, final UsageInfo[] usages) throws IncorrectOperationException {
PsiMethod callee, PsiSubstitutor subsitutor, final UsageInfo[] usages) throws IncorrectOperationException {
if (changeInfo.isNameChanged()) {
if (ref instanceof PsiJavaCodeReferenceElement) {
PsiElement last = ((PsiJavaCodeReferenceElement)ref).getReferenceNameElement();
@@ -226,7 +232,7 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr
}
}
fixActualArgumentsList(list, changeInfo, toInsertDefaultValue);
fixActualArgumentsList(list, changeInfo, toInsertDefaultValue, subsitutor);
}
if (toCatchExceptions) {
@@ -352,7 +358,7 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr
//This methods works equally well for primary usages as well as for propagated callers' usages
private static void fixActualArgumentsList(PsiExpressionList list,
JavaChangeInfo changeInfo,
boolean toInsertDefaultValue) throws IncorrectOperationException {
boolean toInsertDefaultValue, PsiSubstitutor substitutor) throws IncorrectOperationException {
final PsiElementFactory factory = JavaPsiFacade.getInstance(list.getProject()).getElementFactory();
if (changeInfo.isParameterSetOrOrderChanged()) {
if (changeInfo instanceof JavaChangeInfoImpl && ((JavaChangeInfoImpl)changeInfo).isPropagationEnabled) {
@@ -402,8 +408,31 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr
newNonVarargCount = newParms.length;
newArgsLength = newParms.length;
}
String[] oldVarargs = null;
if (changeInfo.wasVararg() && !changeInfo.isRetainsVarargs()) {
oldVarargs = new String[varargCount];
for (int i = nonVarargCount; i < args.length; i++) {
oldVarargs[i - nonVarargCount] = args[i].getText();
}
}
final PsiExpression[] newArgs = new PsiExpression[newArgsLength];
for (int i = 0; i < newNonVarargCount; i++) {
if (newParms[i].getOldIndex() == nonVarargCount && oldVarargs != null) {
PsiType type = newParms[i].createType(changeInfo.getMethod(), list.getManager());
if (type instanceof PsiArrayType) {
type = substitutor.substitute(type);
type = TypeConversionUtil.erasure(type);
String typeText = type.getCanonicalText();
if (type instanceof PsiEllipsisType) {
typeText = typeText.replace("...", "[]");
}
String text = "new " + typeText + "{" + StringUtil.join(oldVarargs, ",") + "}";
newArgs[i] = factory.createExpressionFromText(text, changeInfo.getMethod());
continue;
}
}
newArgs[i] = createActualArgument(changeInfo, list, newParms[i], toInsertDefaultValue, args);
}
if (changeInfo.isArrayToVarargs()) {
@@ -839,7 +868,11 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr
for (JavaParameterInfo info : parameters) {
final PsiType parameterType = info.createType(method, manager);
PsiType parameterType = info.createType(method, manager);
if (parameterType == null) {
parameterType =
JavaPsiFacade.getElementFactory(method.getProject()).createTypeFromText(CommonClassNames.JAVA_LANG_OBJECT, method);
}
PsiParameter param = factory.createParameter(info.getName(), parameterType);
prototype.getParameterList().add(param);
}
@@ -27,6 +27,7 @@ public class MethodCallUsageInfo extends UsageInfo {
private final boolean myToChangeArguments;
private final boolean myToCatchExceptions;
private final PsiMethod myReferencedMethod;
private final PsiSubstitutor mySubstitutor;
public boolean isToCatchExceptions() {
return myToCatchExceptions;
@@ -40,17 +41,19 @@ public class MethodCallUsageInfo extends UsageInfo {
super(ref);
myToChangeArguments = isToChangeArguments;
myToCatchExceptions = isToCatchExceptions;
myReferencedMethod = resolveMethod(ref);
final JavaResolveResult resolveResult = resolveMethod(ref);
myReferencedMethod = (PsiMethod)resolveResult.getElement();
mySubstitutor = resolveResult.getSubstitutor();
}
private static PsiMethod resolveMethod(final PsiElement ref) {
if (ref instanceof PsiEnumConstant) return ((PsiEnumConstant)ref).resolveConstructor();
private static JavaResolveResult resolveMethod(final PsiElement ref) {
if (ref instanceof PsiEnumConstant) return ((PsiEnumConstant)ref).resolveMethodGenerics();
PsiElement parent = ref.getParent();
if (parent instanceof PsiCall) {
return ((PsiCall)parent).resolveMethod();
return ((PsiCall)parent).resolveMethodGenerics();
}
else if (parent instanceof PsiAnonymousClass) {
return ((PsiNewExpression)parent.getParent()).resolveConstructor();
return ((PsiNewExpression)parent.getParent()).resolveMethodGenerics();
}
LOG.error("Unknown reference");
@@ -60,4 +63,8 @@ public class MethodCallUsageInfo extends UsageInfo {
public PsiMethod getReferencedMethod() {
return myReferencedMethod;
}
public PsiSubstitutor getSubstitutor() {
return mySubstitutor;
}
}
@@ -0,0 +1,14 @@
class List<T> {}
class Base<T> {
void fo<caret>o(String s, List<T>... l) {}
}
class Inheritor extends Base<Integer> {
void foo(String s, List<Integer>... l) {}
{
new Inheritor().foo("a", new List<Integer>());
}
}
@@ -0,0 +1,14 @@
class List<T> {}
class Base<T> {
void foo(List<T>[] l, String s) {}
}
class Inheritor extends Base<Integer> {
void foo(List<Integer>[] l, String s) {}
{
new Inheritor().foo(new List[]{new List<Integer>()}, "a");
}
}
@@ -210,6 +210,18 @@ public class ChangeSignatureTest extends LightCodeInsightTestCase {
doTest(null, new ParameterInfoImpl[] {new ParameterInfoImpl(1), new ParameterInfoImpl(0)}, false);
}
public void testReplaceVarargWithArray() throws Exception {
doTest(null, null, null, new GenParams() {
public ParameterInfoImpl[] genParams(PsiMethod method) throws IncorrectOperationException {
final PsiElementFactory factory = JavaPsiFacade.getInstance(method.getProject()).getElementFactory();
return new ParameterInfoImpl[] {
new ParameterInfoImpl(1, "l", factory.createTypeFromText("List<T>[]", method.getParameterList()), "null", false),
new ParameterInfoImpl(0, "s", factory.createTypeFromText("String", method.getParameterList()))
};
}
}, false);
}
private void doTest(String newReturnType, ParameterInfoImpl[] parameterInfos, final boolean generateDelegate) throws Exception {
doTest(null, null, newReturnType, parameterInfos, new ThrownExceptionInfo[0], generateDelegate);
}
@@ -96,22 +96,24 @@ public class GrParameterImpl extends GrVariableImpl implements GrParameter {
}
@NotNull
public PsiType getType() {
/*PsiType type = getTypeGroovy();
if (type == null) type = super.getType();*/
PsiType type = super.getType();
@Override
public PsiType getDeclaredType() {
final PsiType type = super.getDeclaredType();
if (isVarArgs()) {
return new PsiEllipsisType(type);
}
else if (isMainMethodFirstUntypedParameter()) {
return type;
}
@NotNull
public PsiType getType() {
PsiType type = super.getType();
if (isMainMethodFirstUntypedParameter()) {
PsiClassType stringType =
JavaPsiFacade.getInstance(getProject()).getElementFactory().createTypeByFQClassName("java.lang.String", getResolveScope());
return stringType.createArrayType();
}
else {
return type;
}
return type;
}
private boolean isMainMethodFirstUntypedParameter() {
@@ -39,8 +39,6 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrAnonymousClassDefinition;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEnumConstant;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureSignature;
import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
import java.util.ArrayList;
@@ -207,24 +205,16 @@ class GrChageSignatureUsageSearcher {
if (!GroovyFileType.GROOVY_LANGUAGE.equals(element.getLanguage())) continue;
boolean isToCatchExceptions = isToThrowExceptions && needToCatchExceptions(RefactoringUtil.getEnclosingMethod(element));
//todo check for applicability of arguments to method
if (PsiUtil.isMethodUsage(element)) {
GrClosureSignature signature = GrClosureSignatureUtil.createSignature(method, PsiSubstitutor.EMPTY);
final GrArgumentList argList = PsiUtil.getArgumentsList(element);
//enum constant may not have argList
if (argList == null) {
if (element instanceof GrEnumConstant) {
result.add(
new GrMethodCallUsageInfo(element, GrClosureSignatureUtil.createSignature(method, PsiSubstitutor.EMPTY), isToModifyArgs,
isToCatchExceptions, new GrClosureSignatureUtil.ArgInfo[0]));
result.add(new GrMethodCallUsageInfo(element, isToModifyArgs, isToCatchExceptions));
}
}
else {
GrClosureSignatureUtil.ArgInfo[] map =
GrClosureSignatureUtil.mapParametersToArguments(signature, argList, method.getManager(), method.getResolveScope());
result.add(
new GrMethodCallUsageInfo(element, GrClosureSignatureUtil.createSignature(method, PsiSubstitutor.EMPTY), isToModifyArgs,
isToCatchExceptions, map));
result.add(new GrMethodCallUsageInfo(element, isToModifyArgs,isToCatchExceptions));
}
}
else if (element instanceof GrDocTagValueToken) {
@@ -239,11 +229,7 @@ class GrChageSignatureUsageSearcher {
LOG.assertTrue(method.isConstructor());
final PsiClass psiClass = (PsiClass)element;
if (psiClass instanceof GrAnonymousClassDefinition) {
GrClosureSignature signature = GrClosureSignatureUtil.createSignature(method, PsiSubstitutor.EMPTY);
GrClosureSignatureUtil.ArgInfo[] map = GrClosureSignatureUtil
.mapParametersToArguments(signature, PsiUtil.getArgumentsList(element), method.getManager(), method.getResolveScope());
result.add(
new GrMethodCallUsageInfo(element, GrClosureSignatureUtil.createSignature(method, PsiSubstitutor.EMPTY), isToModifyArgs, isToCatchExceptions, map));
result.add(new GrMethodCallUsageInfo(element, isToModifyArgs, isToCatchExceptions));
continue;
}
/*if (!(myChangeInfo instanceof JavaChangeInfoImpl)) continue; todo propagate methods
@@ -296,6 +282,9 @@ class GrChageSignatureUsageSearcher {
UsageInfo usageInfo = new ChangeSignatureParameterUsageInfo(parmRef, parameter.getName(), info.getName());
results.add(usageInfo);
}
if (info.getName() != parameter.getName()) {
}
}
private boolean needToCatchExceptions(PsiMethod caller) {
@@ -217,10 +217,10 @@ public class GrChangeSignatureDialog extends RefactoringDialog {
builder.append(type).append(' ');
builder.append(name).append('(');
final List<GrParameterInfo> infos = myParameterModel.getParameterInfos();
final List<GrTableParameterInfo> infos = myParameterModel.getParameterInfos();
if (infos.size() > 0) {
final List<String> paramsText = ContainerUtil.map(infos, new Function<GrParameterInfo, String>() {
public String fun(GrParameterInfo grParameterInfo) {
final List<String> paramsText = ContainerUtil.map(infos, new Function<GrTableParameterInfo, String>() {
public String fun(GrTableParameterInfo grParameterInfo) {
return generateParameterText(grParameterInfo);
}
});
@@ -245,7 +245,7 @@ public class GrChangeSignatureDialog extends RefactoringDialog {
}
private static String generateParameterText(GrParameterInfo info) {
private static String generateParameterText(GrTableParameterInfo info) {
StringBuilder builder = new StringBuilder();
final PsiTypeCodeFragment typeFragment = info.getTypeFragment();
String typeText = typeFragment != null ? typeFragment.getText().trim() : GrModifier.DEF;
@@ -290,14 +290,19 @@ public class GrChangeSignatureDialog extends RefactoringDialog {
}
String newName = getNewName();
final List<GrParameterInfo> parameterInfos = myParameterModel.getParameterInfos();
final List<GrTableParameterInfo> tableParameterInfos = myParameterModel.getParameterInfos();
final List<GrParameterInfo> parameterInfos = ContainerUtil.map(tableParameterInfos, new Function<GrTableParameterInfo, GrParameterInfo>() {
public GrParameterInfo fun(GrTableParameterInfo info) {
return info.generateParameterInfo();
}
});
final ThrownExceptionInfo[] exceptionInfos = myExceptionTableModel.getThrownExceptions();
invokeRefactoring(new GrChangeSignatureProcessor(
myProject,
new GrChangeInfoImpl(myMethod, modifier, returnType == null ? null : CanonicalTypes.createTypeWrapper(returnType), newName,
parameterInfos, exceptionInfos, myDelegateRadioButton.isSelected())));
invokeRefactoring(new GrChangeSignatureProcessor(myProject, new GrChangeInfoImpl(myMethod, modifier, returnType == null
? null
: CanonicalTypes
.createTypeWrapper(returnType),
newName, parameterInfos, exceptionInfos,
myDelegateRadioButton.isSelected())));
}
private String getNewName() {
@@ -319,7 +324,7 @@ public class GrChangeSignatureDialog extends RefactoringDialog {
return false;
}
for (GrParameterInfo info : myParameterModel.getParameterInfos()) {
for (GrTableParameterInfo info : myParameterModel.getParameterInfos()) {
if (!StringUtil.isJavaIdentifier(info.getName())) {
showErrorHint(message("name.is.wrong", info.getName()));
}
@@ -52,7 +52,8 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArg
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrCodeBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.*;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrSafeCastExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameterList;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
@@ -291,7 +292,7 @@ public class GrChangeSignatureUsageProcessor implements ChangeSignatureUsageProc
if (usageInfo instanceof GrMethodCallUsageInfo) {
processMethodUsage(element, ((JavaChangeInfo)changeInfo), ((GrMethodCallUsageInfo)usageInfo).isToChangeArguments(),
((GrMethodCallUsageInfo)usageInfo).isToCatchExceptions(),
((GrMethodCallUsageInfo)usageInfo).getMapToArguments());
((GrMethodCallUsageInfo)usageInfo).getMapToArguments(), ((GrMethodCallUsageInfo)usageInfo).getSubstitutor());
return true;
}
else if (usageInfo instanceof DefaultConstructorImplicitUsageInfo) {
@@ -334,18 +335,21 @@ public class GrChangeSignatureUsageProcessor implements ChangeSignatureUsageProc
}
constructor = (GrConstructor)psiClass.add(constructor);
processConstructor(constructor, changeInfo);
}
private static void processConstructor(GrMethod constructor, JavaChangeInfo changeInfo) {
final PsiClass containingClass = constructor.getContainingClass();
final PsiClass baseClass = changeInfo.getMethod().getContainingClass();
final PsiSubstitutor substitutor = TypeConversionUtil.getSuperClassSubstitutor(baseClass, containingClass, PsiSubstitutor.EMPTY);
GrOpenBlock block = constructor.getBlock();
GrConstructorInvocation invocation =
GroovyPsiElementFactory.getInstance(constructor.getProject()).createConstructorInvocation("super()");
invocation = (GrConstructorInvocation)block.addStatementBefore(invocation, getFirstStatement(block));
processMethodUsage(invocation.getThisOrSuperKeyword(), changeInfo,
changeInfo.isParameterSetOrOrderChanged() || changeInfo.isParameterNamesChanged(),
changeInfo.isExceptionSetChanged(), GrClosureSignatureUtil.ArgInfo.EMPTY_ARRAY);
changeInfo.isExceptionSetChanged(), GrClosureSignatureUtil.ArgInfo.EMPTY_ARRAY, substitutor);
}
@Nullable
@@ -359,7 +363,7 @@ public class GrChangeSignatureUsageProcessor implements ChangeSignatureUsageProc
JavaChangeInfo changeInfo,
boolean toChangeArguments,
boolean toCatchExceptions,
GrClosureSignatureUtil.ArgInfo[] map) {
GrClosureSignatureUtil.ArgInfo[] map, PsiSubstitutor substitutor) {
if (map == null) return;
if (changeInfo.isNameChanged()) {
if (element instanceof GrReferenceElement) {
@@ -414,10 +418,17 @@ public class GrChangeSignatureUsageProcessor implements ChangeSignatureUsageProc
argument.delete();
}
argText.replace(argText.length() - 2, argText.length(), "]");
if (!(arguments.size() > 0 && arguments.iterator().next() instanceof GrNamedArgument)) {
argText.append(" as ").append(parameter.getTypeText());
PsiType type = parameter.createType(changeInfo.getMethod().getParameterList(), argumentList.getManager());
if (type instanceof PsiArrayType) {
type = substitutor.substitute(type);
String typeText = type.getCanonicalText();
if (type instanceof PsiEllipsisType) {
typeText = typeText.replace("...", "[]");
}
argText.append(" as ").append(typeText);
}
anchor = argumentList.addAfter(factory.createExpressionFromText(argText.toString()), anchor);
PsiUtil.shortenReferences((GroovyPsiElement)anchor);
}
}
else { //arguments for simple parameters
@@ -17,10 +17,12 @@ package org.jetbrains.plugins.groovy.refactoring.changeSignature;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiNewExpression;
import com.intellij.psi.PsiSubstitutor;
import com.intellij.usageView.UsageInfo;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrConstructorInvocation;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrApplicationStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
@@ -28,6 +30,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrC
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEnumConstant;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureSignature;
import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
/**
* @author Maxim.Medvedev
@@ -37,6 +40,7 @@ public class GrMethodCallUsageInfo extends UsageInfo {
private final boolean myToCatchExceptions;
private final PsiMethod myReferencedMethod;
private GrClosureSignatureUtil.ArgInfo[] myMapToArguments;
private PsiSubstitutor mySubstitutor;
public boolean isToCatchExceptions() {
return myToCatchExceptions;
@@ -46,35 +50,39 @@ public class GrMethodCallUsageInfo extends UsageInfo {
return myToChangeArguments;
}
public GrMethodCallUsageInfo(PsiElement element,
GrClosureSignature oldSignature,
boolean isToChangeArguments,
boolean isToCatchExceptions, GrClosureSignatureUtil.ArgInfo[] mapToArguments) {
public GrMethodCallUsageInfo(PsiElement element, boolean isToChangeArguments, boolean isToCatchExceptions) {
super(element);
myToChangeArguments = isToChangeArguments;
myToCatchExceptions = isToCatchExceptions;
myMapToArguments = mapToArguments;
myReferencedMethod = resolveMethod(element);
final GroovyResolveResult resolveResult = resolveMethod(element);
myReferencedMethod = (PsiMethod)resolveResult.getElement();
mySubstitutor = resolveResult.getSubstitutor();
final GrArgumentList list = PsiUtil.getArgumentsList(element);
if (list == null) {
myMapToArguments = GrClosureSignatureUtil.ArgInfo.EMPTY_ARRAY;
}
else {
final GrClosureSignature signature = GrClosureSignatureUtil.createSignature(myReferencedMethod, mySubstitutor);
myMapToArguments =
GrClosureSignatureUtil.mapParametersToArguments(signature, list, element.getManager(), myReferencedMethod.getResolveScope());
}
}
@Nullable
private static PsiMethod resolveMethod(final PsiElement ref) {
if (ref instanceof GrEnumConstant) return ((GrEnumConstant)ref).resolveConstructor();
private static GroovyResolveResult resolveMethod(final PsiElement ref) {
if (ref instanceof GrEnumConstant) return ((GrEnumConstant)ref).resolveConstructorGenerics();
PsiElement parent = ref.getParent();
if (parent instanceof GrCallExpression) {
return ((GrCallExpression)parent).resolveMethod();
return ((GrCallExpression)parent).getMethodVariants()[0];
}
else if (parent instanceof GrApplicationStatement) {
final GrExpression expression = ((GrApplicationStatement)parent).getFunExpression();
if (expression instanceof GrReferenceExpression) {
final PsiElement element = ((GrReferenceExpression)expression).resolve();
if (element instanceof PsiMethod) {
return (PsiMethod)element;
}
return ((GrReferenceExpression)expression).advancedResolve();
}
}
else if (parent instanceof GrConstructorInvocation) {
return ((PsiNewExpression)parent.getParent()).resolveConstructor();
return ((GrConstructorInvocation)parent).resolveConstructorGenerics();
}
return null;
@@ -87,4 +95,8 @@ public class GrMethodCallUsageInfo extends UsageInfo {
public GrClosureSignatureUtil.ArgInfo[] getMapToArguments() {
return myMapToArguments;
}
public PsiSubstitutor getSubstitutor() {
return mySubstitutor;
}
}
@@ -17,12 +17,11 @@ package org.jetbrains.plugins.groovy.refactoring.changeSignature;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.refactoring.changeSignature.JavaParameterInfo;
import com.intellij.refactoring.util.CanonicalTypes;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.debugger.fragments.GroovyCodeFragment;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
@@ -30,60 +29,52 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
* @author Maxim.Medvedev
*/
public class GrParameterInfo implements JavaParameterInfo {
private GroovyCodeFragment myName;
private GroovyCodeFragment myDefaultValue;
private PsiTypeCodeFragment myType;
private GroovyCodeFragment myDefaultInitializer;
private String myName;
private final String myDefaultValue;
private final String myDefaultInitializer;
private final int myPosition;
private CanonicalTypes.Type myTypeWrapper;
public GrParameterInfo(GrParameter parameter, int position) {
myPosition = position;
final Project project = parameter.getProject();
myName = new GroovyCodeFragment(project, parameter.getName());
myName = parameter.getName();
final PsiType type = parameter.getDeclaredType();
if (type != null) {
myType = JavaPsiFacade.getElementFactory(project).createTypeCodeFragment(type.getCanonicalText(), parameter, true, true);
myTypeWrapper = CanonicalTypes.createTypeWrapper(type);
}
else {
myType = JavaPsiFacade.getElementFactory(project).createTypeCodeFragment("", parameter, true, true);
myTypeWrapper = null;
}
final GrExpression defaultInitializer = parameter.getDefaultInitializer();
if (defaultInitializer != null) {
myDefaultInitializer = new GroovyCodeFragment(project, defaultInitializer.getText());
myDefaultInitializer = defaultInitializer.getText();
}
else {
myDefaultInitializer = new GroovyCodeFragment(project, "");
myDefaultInitializer = "";
}
myDefaultValue = new GroovyCodeFragment(project, "");
myDefaultValue = "";
}
public GrParameterInfo(Project project, PsiElement context) {
this.myPosition = -1;
myName = new GroovyCodeFragment(project, "");
myDefaultValue = new GroovyCodeFragment(project, "");
myType = JavaPsiFacade.getElementFactory(project).createTypeCodeFragment("", context, true, true);
myDefaultInitializer = new GroovyCodeFragment(project, "");
}
public GroovyCodeFragment getNameFragment() {
return myName;
}
public GroovyCodeFragment getDefaultValueFragment() {
return myDefaultValue;
}
public PsiTypeCodeFragment getTypeFragment() {
return myType;
}
public GroovyCodeFragment getDefaultInitializerFragment() {
return myDefaultInitializer;
public GrParameterInfo(@NotNull String name,
@Nullable String defaultValue,
@Nullable String defaultInitializer,
@Nullable PsiType type,
int position) {
myName = name;
myDefaultValue = defaultValue;
myDefaultInitializer = defaultInitializer;
myPosition = position;
if (type != null) {
myTypeWrapper = CanonicalTypes.createTypeWrapper(type);
}
else {
myTypeWrapper = null;
}
}
public String getName() {
return myName.getText().trim();
return myName;
}
public int getOldIndex() {
@@ -91,46 +82,30 @@ public class GrParameterInfo implements JavaParameterInfo {
}
public String getDefaultValue() {
return myDefaultValue.getText().trim();
return myDefaultValue;
}
@Nullable
public PsiType createType(PsiElement context, final PsiManager manager) throws IncorrectOperationException {
try {
return myType.getType();
}
catch (PsiTypeCodeFragment.TypeSyntaxException e) {
return null;
}
catch (PsiTypeCodeFragment.NoTypeException e) {
return JavaPsiFacade.getElementFactory(manager.getProject())
.createTypeByFQClassName(CommonClassNames.JAVA_LANG_OBJECT, GlobalSearchScope.allScope(manager.getProject()));
}
if (myTypeWrapper == null) return null;
return myTypeWrapper.getType(context, manager);
}
public String getTypeText() {
CanonicalTypes.Type type = getTypeWrapper();
if (type != null) {
return type.getTypeText();
if (myTypeWrapper != null) {
return myTypeWrapper.getTypeText();
}
return "";
}
@Nullable
public CanonicalTypes.Type getTypeWrapper() {
if (myTypeWrapper == null) {
PsiType type = createType(myType.getContext(), myType.getManager());
if (type != null) {
myTypeWrapper = CanonicalTypes.createTypeWrapper(type);
}
}
return myTypeWrapper;
}
public PsiExpression getValue(PsiCallExpression callExpression) {
return JavaPsiFacade.getInstance(callExpression.getProject()).getElementFactory()
.createExpressionFromText(myDefaultValue.getText(), callExpression);
.createExpressionFromText(myDefaultValue, callExpression);
}
public boolean isVarargType() {
@@ -146,10 +121,17 @@ public class GrParameterInfo implements JavaParameterInfo {
}
public String getDefaultInitializer() {
return myDefaultInitializer.getText().trim();
return myDefaultInitializer;
}
public boolean hasNoType() {
return myType.getText().trim().length() == 0;
return getTypeText().length() == 0;
}
/**
* for testing only
*/
public void setName(String newName) {
myName = newName;
}
}
@@ -32,7 +32,7 @@ import java.util.List;
* @author Maxim.Medvedev
*/
public class GrParameterTableModel extends AbstractTableModel implements RowEditableTableModel {
private final List<GrParameterInfo> infos;
private final List<GrTableParameterInfo> infos;
private final GrMethod myMethod;
private final GrChangeSignatureDialog myDialog;
private final Project myProject;
@@ -41,17 +41,17 @@ public class GrParameterTableModel extends AbstractTableModel implements RowEdit
myMethod = method;
myDialog = dialog;
final GrParameter[] parameters = myMethod.getParameters();
infos = new ArrayList<GrParameterInfo>(parameters.length);
infos = new ArrayList<GrTableParameterInfo>(parameters.length);
for (int i = 0; i < parameters.length; i++) {
GrParameter parameter = parameters[i];
infos.add(new GrParameterInfo(parameter, i));
infos.add(new GrTableParameterInfo(parameter, i));
}
myProject = project;
}
public void addRow() {
final int row = infos.size();
infos.add(new GrParameterInfo(myProject, myMethod));
infos.add(new GrTableParameterInfo(myProject, myMethod));
fireTableRowsInserted(row, row);
}
@@ -61,7 +61,7 @@ public class GrParameterTableModel extends AbstractTableModel implements RowEdit
}
public void exchangeRows(int index1, int index2) {
final GrParameterInfo info = infos.get(index1);
final GrTableParameterInfo info = infos.get(index1);
infos.set(index1, infos.get(index2));
infos.set(index2, info);
fireTableRowsUpdated(Math.min(index1, index2), Math.max(index1, index2));
@@ -79,7 +79,7 @@ public class GrParameterTableModel extends AbstractTableModel implements RowEdit
@Nullable
public Object getValueAt(int rowIndex, int columnIndex) {
if (rowIndex < 0 || rowIndex >= infos.size()) return null;
final GrParameterInfo info = infos.get(rowIndex);
final GrTableParameterInfo info = infos.get(rowIndex);
switch (columnIndex) {
case 0:
return info.getTypeFragment();
@@ -135,11 +135,11 @@ public class GrParameterTableModel extends AbstractTableModel implements RowEdit
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
if (columnIndex < 3) return true;
GrParameterInfo info = infos.get(rowIndex);
GrTableParameterInfo info = infos.get(rowIndex);
return info.getOldIndex() < 0;
}
public List<GrParameterInfo> getParameterInfos() {
public List<GrTableParameterInfo> getParameterInfos() {
return infos;
}
}
@@ -0,0 +1,110 @@
/*
* Copyright 2000-2010 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.plugins.groovy.refactoring.changeSignature;
import com.intellij.openapi.project.Project;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiType;
import com.intellij.psi.PsiTypeCodeFragment;
import org.jetbrains.plugins.groovy.debugger.fragments.GroovyCodeFragment;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
/**
* @author Maxim.Medvedev
*/
public class GrTableParameterInfo {
private GroovyCodeFragment myName;
private GroovyCodeFragment myDefaultValue;
private PsiTypeCodeFragment myType;
private GroovyCodeFragment myDefaultInitializer;
private final int myPosition;
public GrTableParameterInfo(GrParameter parameter, int position) {
myPosition = position;
final Project project = parameter.getProject();
myName = new GroovyCodeFragment(project, parameter.getName());
final PsiType type = parameter.getDeclaredType();
if (type != null) {
String typeText = type.getCanonicalText();
if (typeText == null) typeText = type.getPresentableText();
myType = JavaPsiFacade.getElementFactory(project).createTypeCodeFragment(typeText, parameter, true, true, true);
}
else {
myType = JavaPsiFacade.getElementFactory(project).createTypeCodeFragment("", parameter, true, true, true);
}
final GrExpression defaultInitializer = parameter.getDefaultInitializer();
if (defaultInitializer != null) {
myDefaultInitializer = new GroovyCodeFragment(project, defaultInitializer.getText());
}
else {
myDefaultInitializer = new GroovyCodeFragment(project, "");
}
myDefaultValue = new GroovyCodeFragment(project, "");
}
public GrTableParameterInfo(Project project, PsiElement context) {
this.myPosition = -1;
myName = new GroovyCodeFragment(project, "");
myDefaultValue = new GroovyCodeFragment(project, "");
myType = JavaPsiFacade.getElementFactory(project).createTypeCodeFragment("", context, true, true);
myDefaultInitializer = new GroovyCodeFragment(project, "");
}
public GroovyCodeFragment getNameFragment() {
return myName;
}
public GroovyCodeFragment getDefaultValueFragment() {
return myDefaultValue;
}
public PsiTypeCodeFragment getTypeFragment() {
return myType;
}
public GroovyCodeFragment getDefaultInitializerFragment() {
return myDefaultInitializer;
}
public String getName() {
return myName.getText().trim();
}
public int getOldIndex() {
return myPosition;
}
public String getDefaultValue() {
return myDefaultValue.getText().trim();
}
public GrParameterInfo generateParameterInfo() {
String defaultInitializer = myDefaultInitializer.getText().trim();
PsiType type;
try {
type = myType.getType();
}
catch (PsiTypeCodeFragment.TypeSyntaxException e) {
type = null;
}
catch (PsiTypeCodeFragment.NoTypeException e) {
type = null;
}
return new GrParameterInfo(getName(), getDefaultValue(), defaultInitializer, type, myPosition);
}
}
@@ -15,7 +15,10 @@
*/
package org.jetbrains.plugins.groovy.refactoring.changeSignature;
import com.intellij.psi.*;
import com.intellij.psi.CommonClassNames;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiClassType;
import com.intellij.psi.PsiType;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.refactoring.changeSignature.JavaThrownExceptionInfo;
import com.intellij.refactoring.changeSignature.ThrownExceptionInfo;
@@ -35,7 +38,7 @@ public class ChangeSignatureTest extends ChangeSignatureTestCase {
public void testOneNewParameter() throws Exception {
doTest(new SimpleInfo[]{
new SimpleInfo("p", -1, "\"5\"", null, createType(CommonClassNames.JAVA_LANG_STRING))});
new SimpleInfo("p", -1, "\"5\"", null, CommonClassNames.JAVA_LANG_STRING)});
}
public void testRemoveParameter() throws Exception {
@@ -194,7 +197,7 @@ public class ChangeSignatureTest extends ChangeSignatureTestCase {
}
public void testTypeParameters() throws Exception {
doTest(new SimpleInfo[]{new SimpleInfo("list", -1, "null", null, createType("java.util.List<T>")), new SimpleInfo(0)});
doTest(new SimpleInfo[]{new SimpleInfo("list", -1, "null", null, "java.util.List<T>"), new SimpleInfo(0)});
}
public void testEnumConstructor() throws Exception {
@@ -205,6 +208,10 @@ public class ChangeSignatureTest extends ChangeSignatureTestCase {
doTest(new SimpleInfo[] {new SimpleInfo(1), new SimpleInfo(0)});
}
public void testReplaceVarargWithArray() throws Exception {
doTest(new SimpleInfo[]{new SimpleInfo("l", 1, null, null, "List<T>[]"), new SimpleInfo(0)});
}
private PsiType createType(String typeText) {
return JavaPsiFacade.getElementFactory(getProject()).createTypeByFQClassName(typeText, GlobalSearchScope.allScope(getProject()));
}
@@ -16,15 +16,13 @@
package org.jetbrains.plugins.groovy.refactoring.changeSignature;
import com.intellij.codeInsight.TargetElementUtilBase;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.refactoring.changeSignature.ThrownExceptionInfo;
import com.intellij.refactoring.util.CanonicalTypes;
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
@@ -84,43 +82,43 @@ public abstract class ChangeSignatureTestCase extends LightCodeInsightFixtureTes
GrParameter[] params = method.getParameterList().getParameters();
GrParameterInfo[] result = new GrParameterInfo[myInfos.length];
for (int i = 0; i < myInfos.length; i++) {
final SimpleInfo sim = myInfos[i];
int oldIndex = sim.myOldIndex;
final GrParameterInfo info;
String name = null;
String defInitializer = null;
PsiType type = null;
String defValue = null;
if (oldIndex > -1) {
info = new GrParameterInfo(params[oldIndex], oldIndex);
}
else {
info = new GrParameterInfo(myProject, method);
final GrParameter p = params[oldIndex];
name = p.getName();
final GrExpression initializer = p.getDefaultInitializer();
defInitializer = initializer != null ? initializer.getText() : null;
type = p.getDeclaredType();
}
if (sim.myNewName != null) {
setText(info.getNameFragment(), sim.myNewName);
name = sim.myNewName;
}
if (sim.myType != null) {
setText(info.getTypeFragment(), sim.myType.getCanonicalText());
if (sim.myType != null && sim.myType.length() > 0) {
type = JavaPsiFacade.getElementFactory(myProject).createTypeFromText(sim.myType, method);
}
if (sim.myDefaultInitializer != null) {
setText(info.getDefaultInitializerFragment(), sim.myDefaultInitializer);
defInitializer = sim.myDefaultInitializer;
}
if (sim.myDefaultValue != null) {
setText(info.getDefaultValueFragment(), sim.myDefaultValue);
defValue = sim.myDefaultValue;
}
assert (oldIndex < 0 && defValue != null) || oldIndex >= 0;
assert name != null;
info = new GrParameterInfo(name, defValue, defInitializer, type, oldIndex);
result[i] = info;
}
return result;
}
private void setText(final PsiCodeFragment codeFragment, final String newText) {
new WriteAction() {
@Override
protected void run(Result result) throws Throwable {
final PsiDocumentManager docManager = PsiDocumentManager.getInstance(myProject);
final Document document = docManager.getDocument(codeFragment);
document.setText(newText);
docManager.commitDocument(document);
}
}.execute();
}
}
interface GenExceptions {
@@ -151,22 +149,26 @@ public abstract class ChangeSignatureTestCase extends LightCodeInsightFixtureTes
String myNewName;
String myDefaultValue;
String myDefaultInitializer;
private PsiType myType;
private String myType;
SimpleInfo(int oldIndex) {
this(null, oldIndex);
}
SimpleInfo(String newName, int oldIndex) {
this(newName, oldIndex, "", null, null);
this(newName, oldIndex, "", null, "");
}
SimpleInfo(String newName, int oldIndex, String defaultValue, String defaultInitializer, PsiType type) {
SimpleInfo(String newName, int oldIndex, String defaultValue, String defaultInitializer, String type) {
myOldIndex = oldIndex;
myNewName = newName;
myDefaultValue = defaultValue;
myDefaultInitializer = defaultInitializer;
myType = type;
}
SimpleInfo(String newName, int oldIndex, String defaultValue, String defaultInitializer, PsiType type) {
this(newName, oldIndex, defaultValue, defaultInitializer, type.getCanonicalText());
}
}
}
@@ -1,3 +1,3 @@
def fo<caret>o(String s, String[] args) {}
def fo<caret>o(String s, String... args) {}
foo("a", "b", "c")
@@ -1,3 +1,3 @@
def foo(String[] args, String s) {}
def foo(String... args, String s) {}
foo(["b", "c"] as String[], "a")
@@ -1,5 +1,5 @@
class Foo {
public static void main(String[] args) {
new MoveVarArgParameters().foo(new String[]{"b", "c"}, "a")
new MoveVarArgParameters().foo(new String[]{"b","c"},"a" )
}
}
@@ -0,0 +1,14 @@
class List<T> {}
class Base<T> {
void fo<caret>o(String s, List<T>... l) {}
}
class Inheritor extends Base<Integer> {
void foo(String s, List<Integer>... l) {}
{
new Inheritor().foo("a", new ArrayList<Integer>());
}
}
@@ -0,0 +1,14 @@
class List<T> {}
class Base<T> {
void foo(List<T>[] l, String s) {}
}
class Inheritor extends Base<Integer> {
void foo(List<Integer>[] l, String s) {}
{
new Inheritor().foo([new List<Integer>()] as List<Integer>[], "a");
}
}