(no message)

This commit is contained in:
Eugene Vigdorchik
2005-02-16 20:49:03 +03:00
parent 24d907014a
commit 99d845186c
14 changed files with 540 additions and 261 deletions
@@ -0,0 +1,32 @@
package com.intellij.refactoring.changeSignature;
import com.intellij.psi.PsiMethod;
import com.intellij.usageView.UsageInfo;
/**
* @author ven
*/
public class CallerUsageInfo extends UsageInfo {
private PsiMethod myMethod;
private final boolean myToInsertParameter;
private final boolean myToInsertException;
public CallerUsageInfo(final PsiMethod method, boolean isToInsertParameter, boolean isToInsertException) {
super(method);
myMethod = method;
myToInsertParameter = isToInsertParameter;
myToInsertException = isToInsertException;
}
public boolean isToInsertException() {
return myToInsertException;
}
public boolean isToInsertParameter() {
return myToInsertParameter;
}
public PsiMethod getMethod() {
return myMethod;
}
}
@@ -12,6 +12,8 @@ import com.intellij.refactoring.util.CanonicalTypes;
import com.intellij.util.IncorrectOperationException;
import java.util.Arrays;
import java.util.List;
import java.util.ArrayList;
class ChangeInfo {
private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.changeSignature.ChangeInfo");
@@ -25,7 +27,7 @@ class ChangeInfo {
final String newName;
final CanonicalTypes.Type newReturnType;
final ParameterInfo[] newParms;
final ThrownExceptionInfo[] newExceptions;
ThrownExceptionInfo[] newExceptions;
final boolean[] toRemoveParm;
boolean isVisibilityChanged = false;
boolean isNameChanged = false;
@@ -35,6 +37,7 @@ class ChangeInfo {
boolean isExceptionSetOrOrderChanged = false;
boolean isParameterNamesChanged = false;
boolean isParameterTypesChanged = false;
boolean isPropagationEnabled = true;
final boolean wasVararg;
final boolean retainsVarargs;
final boolean obtainsVarags;
@@ -89,7 +92,7 @@ class ChangeInfo {
if (parameters.length != newParms.length){
this.isParameterSetOrOrderChanged = true;
}
else{
else {
for(int i = 0; i < newParms.length; i++){
ParameterInfo parmInfo = newParms[i];
PsiParameter parameter = parameters[i];
@@ -111,28 +114,9 @@ class ChangeInfo {
}
}
if (newExceptions == null) newExceptions = extractExceptions(method);
setupPropagationEnabled(parameters, newParms);
this.newExceptions = newExceptions;
PsiClassType[] types = method.getThrowsList().getReferencedTypes();
isExceptionSetChanged = newExceptions.length != types.length;
if (!isExceptionSetChanged) {
for (int i = 0; i < newExceptions.length; i++) {
try {
if (newExceptions[i].oldIndex < 0 || !types[i].equals(newExceptions[i].myType.getType(method))) {
isExceptionSetChanged = true;
break;
}
}
catch (IncorrectOperationException e) {
isExceptionSetChanged = true;
}
if (newExceptions[i].oldIndex != i) isExceptionSetOrOrderChanged = true;
}
}
isExceptionSetOrOrderChanged |= isExceptionSetChanged;
setupExceptions(newExceptions, method);
this.toRemoveParm = new boolean[parameters.length];
Arrays.fill(this.toRemoveParm, true);
@@ -169,6 +153,46 @@ class ChangeInfo {
ejbRole = J2EERolesUtil.getEjbRole(method);
}
private void setupExceptions(ThrownExceptionInfo[] newExceptions, final PsiMethod method) {
if (newExceptions == null) newExceptions = extractExceptions(method);
this.newExceptions = newExceptions;
PsiClassType[] types = method.getThrowsList().getReferencedTypes();
isExceptionSetChanged = newExceptions.length != types.length;
if (!isExceptionSetChanged) {
for (int i = 0; i < newExceptions.length; i++) {
try {
if (newExceptions[i].oldIndex < 0 || !types[i].equals(newExceptions[i].myType.getType(method))) {
isExceptionSetChanged = true;
break;
}
}
catch (IncorrectOperationException e) {
isExceptionSetChanged = true;
}
if (newExceptions[i].oldIndex != i) isExceptionSetOrOrderChanged = true;
}
}
isExceptionSetOrOrderChanged |= isExceptionSetChanged;
}
private void setupPropagationEnabled(final PsiParameter[] parameters, final ParameterInfo[] newParms) {
if (parameters.length >= newParms.length) {
isPropagationEnabled = false;
}
else {
for (int i = 0; i < parameters.length; i++) {
final ParameterInfo newParm = newParms[i];
if (newParm.oldParameterIndex != i) {
isPropagationEnabled = false;
break;
}
}
}
}
//create identity mapping
private static ThrownExceptionInfo[] extractExceptions(PsiMethod method) {
PsiClassType[] types = method.getThrowsList().getReferencedTypes();
@@ -186,4 +210,15 @@ class ChangeInfo {
public void updateMethod(PsiMethod method) {
this.method = method;
}
public ParameterInfo[] getCreatedParmsInfoWithoutVarargs() {
List<ParameterInfo> result = new ArrayList<ParameterInfo>();
for (int i = 0; i < newParms.length; i++) {
ParameterInfo newParm = newParms[i];
if (newParm.oldParameterIndex < 0 && !newParm.isVarargType()) {
result.add(newParm);
}
}
return result.toArray(new ParameterInfo[result.size()]);
}
}
@@ -38,10 +38,8 @@ import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.*;
import java.util.List;
import java.util.StringTokenizer;
public class ChangeSignatureDialog extends RefactoringDialog {
private static final Logger LOG = Logger.getInstance(
@@ -63,8 +61,8 @@ public class ChangeSignatureDialog extends RefactoringDialog {
private ExceptionsTableModel myExceptionsTableModel;
private JButton myPropagateParamChangesButton;
private JButton myPropagateExnChangesButton;
private PsiMethod[] myMethodsToPropagateParameters = null;
private PsiMethod[] myMethodsToPropagateExceptions = null;
private Set<PsiMethod> myMethodsToPropagateParameters = null;
private Set<PsiMethod> myMethodsToPropagateExceptions = null;
public ChangeSignatureDialog(Project project, PsiMethod method, boolean allowDelegation) {
super(project, true);
@@ -166,8 +164,8 @@ public class ChangeSignatureDialog extends RefactoringDialog {
myPropagateParamChangesButton = new JButton("Propagate Parameters");
myPropagateParamChangesButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
new CallerChooser(myMethod, "Select Caller Methods To Apply Default Value") {
protected void callersChosen(PsiMethod[] callers) {
new CallerChooser(myMethod, "Select New Parameters Propagation End Points") {
protected void callersChosen(Set<PsiMethod> callers) {
myMethodsToPropagateParameters = callers;
}
}.show();
@@ -178,8 +176,8 @@ public class ChangeSignatureDialog extends RefactoringDialog {
myPropagateExnChangesButton = new JButton("Propagate Exceptions");
myPropagateExnChangesButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
new CallerChooser(myMethod, "Select Caller Methods To Insert Catch Statements") {
protected void callersChosen(PsiMethod[] callers) {
new CallerChooser(myMethod, "Select New Thrown Exceptions Propagation End Points") {
protected void callersChosen(Set<PsiMethod> callers) {
myMethodsToPropagateExceptions = callers;
}
}.show();
@@ -334,14 +332,6 @@ public class ChangeSignatureDialog extends RefactoringDialog {
myExceptionsTable.getColumnModel().getColumn(0).setCellEditor(new CodeFragmentTableCellEditor(myProject));
}
public PsiMethod[] getEndPointsToPropagateExceptions() {
return myMethodsToPropagateExceptions;
}
public PsiMethod[] getEndPointsToPropagateParameters() {
return myMethodsToPropagateParameters;
}
private void completeVariable(EditorTextField editorTextField, PsiType type) {
Editor editor = editorTextField.getEditor();
String prefix = editorTextField.getText();
@@ -518,8 +508,8 @@ public class ChangeSignatureDialog extends RefactoringDialog {
invokeRefactoring(new ChangeSignatureProcessor(getProject(), myMethod, isGenerateDelegate(),
getVisibility(), getMethodName(), getReturnType(),
getParameters(), getExceptions(),
getEndPointsToPropagateParameters(),
getEndPointsToPropagateExceptions()));
myMethodsToPropagateParameters,
myMethodsToPropagateExceptions));
}
private String validateAndCommitData() {
@@ -17,9 +17,9 @@ import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.javadoc.PsiDocTagValue;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.codeStyle.VariableKind;
import com.intellij.psi.javadoc.PsiDocTagValue;
import com.intellij.psi.scope.processor.VariablesProcessor;
import com.intellij.psi.scope.util.PsiScopesUtil;
import com.intellij.psi.search.GlobalSearchScope;
@@ -48,16 +48,14 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor {
private final String myNewVisibility;
private String myNewName;
private CanonicalTypes.Type myNewType;
private ParameterInfo[] myParameterInfo;
private ChangeInfo myChangeInfo;
private PsiManager myManager;
private PsiElementFactory myFactory;
private static final Class[] NORMALIZED_RESOLUTION_CONTEXT_CLASSES =
new Class[]{PsiStatement.class, PsiClass.class, PsiFile.class};
private HashSet<PsiMethod> myMethodsToBeChanged;
private final boolean myGenerateDelegate;
private final PsiMethod[] myPropagateParametersEndPoints;
private final PsiMethod[] myPropagateExceptionsEndPoints;
private final Set<PsiMethod> myPropagateParametersMethods;
private final Set<PsiMethod> myPropagateExceptionsMethods;
public ChangeSignatureProcessor(Project project,
PsiMethod method,
@@ -92,12 +90,14 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor {
CanonicalTypes.Type newType,
ParameterInfo[] parameterInfo,
ThrownExceptionInfo[] thrownExceptions,
PsiMethod[] propagateParametersEndPoints,
PsiMethod[] propagateExceptionsEndPoints) {
Set<PsiMethod> propagateParametersMethods,
Set<PsiMethod> propagateExceptionsMethods) {
super(project);
myGenerateDelegate = generateDelegate;
myPropagateParametersEndPoints = propagateParametersEndPoints;
myPropagateExceptionsEndPoints = propagateExceptionsEndPoints;
myPropagateParametersMethods = propagateParametersMethods != null ? propagateParametersMethods : new HashSet<PsiMethod>();
myPropagateExceptionsMethods = propagateExceptionsMethods != null ? propagateExceptionsMethods : new HashSet<PsiMethod>();
LOG.assertTrue(method.isValid());
if (newVisibility == null) {
myNewVisibility = VisibilityUtil.getVisibilityModifier(method.getModifierList());
@@ -106,9 +106,7 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor {
}
myNewName = newName;
myNewType = newType;
myParameterInfo = parameterInfo;
myChangeInfo = new ChangeInfo(myNewVisibility, method, myNewName, myNewType, myParameterInfo, thrownExceptions);
myChangeInfo = new ChangeInfo(myNewVisibility, method, myNewName, myNewType, parameterInfo, thrownExceptions);
LOG.assertTrue(myChangeInfo.getMethod().isValid());
}
@@ -132,6 +130,18 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor {
}
private void findSimpleUsages(final PsiMethod method, final ArrayList<UsageInfo> result) {
PsiMethod[] overridingMethods = findSimpleUsagesWithoutParameters(method, result, true, true, true);
findUsagesInCallers (result);
//Parameter name changes are not propagated
findParametersUsage(method, result, overridingMethods);
}
private PsiMethod[] findSimpleUsagesWithoutParameters(final PsiMethod method,
final ArrayList<UsageInfo> result,
boolean isToModifyArgs,
boolean isToThrowExceptions,
boolean isOriginal) {
PsiManager manager = method.getManager();
PsiSearchHelper helper = manager.getSearchHelper();
@@ -140,10 +150,10 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor {
for (int i = 0; i < overridingMethods.length; i++) {
PsiMethod overridingMethod = overridingMethods[i];
result.add(new UsageInfo(overridingMethod));
result.add(new OverriderUsageInfo(overridingMethod, method, isOriginal, isToModifyArgs, isToThrowExceptions));
}
boolean needToChangeCalls = !myGenerateDelegate && (needToChangeCalls() || myChangeInfo.isVisibilityChanged/*for checking inaccessible*/);
boolean needToChangeCalls = !myGenerateDelegate && (myChangeInfo.isNameChanged || myChangeInfo.isParameterSetOrOrderChanged || myChangeInfo.isExceptionSetOrOrderChanged || myChangeInfo.isVisibilityChanged/*for checking inaccessible*/);
if (needToChangeCalls) {
List<PsiElement> l = new ArrayList<PsiElement>();
PsiReference[] refs = helper.findReferencesIncludingOverriding(method, projectScope, true);
@@ -155,13 +165,14 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor {
int parameterCount = method.getParameterList().getParameters().length;
for (Iterator<PsiElement> iterator = l.iterator(); iterator.hasNext();) {
PsiElement ref = iterator.next();
if (myChangeInfo.isParameterSetOrOrderChanged) {
boolean isToCatchExceptions = isToThrowExceptions && needToCatchExceptions(RefactoringUtil.getEnclosingMethod(ref));
if (!isToCatchExceptions) {
if (RefactoringUtil.isMethodUsage(ref)) {
PsiExpressionList list = RefactoringUtil.getArgumentListByMethodReference((PsiJavaCodeReferenceElement)ref);
PsiExpressionList list = RefactoringUtil.getArgumentListByMethodReference(ref);
if (!method.isVarArgs() && list.getExpressions().length != parameterCount) continue;
}
}
result.add(new UsageInfo(ref));
result.add(new MethodCallUsageInfo(ref, isToModifyArgs, isToCatchExceptions));
}
if (method.isConstructor() && parameterCount == 0) {
@@ -178,52 +189,68 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor {
}
}
findParametersUsage(method, result, overridingMethods);
// Conflicts
detectLocalsCollisionsInMethod(method, result);
detectLocalsCollisionsInMethod(method, result, isOriginal);
for (int j = 0; j < overridingMethods.length; j++) {
final PsiMethod overridingMethod = overridingMethods[j];
detectLocalsCollisionsInMethod(overridingMethod, result);
detectLocalsCollisionsInMethod(overridingMethod, result, isOriginal);
}
return overridingMethods;
}
private void findUsagesInCallers(final ArrayList<UsageInfo> usages) {
for (Iterator<PsiMethod> iterator = myPropagateParametersMethods.iterator(); iterator.hasNext();) {
PsiMethod caller = iterator.next();
usages.add(new CallerUsageInfo(caller, true, myPropagateExceptionsMethods.contains(caller)));
}
for (Iterator<PsiMethod> iterator = myPropagateExceptionsMethods.iterator(); iterator.hasNext();) {
PsiMethod caller = iterator.next();
usages.add(new CallerUsageInfo(caller, myPropagateParametersMethods.contains(caller), true));
}
Set<PsiMethod> merged = new HashSet<PsiMethod>();
merged.addAll(myPropagateParametersMethods);
merged.addAll(myPropagateExceptionsMethods);
for (Iterator<PsiMethod> iterator = merged.iterator(); iterator.hasNext();) {
final PsiMethod method = iterator.next();
findSimpleUsagesWithoutParameters(method, usages, myPropagateParametersMethods.contains(method),
myPropagateExceptionsMethods.contains(method), false);
}
}
private boolean needToChangeCalls() {
return myChangeInfo.isNameChanged || myChangeInfo.isParameterSetOrOrderChanged || myChangeInfo.isExceptionSetChanged;
return myChangeInfo.isNameChanged || myChangeInfo.isParameterSetOrOrderChanged || myChangeInfo.isExceptionSetOrOrderChanged;
}
private boolean needToCatchExceptions(PsiMethod caller) {
return myChangeInfo.isExceptionSetOrOrderChanged && !myPropagateExceptionsMethods.contains(caller);
}
private void detectLocalsCollisionsInMethod(final PsiMethod method,
final ArrayList<UsageInfo> result) {
final PsiParameter[] overridingParameters = method.getParameterList().getParameters();
final Set<PsiParameter> deletedParameters =
new HashSet<PsiParameter>(Arrays.asList(overridingParameters));
for (int i = 0; i < myParameterInfo.length; i++) {
ParameterInfo parameterInfo = myParameterInfo[i];
if (parameterInfo.oldParameterIndex >= 0 &&
parameterInfo.getName().equals(overridingParameters[parameterInfo.oldParameterIndex].getName())) {
deletedParameters.remove(overridingParameters[parameterInfo.oldParameterIndex]);
}
}
for (int i = 0; i < myParameterInfo.length; i++) {
ParameterInfo parameterInfo = myParameterInfo[i];
final ArrayList<UsageInfo> result,
boolean isOriginal) {
final PsiParameter[] parameters = method.getParameterList().getParameters();
for (int i = 0; i < myChangeInfo.newParms.length; i++) {
ParameterInfo parameterInfo = myChangeInfo.newParms[i];
final int oldParameterIndex = parameterInfo.oldParameterIndex;
final String newName = parameterInfo.getName();
if (oldParameterIndex >= 0) {
final PsiParameter parameter = overridingParameters[oldParameterIndex];
if (!newName.equals(parameter.getName())) {
RenameUtil.visitLocalsCollisions(parameter, newName, method.getBody(), null, new RenameUtil.CollidingVariableVisitor() {
public void visitCollidingElement(final PsiVariable collidingVariable) {
if (!(collidingVariable instanceof PsiField) && !deletedParameters.contains(collidingVariable)) {
result.add(new RenamedParameterCollidesWithLocalUsageInfo(parameter, collidingVariable, method));
if (isOriginal) { //Name changes take place only in primary method
final PsiParameter parameter = parameters[oldParameterIndex];
if (!newName.equals(parameter.getName())) {
RenameUtil.visitLocalsCollisions(parameter, newName, method.getBody(), null, new RenameUtil.CollidingVariableVisitor() {
public void visitCollidingElement(final PsiVariable collidingVariable) {
if (!(collidingVariable instanceof PsiField)) {
result.add(new RenamedParameterCollidesWithLocalUsageInfo(parameter, collidingVariable, method));
}
}
}
});
});
}
}
} else {
RenameUtil.visitLocalsCollisions(method, newName, method.getBody(), null, new RenameUtil.CollidingVariableVisitor() {
public void visitCollidingElement(PsiVariable collidingVariable) {
if (!(collidingVariable instanceof PsiField) && !deletedParameters.contains(collidingVariable)) {
if (!(collidingVariable instanceof PsiField)) {
result.add(new NewParameterCollidesWithLocalUsageInfo(collidingVariable, collidingVariable, method));
}
}
@@ -332,20 +359,21 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor {
private void askToRemoveCovariantOverriders(Set<UsageInfo> usages) {
if (myManager.getEffectiveLanguageLevel().compareTo(LanguageLevel.JDK_1_5) >= 0) {
List<UsageInfo> covariantOverriderInfos = new ArrayList<UsageInfo>();
PsiSubstitutor substitutor = calculateSubstitutor(myChangeInfo.getMethod());
PsiType type;
try {
type = substitutor.substitute(myChangeInfo.newReturnType.getType(myChangeInfo.getMethod()));
}
catch (IncorrectOperationException e) {
LOG.error(e);
return;
}
for (Iterator<UsageInfo> iterator = usages.iterator(); iterator.hasNext();) {
UsageInfo usageInfo = iterator.next();
if (usageInfo.getElement() instanceof PsiMethod) {
PsiMethod overrider = (PsiMethod)usageInfo.getElement();
if (usageInfo instanceof OverriderUsageInfo) {
final OverriderUsageInfo info = (OverriderUsageInfo)usageInfo;
PsiMethod overrider = info.getElement();
PsiMethod baseMethod = info.getBaseMethod();
PsiSubstitutor substitutor = calculateSubstitutor(overrider, baseMethod);
PsiType type;
try {
type = substitutor.substitute(myChangeInfo.newReturnType.getType(myChangeInfo.getMethod()));
}
catch (IncorrectOperationException e) {
LOG.error(e);
return;
}
if (type.isAssignableFrom(overrider.getReturnType())) {
covariantOverriderInfos.add(usageInfo);
}
@@ -368,8 +396,6 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor {
protected void performRefactoring(UsageInfo[] usages) {
PsiElementFactory factory = myManager.getElementFactory();
List<UsageInfo> postponedUsages = new ArrayList<UsageInfo>();
try {
@@ -381,43 +407,48 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor {
myChangeInfo.newTypeElement = myChangeInfo.newReturnType.getType(myChangeInfo.getMethod());
}
myMethodsToBeChanged = new HashSet<PsiMethod>();
if (myGenerateDelegate) {
generateDelegate();
}
for (int i = 0; i < usages.length; i++) {
UsageInfo usage = usages[i];
if (!(usage instanceof DefaultConstructorImplicitUsageInfo) && usage.getElement() instanceof PsiMethod) {
myMethodsToBeChanged.add((PsiMethod) usage.getElement());
if (usage instanceof CallerUsageInfo) {
final CallerUsageInfo callerUsageInfo = (CallerUsageInfo)usage;
processCallerMethod(callerUsageInfo.getMethod(), null, callerUsageInfo.isToInsertParameter(), callerUsageInfo.isToInsertException());
} else if (usage instanceof OverriderUsageInfo) {
OverriderUsageInfo info = (OverriderUsageInfo)usage;
final PsiMethod method = info.getElement();
final PsiMethod baseMethod = info.getBaseMethod();
if (info.isOriginalOverrider()) {
processPrimaryMethod(method, baseMethod, false);
}
else {
processCallerMethod(method, baseMethod, info.isToInsertArgs(), info.isToCatchExceptions());
}
}
}
if (myChangeInfo.isExceptionSetOrOrderChanged) {
fixThrowsLists(getChangedExceptionInfo(myChangeInfo));
}
for (int i = 0; i < usages.length; i++) {
UsageInfo usage = usages[i];
if (!usage.getElement().isValid()) continue;
if (usage.getElement() == null) continue;
if (usage instanceof DefaultConstructorImplicitUsageInfo) {
addSuperCall(((DefaultConstructorImplicitUsageInfo) usage).getConstructor());
final DefaultConstructorImplicitUsageInfo defConstructorUsage = (DefaultConstructorImplicitUsageInfo)usage;
addSuperCall(defConstructorUsage.getConstructor(), defConstructorUsage.getBaseConstructor());
} else if (usage instanceof NoConstructorClassUsageInfo) {
addDefaultConstructor(((NoConstructorClassUsageInfo) usage).getPsiClass());
} else if (usage.getElement() instanceof PsiMethod) {
processMethod((PsiMethod) usage.getElement(), false);
} else if (usage.getElement() instanceof PsiJavaCodeReferenceElement) {
if (RefactoringUtil.isMethodUsage(usage.getElement())) {
processMethodUsage((PsiJavaCodeReferenceElement) usage.getElement(), myChangeInfo);
if (usage instanceof MethodCallUsageInfo) {
final MethodCallUsageInfo methodCallInfo = ((MethodCallUsageInfo)usage);
processMethodUsage(methodCallInfo.getElement(), myChangeInfo, methodCallInfo.isToChangeArguments(), methodCallInfo.isToCatchExceptions(), methodCallInfo.getReferencedMethod());
} else {
String newName = ((MyParameterUsageInfo) usage).newParameterName;
String oldName = ((MyParameterUsageInfo) usage).oldParameterName;
processParameterUsage((PsiReferenceExpression) usage.getElement(), oldName, newName);
}
} else if (usage.getElement() instanceof PsiEnumConstant) {
fixActualArgumentsList(((PsiEnumConstant)usage.getElement()).getArgumentList(), myChangeInfo, false);
fixActualArgumentsList(((PsiEnumConstant)usage.getElement()).getArgumentList(), myChangeInfo, true);
} else {
postponedUsages.add(usage);
}
@@ -425,7 +456,7 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor {
LOG.assertTrue(myChangeInfo.getMethod().isValid());
processMethod(myChangeInfo.getMethod(), true);
processPrimaryMethod(myChangeInfo.getMethod(), null, true);
for (Iterator<UsageInfo> i = postponedUsages.iterator(); i.hasNext();) {
UsageInfo usageInfo = i.next();
@@ -451,11 +482,6 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor {
}
}
fixJavadocsForChangedMethod(myChangeInfo.getMethod());
for (Iterator<PsiMethod> iterator = myMethodsToBeChanged.iterator(); iterator.hasNext();) {
PsiMethod method = iterator.next();
fixJavadocsForChangedMethod(method);
}
LOG.assertTrue(myChangeInfo.getMethod().isValid());
} catch (IncorrectOperationException e) {
LOG.error(e);
@@ -527,17 +553,17 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor {
defaultConstructor = (PsiMethod) CodeStyleManager.getInstance(myProject).reformat(defaultConstructor);
defaultConstructor = (PsiMethod) aClass.add(defaultConstructor);
defaultConstructor.getModifierList().setModifierProperty(VisibilityUtil.getVisibilityModifier(aClass.getModifierList()), true);
addSuperCall(defaultConstructor);
addSuperCall(defaultConstructor, null);
} else {
final PsiElement parent = aClass.getParent();
if (parent instanceof PsiNewExpression) {
final PsiExpressionList argumentList = ((PsiNewExpression) parent).getArgumentList();
fixActualArgumentsList(argumentList, myChangeInfo, false);
fixActualArgumentsList(argumentList, myChangeInfo, true);
}
}
}
private void addSuperCall(PsiMethod constructor) throws IncorrectOperationException {
private void addSuperCall(PsiMethod constructor, PsiMethod callee) throws IncorrectOperationException {
PsiExpressionStatement superCall = (PsiExpressionStatement) myFactory.createStatementFromText("super();", constructor);
PsiStatement[] statements = constructor.getBody().getStatements();
if (statements.length > 0) {
@@ -546,7 +572,7 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor {
superCall = (PsiExpressionStatement) constructor.getBody().add(superCall);
}
PsiMethodCallExpression callExpression = (PsiMethodCallExpression) superCall.getExpression();
processMethodUsage(callExpression.getMethodExpression(), myChangeInfo);
processMethodUsage(callExpression.getMethodExpression(), myChangeInfo, true, false, callee);
}
private PsiParameter createNewParameter(ParameterInfo newParm, PsiSubstitutor substitutor) throws IncorrectOperationException {
@@ -561,41 +587,51 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor {
return "Changing signature of " + UsageViewUtil.getDescriptiveName(myChangeInfo.getMethod());
}
private void processMethodUsage(PsiJavaCodeReferenceElement ref, ChangeInfo changeInfo)
private void processMethodUsage(PsiElement ref,
ChangeInfo changeInfo,
boolean toChangeArguments,
boolean toCatchExceptions,
PsiMethod callee)
throws IncorrectOperationException {
if (changeInfo.isNameChanged) {
PsiElement last = ref.getReferenceNameElement();
if (last instanceof PsiIdentifier && last.getText().equals(changeInfo.oldName)) {
last.replace(changeInfo.newNameIdentifier);
}
}
final PsiExpressionList list = RefactoringUtil.getArgumentListByMethodReference(ref);
boolean isSuperCall = false;
if (ref instanceof PsiReferenceExpression) {
final PsiExpression qualifierExpression = ((PsiReferenceExpression) ref).getQualifierExpression();
if (qualifierExpression instanceof PsiSuperExpression) {
for (Iterator<PsiMethod> iterator = myMethodsToBeChanged.iterator(); iterator.hasNext();) {
PsiElement element = iterator.next();
if (PsiTreeUtil.isAncestor(element, ref, false)) {
isSuperCall = true;
break;
}
if (ref instanceof PsiJavaCodeReferenceElement) {
PsiElement last = ((PsiJavaCodeReferenceElement)ref).getReferenceNameElement();
if (last instanceof PsiIdentifier && last.getText().equals(changeInfo.oldName)) {
last.replace(changeInfo.newNameIdentifier);
}
}
}
fixActualArgumentsList(list, changeInfo, isSuperCall);
final PsiMethod caller = RefactoringUtil.getEnclosingMethod(ref);
if (toChangeArguments) {
final PsiExpressionList list = RefactoringUtil.getArgumentListByMethodReference(ref);
boolean toInsertDefaultValue = !myPropagateParametersMethods.contains(caller);
if (toInsertDefaultValue && ref instanceof PsiReferenceExpression) {
final PsiExpression qualifierExpression = ((PsiReferenceExpression) ref).getQualifierExpression();
if (qualifierExpression instanceof PsiSuperExpression) {
toInsertDefaultValue = false;
}
}
if (changeInfo.isExceptionSetChanged) {
PsiClassType[] newExceptions = getChangedExceptionInfo(changeInfo);
fixExceptions(ref, newExceptions);
fixActualArgumentsList(list, changeInfo, toInsertDefaultValue);
}
if (toCatchExceptions) {
if (!(ref instanceof PsiReferenceExpression && ((PsiReferenceExpression)ref).getQualifierExpression() instanceof PsiSuperExpression)) {
if (needToCatchExceptions(caller)) {
PsiClassType[] newExceptions = callee != null ? getCalleeChangedExceptionInfo(callee) : getPrimaryChangedExceptionInfo(changeInfo);
fixExceptions(ref, newExceptions);
}
}
}
}
private PsiClassType[] getChangedExceptionInfo(ChangeInfo changeInfo) throws IncorrectOperationException {
private PsiClassType[] getCalleeChangedExceptionInfo(final PsiMethod callee) {
return callee.getThrowsList().getReferencedTypes(); //Callee method's throws list is already modified!
}
private PsiClassType[] getPrimaryChangedExceptionInfo(ChangeInfo changeInfo) throws IncorrectOperationException {
PsiClassType[] newExceptions = new PsiClassType[changeInfo.newExceptions.length];
for (int i = 0; i < newExceptions.length; i++) {
newExceptions[i] = (PsiClassType)changeInfo.newExceptions[i].myType.getType(myChangeInfo.getMethod()); //context really does not matter here
@@ -603,12 +639,9 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor {
return newExceptions;
}
private void fixExceptions(PsiJavaCodeReferenceElement ref, PsiClassType[] newExceptions) throws IncorrectOperationException {
fixThrowsLists(newExceptions);
private void fixExceptions(PsiElement ref, PsiClassType[] newExceptions) throws IncorrectOperationException {
//methods' throws lists are already modified, may use ExceptionUtil.collectUnhandledExceptions
newExceptions = filterCheckedExceptions(newExceptions);
//Now that methods' throws lists are modified, may use ExceptionUtil.collectUnhandledExceptions
PsiElement context = PsiTreeUtil.getParentOfType(ref, new Class[]{PsiTryStatement.class, PsiMethod.class});
if (context instanceof PsiTryStatement) {
@@ -686,7 +719,7 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor {
}
}
private void fixThrowsLists(PsiClassType[] newExceptions) throws IncorrectOperationException {
private void fixPrimaryThrowsLists(PsiMethod method, PsiClassType[] newExceptions) throws IncorrectOperationException {
PsiElementFactory elementFactory = myManager.getElementFactory();
PsiJavaCodeReferenceElement[] refs = new PsiJavaCodeReferenceElement[newExceptions.length];
for (int i = 0; i < refs.length; i++) {
@@ -694,11 +727,7 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor {
}
PsiReferenceList throwsList = elementFactory.createReferenceList(refs);
replaceThrowsList(myChangeInfo.getMethod(), throwsList);
for (Iterator<PsiMethod> iterator = myMethodsToBeChanged.iterator(); iterator.hasNext();) {
PsiMethod method = iterator.next();
replaceThrowsList(method, throwsList);
}
replaceThrowsList(method, throwsList);
}
private void replaceThrowsList(PsiMethod method, PsiReferenceList throwsList) throws IncorrectOperationException {
@@ -730,47 +759,66 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor {
return changeInfo.getMethod().getParameterList().getParameters().length - 1;
}
private void fixActualArgumentsList(PsiExpressionList list, ChangeInfo changeInfo, boolean isSuperCall) throws IncorrectOperationException {
//This methods works equally well for primary usages as well as for propagated callers' usages
private void fixActualArgumentsList(PsiExpressionList list,
ChangeInfo changeInfo,
boolean toInsertDefaultValue) throws IncorrectOperationException {
final PsiElementFactory factory = list.getManager().getElementFactory();
if (changeInfo.isParameterSetOrOrderChanged) {
final PsiExpression[] args = list.getExpressions();
final int nonVarargCount = getNonVarargCount(changeInfo, args);
final int varargCount = args.length - nonVarargCount;
final int newArgsLength;
final int newNonVarargCount;
if (changeInfo.retainsVarargs) {
newNonVarargCount = changeInfo.newParms.length - 1;
newArgsLength = newNonVarargCount + varargCount;
}
else if (changeInfo.obtainsVarags) {
newNonVarargCount = changeInfo.newParms.length - 1;
newArgsLength = newNonVarargCount;
}
else {
newNonVarargCount = changeInfo.newParms.length;
newArgsLength = changeInfo.newParms.length;
}
final PsiExpression[] newArgs = new PsiExpression[newArgsLength];
for (int i = 0; i < newNonVarargCount; i++) {
final ParameterInfo info = changeInfo.newParms[i];
final int index = info.oldParameterIndex;
if (index >= 0) {
newArgs[i] = args[index];
} else {
if (!isSuperCall) {
newArgs[i] = createDefaultValue(factory, info, list);
} else {
newArgs[i] = factory.createExpressionFromText(info.getName(), list);
if (changeInfo.isPropagationEnabled) {
final ParameterInfo[] createdParmsInfo = changeInfo.getCreatedParmsInfoWithoutVarargs();
for (int i = 0; i < createdParmsInfo.length; i++) {
ParameterInfo info = createdParmsInfo[i];
PsiExpression newArg;
if (toInsertDefaultValue) {
newArg = createDefaultValue(factory, info, list);
}
else {
newArg = factory.createExpressionFromText(info.getName(), list);
}
list.add(newArg);
}
}
final int newVarargCount = newArgsLength - newNonVarargCount;
LOG.assertTrue(newVarargCount == 0 || newVarargCount == varargCount);
for (int i = 0; i < newVarargCount; i++) {
newArgs[newNonVarargCount + i] = args[nonVarargCount + i];
else {
final PsiExpression[] args = list.getExpressions();
final int nonVarargCount = getNonVarargCount(changeInfo, args);
final int varargCount = args.length - nonVarargCount;
final int newArgsLength;
final int newNonVarargCount;
if (changeInfo.retainsVarargs) {
newNonVarargCount = changeInfo.newParms.length - 1;
newArgsLength = newNonVarargCount + varargCount;
}
else if (changeInfo.obtainsVarags) {
newNonVarargCount = changeInfo.newParms.length - 1;
newArgsLength = newNonVarargCount;
}
else {
newNonVarargCount = changeInfo.newParms.length;
newArgsLength = changeInfo.newParms.length;
}
final PsiExpression[] newArgs = new PsiExpression[newArgsLength];
for (int i = 0; i < newNonVarargCount; i++) {
final ParameterInfo info = changeInfo.newParms[i];
final int index = info.oldParameterIndex;
if (index >= 0) {
newArgs[i] = args[index];
} else {
if (toInsertDefaultValue) {
newArgs[i] = createDefaultValue(factory, info, list);
} else {
newArgs[i] = factory.createExpressionFromText(info.getName(), list);
}
}
}
final int newVarargCount = newArgsLength - newNonVarargCount;
LOG.assertTrue(newVarargCount == 0 || newVarargCount == varargCount);
for (int i = 0; i < newVarargCount; i++) {
newArgs[newNonVarargCount + i] = args[nonVarargCount + i];
}
ChangeSignatureUtil.synchronizeList(list, Arrays.asList(newArgs), ExpressionList.INSTANCE, changeInfo.toRemoveParm);
}
ChangeSignatureUtil.synchronizeList(list, Arrays.asList(newArgs), ExpressionList.INSTANCE, changeInfo.toRemoveParm);
}
}
@@ -814,7 +862,47 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor {
}
}
private void processMethod(PsiMethod method, boolean isOriginal) throws IncorrectOperationException {
private void processCallerMethod(PsiMethod caller,
PsiMethod baseMethod,
boolean toInsertParams,
boolean toInsertThrows) throws IncorrectOperationException {
LOG.assertTrue(toInsertParams || toInsertThrows);
if (toInsertParams) {
List<PsiParameter> newParameters = new ArrayList<PsiParameter>();
newParameters.addAll(Arrays.asList(caller.getParameterList().getParameters()));
final ParameterInfo[] primaryNewParms = myChangeInfo.newParms;
PsiSubstitutor substitutor = baseMethod == null ? PsiSubstitutor.EMPTY : calculateSubstitutor(caller, baseMethod);
for (int i = 0; i < primaryNewParms.length; i++) {
if (primaryNewParms[i].oldParameterIndex < 0) newParameters.add(createNewParameter(primaryNewParms[i], substitutor));
}
PsiParameter[] arrayed = newParameters.toArray(new PsiParameter[newParameters.size()]);
boolean[] toRemoveParm = new boolean[arrayed.length];
Arrays.fill(toRemoveParm, false);
resolveParameterVsFieldsConflicts(arrayed, caller, caller.getParameterList(), toRemoveParm);
}
if (toInsertThrows) {
List<PsiJavaCodeReferenceElement> newThrowns = new ArrayList<PsiJavaCodeReferenceElement>();
final PsiReferenceList throwsList = caller.getThrowsList();
newThrowns.addAll(Arrays.asList(throwsList.getReferenceElements()));
final ThrownExceptionInfo[] primaryNewExns = myChangeInfo.newExceptions;
for (int i = 0; i < primaryNewExns.length; i++) {
if (primaryNewExns[i].oldIndex < 0) {
final PsiClassType type = (PsiClassType)primaryNewExns[i].createType(caller);
final PsiJavaCodeReferenceElement ref = caller.getManager().getElementFactory().createReferenceElementByType(type);
newThrowns.add(ref);
}
}
PsiJavaCodeReferenceElement[] arrayed = newThrowns.toArray(new PsiJavaCodeReferenceElement[newThrowns.size()]);
boolean[] toRemoveParm = new boolean[arrayed.length];
Arrays.fill(toRemoveParm, false);
ChangeSignatureUtil.synchronizeList(throwsList, Arrays.asList(arrayed), ThrowsList.INSTANCE, toRemoveParm);
}
}
private void processPrimaryMethod(PsiMethod method,
PsiMethod baseMethod,
boolean isOriginal) throws IncorrectOperationException {
PsiElementFactory factory = method.getManager().getElementFactory();
if (myChangeInfo.isVisibilityChanged) {
@@ -826,8 +914,6 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor {
RefactoringUtil.setVisibility(modifierList, highestVisibility);
}
final PsiSubstitutor substitutor = calculateSubstitutor(method);
if (myChangeInfo.isNameChanged) {
final EjbMethodRole role = J2EERolesUtil.getEjbRole(method);
if (role instanceof EjbImplMethodRole && myChangeInfo.ejbRole instanceof EjbDeclMethodRole) {
@@ -852,9 +938,9 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor {
}
}
if (myChangeInfo.isReturnTypeChanged) {
//TODO : normalize brackets!
final PsiSubstitutor substitutor = baseMethod == null ? PsiSubstitutor.EMPTY : calculateSubstitutor(method, baseMethod);
if (myChangeInfo.isReturnTypeChanged) {
final PsiType returnType = substitutor.substitute(myChangeInfo.newTypeElement);
method.getReturnTypeElement().replace(factory.createTypeElement(returnType));
}
@@ -888,30 +974,41 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor {
}
}
List<FieldConflictsResolver> conflictResolvers = new ArrayList<FieldConflictsResolver>();
final ParameterInfo[] newParmsInfo = myChangeInfo.newParms;
for (int i = 0; i < newParmsInfo.length; i++) {
ParameterInfo parameterInfo = newParmsInfo[i];
conflictResolvers.add(new FieldConflictsResolver(parameterInfo.getName(), method.getBody()));
resolveParameterVsFieldsConflicts(newParms, method, list, myChangeInfo.toRemoveParm);
fixJavadocsForChangedMethod(method);
if (myChangeInfo.isExceptionSetOrOrderChanged) {
final PsiClassType[] newExceptions = getPrimaryChangedExceptionInfo(myChangeInfo);
fixPrimaryThrowsLists(method, newExceptions);
}
ChangeSignatureUtil.synchronizeList(list, Arrays.asList(newParms), ParameterList.INSTANCE, myChangeInfo.toRemoveParm);
}
private void resolveParameterVsFieldsConflicts(final PsiParameter[] newParms,
final PsiMethod method,
final PsiParameterList list,
boolean[] toRemoveParm) throws IncorrectOperationException {
List<FieldConflictsResolver> conflictResolvers = new ArrayList<FieldConflictsResolver>();
for (int i = 0; i < newParms.length; i++) {
PsiParameter parameter = newParms[i];
conflictResolvers.add(new FieldConflictsResolver(parameter.getName(), method.getBody()));
}
ChangeSignatureUtil.synchronizeList(list, Arrays.asList(newParms), ParameterList.INSTANCE, toRemoveParm);
for (int i = 0; i < conflictResolvers.size(); i++) {
FieldConflictsResolver fieldConflictsResolver = conflictResolvers.get(i);
fieldConflictsResolver.fix();
}
}
private PsiSubstitutor calculateSubstitutor(PsiMethod method) {
private PsiSubstitutor calculateSubstitutor(PsiMethod derivedMethod, PsiMethod baseMethod) {
PsiSubstitutor substitutor;
if (method.getManager().areElementsEquivalent(method, myChangeInfo.getMethod())) {
if (derivedMethod.getManager().areElementsEquivalent(derivedMethod, baseMethod)) {
substitutor = PsiSubstitutor.EMPTY;
} else {
final PsiClass sourceClass = myChangeInfo.getMethod().getContainingClass();
final PsiClass containingClass = method.getContainingClass();
if(sourceClass != null && containingClass != null && InheritanceUtil.isInheritorOrSelf(containingClass, sourceClass, true)) {
final PsiSubstitutor superClassSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(sourceClass, containingClass, PsiSubstitutor.EMPTY);
final MethodSignature superMethodSignature = myChangeInfo.getMethod().getSignature(superClassSubstitutor);
final MethodSignature methodSignature = method.getSignature(PsiSubstitutor.EMPTY);
final PsiClass baseClass = baseMethod.getContainingClass();
final PsiClass derivedClass = derivedMethod.getContainingClass();
if(baseClass != null && derivedClass != null && InheritanceUtil.isInheritorOrSelf(derivedClass, baseClass, true)) {
final PsiSubstitutor superClassSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(baseClass, derivedClass, PsiSubstitutor.EMPTY);
final MethodSignature superMethodSignature = baseMethod.getSignature(superClassSubstitutor);
final MethodSignature methodSignature = derivedMethod.getSignature(PsiSubstitutor.EMPTY);
final PsiSubstitutor superMethodSubstitutor = MethodSignatureUtil.getSuperMethodSignatureSubstitutor(methodSignature, superMethodSignature);
substitutor = superMethodSubstitutor != null ? superMethodSubstitutor : superClassSubstitutor;
} else {
@@ -1007,4 +1104,11 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor {
}
}
private static class ThrowsList implements ChangeSignatureUtil.ChildrenGenerator<PsiReferenceList, PsiJavaCodeReferenceElement> {
public static final ThrowsList INSTANCE = new ThrowsList();
private ThrowsList() {}
public List<PsiJavaCodeReferenceElement> getChildren(PsiReferenceList throwsList) {
return Arrays.asList(throwsList.getReferenceElements());
}
}
}
@@ -0,0 +1,48 @@
package com.intellij.refactoring.changeSignature;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.*;
import com.intellij.usageView.UsageInfo;
/**
* @author ven
*/
public class MethodCallUsageInfo extends UsageInfo {
private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.changeSignature.MethodCallUsageInfo");
private final boolean myToChangeArguments;
private final boolean myToCatchExceptions;
private final PsiMethod myReferencedMethod;
public boolean isToCatchExceptions() {
return myToCatchExceptions;
}
public boolean isToChangeArguments() {
return myToChangeArguments;
}
public MethodCallUsageInfo(final PsiElement ref, boolean isToChangeArguments, boolean isToCatchExceptions) {
super(ref);
myToChangeArguments = isToChangeArguments;
myToCatchExceptions = isToCatchExceptions;
myReferencedMethod = resolveMethod(ref);
}
private PsiMethod resolveMethod(final PsiElement ref) {
if (ref instanceof PsiEnumConstant) return ((PsiEnumConstant)ref).resolveConstructor();
PsiElement parent = ref.getParent();
if (parent instanceof PsiCall) {
return ((PsiCall)parent).resolveMethod();
}
else if (parent instanceof PsiAnonymousClass) {
return ((PsiNewExpression)parent.getParent()).resolveConstructor();
}
LOG.assertTrue(false, "Unknown reference");
return null;
}
public PsiMethod getReferencedMethod() {
return myReferencedMethod;
}
}
@@ -0,0 +1,43 @@
package com.intellij.refactoring.changeSignature;
import com.intellij.psi.PsiMethod;
import com.intellij.usageView.UsageInfo;
/**
* @author ven
*/
public class OverriderUsageInfo extends UsageInfo {
private final PsiMethod myBaseMethod;
private final boolean myToInsertArgs;
private final boolean myToCatchExceptions;
private boolean myIsOriginalOverrider;
public OverriderUsageInfo(final PsiMethod method, PsiMethod baseMethod, boolean isOriginalOverrider,
boolean toInsertArgs, boolean toCatchExceptions) {
super(method);
myBaseMethod = baseMethod;
myToInsertArgs = toInsertArgs;
myToCatchExceptions = toCatchExceptions;
myIsOriginalOverrider = isOriginalOverrider;
}
public PsiMethod getBaseMethod() {
return myBaseMethod;
}
public PsiMethod getElement() {
return (PsiMethod)super.getElement();
}
public boolean isOriginalOverrider() {
return myIsOriginalOverrider;
}
public boolean isToCatchExceptions() {
return myToCatchExceptions;
}
public boolean isToInsertArgs() {
return myToInsertArgs;
}
}
@@ -1,34 +1,37 @@
package com.intellij.refactoring.changeSignature.inCallers;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Splitter;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiFile;
import com.intellij.openapi.ui.Splitter;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.ui.*;
import com.intellij.util.Alarm;
import com.intellij.util.ui.Tree;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiMethod;
import com.intellij.refactoring.changeSignature.ChangeSignatureHandler;
import com.intellij.ui.CheckboxTree;
import com.intellij.ui.CheckedTreeNode;
import com.intellij.ui.EditorTextField;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.util.Alarm;
import com.intellij.util.containers.HashSet;
import com.intellij.util.ui.Tree;
import javax.swing.*;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.*;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import java.awt.*;
import java.util.Enumeration;
import java.util.ArrayList;
import java.util.Set;
/**
* @author ven
*/
public abstract class CallerChooser extends DialogWrapper {
private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.changeSignature.inCallers.CallerChooser");
PsiMethod myMethod;
private EditorTextField myEditorField;
private Alarm myAlarm = new Alarm();
@@ -129,20 +132,18 @@ public abstract class CallerChooser extends DialogWrapper {
}
}
private PsiMethod[] getSelectedMethods () {
private void getSelectedMethods(Set<PsiMethod> methods) {
MethodNode node = myRoot;
ArrayList<PsiMethod> result = new ArrayList<PsiMethod>();
getSelectedMethodsInner(node, result);
return result.toArray(new PsiMethod[result.size()]);
getSelectedMethodsInner(node, methods);
methods.remove(node.getMethod());
}
private void getSelectedMethodsInner(final MethodNode node, final ArrayList<PsiMethod> methods) {
if (node.isChecked()) {
methods.add(node.getMethod());
} else {
private void getSelectedMethodsInner(final MethodNode node, final Set<PsiMethod> allMethods) {
allMethods.add(node.getMethod());
if (!node.isChecked()) {
final Enumeration children = node.children();
while (children.hasMoreElements()) {
getSelectedMethodsInner((MethodNode)children.nextElement(), methods);
getSelectedMethodsInner((MethodNode)children.nextElement(), allMethods);
}
}
}
@@ -153,8 +154,8 @@ public abstract class CallerChooser extends DialogWrapper {
return;
}
final PsiMethod[] selectedMethods = getSelectedMethods();
LOG.assertTrue(selectedMethods.length > 0);
final Set<PsiMethod> selectedMethods = new HashSet<PsiMethod>();
getSelectedMethods(selectedMethods);
callersChosen(selectedMethods);
super.doOKAction();
}
@@ -170,5 +171,5 @@ public abstract class CallerChooser extends DialogWrapper {
return true;
}
abstract protected void callersChosen (PsiMethod[] callers);
abstract protected void callersChosen(Set<PsiMethod> allCallers);
}
@@ -70,7 +70,8 @@ public class MethodNode extends CheckedTreeNode {
List<PsiMethod> callers = new ArrayList<PsiMethod>();
for (int i = 0; i < refs.length; i++) {
final PsiElement element = refs[i].getElement();
if (element instanceof PsiReferenceExpression && element.getParent() instanceof PsiMethodCallExpression) {
if (!(element instanceof PsiReferenceExpression) ||
!(((PsiReferenceExpression)element).getQualifierExpression() instanceof PsiSuperExpression)) {
final PsiElement enclosingContext = PsiTreeUtil.getParentOfType(element, new Class[]{PsiMethod.class, PsiClass.class});
if (enclosingContext instanceof PsiMethod) callers.add((PsiMethod)enclosingContext);
}
@@ -95,8 +96,10 @@ public class MethodNode extends CheckedTreeNode {
);
buffer.append(methodText);
final int style = isEnabled() ? SimpleTextAttributes.STYLE_PLAIN : SimpleTextAttributes.STYLE_STRIKEOUT;
renderer.append(buffer.toString(), new SimpleTextAttributes(style, IdeaUIManager.getTreeForegroung()));
final SimpleTextAttributes attributes = isEnabled() ?
new SimpleTextAttributes(SimpleTextAttributes.STYLE_PLAIN, IdeaUIManager.getTreeForegroung()) :
SimpleTextAttributes.EXCLUDED_ATTRIBUTES;
renderer.append(buffer.toString(), attributes);
final String packageName = getPackageName(myMethod.getContainingClass());
renderer.append(" (" + packageName + ")", new SimpleTextAttributes(SimpleTextAttributes.STYLE_ITALIC, Color.GRAY));
@@ -479,13 +479,13 @@ public class PullUpHelper {
// check default constructor
if (constructor == null || constructor.getParameterList().getParameters().length == 0) {
RefactoringUtil.visitImplicitSuperConstructorUsages(mySourceClass, new RefactoringUtil.ImplicitConstructorUsageVisitor() {
public void visitConstructor(PsiMethod constructor) {
public void visitConstructor(PsiMethod constructor, PsiMethod baseConstructor) {
referencingSubConstructors.add(constructor);
}
public void visitClassWithoutConstructors(PsiClass aClass) {
}
});
}, myTargetSuperClass);
}
}
@@ -102,7 +102,7 @@ public class ReplaceConstructorWithFactoryProcessor extends BaseRefactoringProce
if (myConstructor != null && myConstructor.getParameterList().getParameters().length == 0) {
RefactoringUtil.visitImplicitConstructorUsages(getConstructorContainingClass(), new RefactoringUtil.ImplicitConstructorUsageVisitor() {
public void visitConstructor(PsiMethod constructor) {
public void visitConstructor(PsiMethod constructor, PsiMethod baseConstructor) {
myNonNewConstructorUsages.add(constructor);
}
@@ -394,8 +394,9 @@ public class RefactoringUtil {
PsiElement prev = null;
while (true) {
if (parent instanceof PsiClass) {
if (!(parent instanceof PsiAnonymousClass && ((PsiAnonymousClass)parent).getArgumentList() == prev))
if (!(parent instanceof PsiAnonymousClass && ((PsiAnonymousClass)parent).getArgumentList() == prev)) {
return (PsiClass)parent;
}
}
prev = parent;
parent = parent.getContext();
@@ -406,8 +407,9 @@ public class RefactoringUtil {
public static PsiClass getThisResolveClass(final PsiReferenceExpression place) {
final ResolveResult resolveResult = place.advancedResolve(false);
final PsiElement scope = resolveResult.getCurrentFileResolveScope();
if (scope instanceof PsiClass)
return (PsiClass) scope;
if (scope instanceof PsiClass) {
return (PsiClass)scope;
}
return null;
/*
PsiElement parent = place.getContext();
@@ -435,6 +437,11 @@ public class RefactoringUtil {
return parent instanceof PsiNewExpression ? (PsiNewExpression)parent : null;
}
public static final PsiMethod getEnclosingMethod (PsiElement element) {
final PsiElement container = PsiTreeUtil.getParentOfType(element, new Class[]{PsiMethod.class, PsiClass.class});
return container instanceof PsiMethod ? ((PsiMethod)container) : null;
}
public static void renameVariableReferences(PsiVariable variable, String newName, SearchScope scope)
throws IncorrectOperationException {
PsiManager manager = variable.getManager();
@@ -764,7 +771,8 @@ public class RefactoringUtil {
}
}
public static PsiExpressionList getArgumentListByMethodReference(PsiJavaCodeReferenceElement ref) {
public static PsiExpressionList getArgumentListByMethodReference(PsiElement ref) {
if (ref instanceof PsiEnumConstant) return ((PsiEnumConstant)ref).getArgumentList();
PsiElement parent = ref.getParent();
if (parent instanceof PsiCall) {
return ((PsiCall)parent).getArgumentList();
@@ -1051,30 +1059,41 @@ public class RefactoringUtil {
for (int i = 0; i < inheritors.length; i++) {
PsiClass inheritor = inheritors[i];
visitImplicitSuperConstructorUsages(inheritor, implicitConstructorUsageVistor);
visitImplicitSuperConstructorUsages(inheritor, implicitConstructorUsageVistor, aClass);
}
}
public static void visitImplicitSuperConstructorUsages(PsiClass subClass,
final ImplicitConstructorUsageVisitor implicitConstructorUsageVistor) {
final ImplicitConstructorUsageVisitor implicitConstructorUsageVistor,
PsiClass superClass) {
final PsiMethod baseDefaultConstructor = findDefaultConstructor (superClass);
final PsiMethod[] constructors = subClass.getConstructors();
if (constructors.length > 0) {
for (int j = 0; j < constructors.length; j++) {
PsiMethod constructor = constructors[j];
final PsiStatement[] statements = constructor.getBody().getStatements();
if (statements.length < 1 || !isSuperOrThisCall(statements[0], true, true)) {
implicitConstructorUsageVistor.visitConstructor(constructor);
implicitConstructorUsageVistor.visitConstructor(constructor, baseDefaultConstructor);
}
}
}
else {
implicitConstructorUsageVistor.visitClassWithoutConstructors(subClass);
// visitImplicitConstructorUsages(inheritor, implicitConstructorUsageVistor);
}
}
private static PsiMethod findDefaultConstructor(final PsiClass aClass) {
final PsiMethod[] constructors = aClass.getConstructors();
for (int i = 0; i < constructors.length; i++) {
PsiMethod constructor = constructors[i];
if (constructor.getParameterList().getParameters().length == 0) return constructor;
}
return null;
}
public static interface ImplicitConstructorUsageVisitor {
void visitConstructor(PsiMethod constructor);
void visitConstructor(PsiMethod constructor, PsiMethod baseConstructor);
void visitClassWithoutConstructors(PsiClass aClass);
}
@@ -8,13 +8,19 @@ import com.intellij.usageView.UsageInfo;
*/
public class DefaultConstructorImplicitUsageInfo extends UsageInfo {
private final PsiMethod myOverridingConstructor;
private final PsiMethod myBaseConstructor;
public DefaultConstructorImplicitUsageInfo(PsiMethod overridingConstructor) {
public DefaultConstructorImplicitUsageInfo(PsiMethod overridingConstructor, PsiMethod baseConstructor) {
super(overridingConstructor);
myOverridingConstructor = overridingConstructor;
myBaseConstructor = baseConstructor;
}
public PsiMethod getConstructor() {
return myOverridingConstructor;
}
public PsiMethod getBaseConstructor() {
return myBaseConstructor;
}
}
@@ -2,21 +2,22 @@ package com.intellij.refactoring.util.usageInfo;
import com.intellij.psi.*;
import com.intellij.refactoring.util.RefactoringUtil;
import com.intellij.usageView.UsageInfo;
import java.util.ArrayList;
public class DefaultConstructorUsageCollector implements RefactoringUtil.ImplicitConstructorUsageVisitor {
private final ArrayList myUsages;
private final ArrayList<UsageInfo> myUsages;
public void visitConstructor(PsiMethod constructor) {
myUsages.add(new DefaultConstructorImplicitUsageInfo(constructor));
public void visitConstructor(PsiMethod constructor, PsiMethod baseConstructor) {
myUsages.add(new DefaultConstructorImplicitUsageInfo(constructor, baseConstructor));
}
public void visitClassWithoutConstructors(PsiClass aClass) {
myUsages.add(new NoConstructorClassUsageInfo(aClass));
}
public DefaultConstructorUsageCollector(ArrayList result) {
public DefaultConstructorUsageCollector(ArrayList<UsageInfo> result) {
myUsages = result;
}
}
@@ -10,9 +10,6 @@ import com.intellij.refactoring.changeSignature.ChangeSignatureProcessor;
import com.intellij.refactoring.changeSignature.ParameterInfo;
import com.intellij.refactoring.changeSignature.ThrownExceptionInfo;
import com.intellij.util.IncorrectOperationException;
import com.intellij.idea.IdeaTestUtil;
import java.util.Calendar;
/**
* @author dsl