String result = "";
try {
for (ParameterInfoImpl info : infos) {
- PsiType type = info.getTypeWrapper().getType(context, context.getManager());
+ PsiType type = info.createType(context, context.getManager());
if (result.length() != 0) {
result += ", ";
}
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.command.UndoConfirmationPolicy;
import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.editor.EditorModificationUtil;
+import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.editor.highlighter.HighlighterIterator;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.refactoring.RefactoringActionHandler;
+import com.intellij.refactoring.changeSignature.ChangeSignatureHandler;
+import com.intellij.refactoring.changeSignature.JavaChangeSignatureHandler;
import com.intellij.refactoring.extractInterface.ExtractInterfaceHandler;
import com.intellij.refactoring.extractMethod.ExtractMethodHandler;
import com.intellij.refactoring.extractSuperclass.ExtractSuperclassHandler;
return new ExtractSuperclassHandler();
}
+ @Override
+ public ChangeSignatureHandler getChangeSignatureHandler() {
+ return new JavaChangeSignatureHandler();
+ }
+
public static boolean mayRenameInplace(PsiElement elementToRename, final PsiElement nameSuggestionContext) {
if (!(elementToRename instanceof PsiVariable)) return false;
if (nameSuggestionContext != null && nameSuggestionContext.getContainingFile() != elementToRename.getContainingFile()) return false;
import com.intellij.psi.impl.source.jsp.jspJava.JspxImportStatement;
import com.intellij.psi.impl.source.tree.TreeElement;
import com.intellij.psi.statistics.JavaStatisticsManager;
-import com.intellij.psi.util.*;
+import com.intellij.psi.util.InheritanceUtil;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.util.PsiUtil;
+import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.HashSet;
*/
package com.intellij.refactoring.actions;
+import com.intellij.lang.Language;
+import com.intellij.lang.LanguageRefactoringSupport;
import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.ScrollType;
+import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.refactoring.RefactoringActionHandler;
import com.intellij.refactoring.changeSignature.ChangeSignatureHandler;
-import com.intellij.refactoring.changeSignature.ChangeSignatureTargetUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
public class ChangeSignatureAction extends BaseRefactoringAction {
public boolean isAvailableInEditorOnly() {
protected boolean isAvailableOnElementInEditor(final PsiElement element, final Editor editor) {
final Document document = editor.getDocument();
final PsiFile file = PsiDocumentManager.getInstance(element.getProject()).getPsiFile(document);
- if (file != null && ChangeSignatureTargetUtil.findTargetMember(file, editor) != null) {
- return true;
+ if (file == null) return false;
+ PsiElement targetMember = findTargetMember(file, editor);
+ if (targetMember == null) return false;
+ final ChangeSignatureHandler targetHandler = getChangeSignatureHandler(targetMember.getLanguage());
+ if (targetHandler == null) return false;
+ return true;
+ }
+
+ @Nullable
+ private static PsiElement findTargetMember(PsiFile file, Editor editor) {
+ final PsiElement element = file.findElementAt(editor.getCaretModel().getOffset());
+ final PsiElement targetMember = findTargetMember(element);
+ if (targetMember != null) return targetMember;
+
+ final PsiReference reference = file.findReferenceAt(editor.getCaretModel().getOffset());
+ if (reference == null) return null;
+ return reference.resolve();
+ }
+
+ @Nullable
+ private static PsiElement findTargetMember(@Nullable PsiElement element) {
+ if (element == null) return null;
+ final ChangeSignatureHandler fileHandler = getChangeSignatureHandler(element.getLanguage());
+ if (fileHandler != null) {
+ final PsiElement targetMember = fileHandler.findTargetMember(element);
+ if (targetMember != null) return targetMember;
}
- return element instanceof PsiMethod || element instanceof PsiClass;
+ final PsiReference reference = element.getReference();
+ if (reference == null) return null;
+ return reference.resolve();
}
public RefactoringActionHandler getHandler(DataContext dataContext) {
- return new ChangeSignatureHandler();
+ final Language language = LangDataKeys.LANGUAGE.getData(dataContext);
+ if (language != null) {
+ return new RefactoringActionHandler() {
+ public void invoke(@NotNull Project project, Editor editor, PsiFile file, DataContext dataContext) {
+ editor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE);
+ final PsiElement targetMember = findTargetMember(file, editor);
+ if (targetMember == null) return;
+ final ChangeSignatureHandler handler = getChangeSignatureHandler(targetMember.getLanguage());
+ if (handler == null) return;
+ handler.invoke(project, new PsiElement[]{targetMember}, dataContext);
+ }
+
+ public void invoke(@NotNull Project project, @NotNull PsiElement[] elements, DataContext dataContext) {
+ if (elements.length != 1) return;
+ final PsiElement targetMember = findTargetMember(elements[0]);
+ if (targetMember == null) return;
+ final ChangeSignatureHandler handler = getChangeSignatureHandler(targetMember.getLanguage());
+ if (handler == null) return;
+ handler.invoke(project, new PsiElement[]{targetMember}, dataContext);
+ }
+ };
+ }
+ return null;
+ }
+
+ @Override
+ protected boolean isAvailableForLanguage(Language language) {
+ return getChangeSignatureHandler(language) != null;
+ }
+
+ @Nullable
+ private static ChangeSignatureHandler getChangeSignatureHandler(Language language) {
+ return LanguageRefactoringSupport.INSTANCE.forLanguage(language).getChangeSignatureHandler();
}
}
panel.add(subPanel, BorderLayout.CENTER);
JPanel subPanel1 = new JPanel(new GridBagLayout());
- subPanel1.add(createExceptionsPanel(), new GridBagConstraints(0, 0, 1, 1, 0.5, 0.0, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(4,4,4,0), 0, 0));
- subPanel1.add(createSignaturePanel(), new GridBagConstraints(1, 0, 1, 1, 0.5, 0.0, GridBagConstraints.EAST, GridBagConstraints.BOTH, new Insets(4,0,4,4), 0, 0));
+ subPanel1.add(createExceptionsPanel(),
+ new GridBagConstraints(0, 0, 1, 1, 0.5, 0.0, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(4, 4, 4, 0), 0,
+ 0));
+ subPanel1.add(createSignaturePanel(),
+ new GridBagConstraints(1, 0, 1, 1, 0.5, 0.0, GridBagConstraints.EAST, GridBagConstraints.BOTH, new Insets(4, 0, 4, 4), 0,
+ 0));
panel.add(subPanel1, BorderLayout.SOUTH);
return panel;
final PsiClassType[] types = myMethod.getThrowsList().getReferencedTypes();
if (thrownExceptions.length <= types.length) return false;
for (int i = 0; i < types.length; i++) {
- if (thrownExceptions[i].oldIndex != i) return false;
+ if (thrownExceptions[i].getOldIndex() != i) return false;
}
return true;
}
--- /dev/null
+/*
+ * 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 com.intellij.refactoring.changeSignature;
+
+import com.intellij.psi.PsiElement;
+import com.intellij.usageView.UsageInfo;
+
+/**
+* @author Maxim.Medvedev
+*/
+public class ChangeSignatureParameterUsageInfo extends UsageInfo {
+ public final String oldParameterName;
+ public final String newParameterName;
+
+ public ChangeSignatureParameterUsageInfo(PsiElement element, String oldParameterName, String newParameterName) {
+ super(element);
+ this.oldParameterName = oldParameterName;
+ this.newParameterName = newParameterName;
+ }
+}
*/
package com.intellij.refactoring.changeSignature;
-import com.intellij.codeInsight.ExceptionUtil;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
-import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Ref;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
-import com.intellij.psi.codeStyle.JavaCodeStyleManager;
-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;
-import com.intellij.psi.search.searches.MethodReferencesSearch;
-import com.intellij.psi.search.searches.OverridingMethodsSearch;
-import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.util.*;
-import com.intellij.psi.xml.XmlElement;
import com.intellij.refactoring.BaseRefactoringProcessor;
import com.intellij.refactoring.RefactoringBundle;
-import com.intellij.refactoring.rename.JavaUnresolvableLocalCollisionDetector;
import com.intellij.refactoring.rename.RenameUtil;
-import com.intellij.refactoring.rename.UnresolvableCollisionUsageInfo;
import com.intellij.refactoring.ui.ConflictsDialog;
-import com.intellij.refactoring.util.*;
-import com.intellij.refactoring.util.usageInfo.DefaultConstructorImplicitUsageInfo;
-import com.intellij.refactoring.util.usageInfo.NoConstructorClassUsageInfo;
+import com.intellij.refactoring.util.CanonicalTypes;
import com.intellij.usageView.UsageInfo;
import com.intellij.usageView.UsageViewDescriptor;
import com.intellij.usageView.UsageViewUtil;
import com.intellij.util.containers.HashSet;
import com.intellij.util.containers.MultiMap;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.util.*;
public class ChangeSignatureProcessor extends BaseRefactoringProcessor {
private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.changeSignature.ChangeSignatureProcessor");
- @Modifier private final String myNewVisibility;
- private final ChangeInfoImpl myChangeInfo;
+ private final JavaChangeInfoImpl myChangeInfo;
private final PsiManager myManager;
- private final PsiElementFactory myFactory;
- private final boolean myGenerateDelegate;
- private final Set<PsiMethod> myPropagateParametersMethods;
- private final Set<PsiMethod> myPropagateExceptionsMethods;
public ChangeSignatureProcessor(Project project,
PsiMethod method,
public ChangeSignatureProcessor(Project project,
PsiMethod method,
boolean generateDelegate,
- String newVisibility,
+ @Modifier String newVisibility,
String newName,
CanonicalTypes.Type newType,
@NotNull ParameterInfoImpl[] parameterInfo,
Set<PsiMethod> propagateExceptionsMethods) {
super(project);
myManager = PsiManager.getInstance(project);
- myFactory = JavaPsiFacade.getInstance(myManager.getProject()).getElementFactory();
- myGenerateDelegate = generateDelegate;
- myPropagateParametersMethods = propagateParametersMethods != null ? propagateParametersMethods : new HashSet<PsiMethod>();
- myPropagateExceptionsMethods = propagateExceptionsMethods != null ? propagateExceptionsMethods : new HashSet<PsiMethod>();
+ Set<PsiMethod> myPropagateParametersMethods =
+ propagateParametersMethods != null ? propagateParametersMethods : new HashSet<PsiMethod>();
+ Set<PsiMethod> myPropagateExceptionsMethods =
+ propagateExceptionsMethods != null ? propagateExceptionsMethods : new HashSet<PsiMethod>();
LOG.assertTrue(method.isValid());
if (newVisibility == null) {
- myNewVisibility = VisibilityUtil.getVisibilityModifier(method.getModifierList());
- } else {
- myNewVisibility = newVisibility;
- }
+ newVisibility = VisibilityUtil.getVisibilityModifier(method.getModifierList());
+ }
- myChangeInfo = new ChangeInfoImpl(myNewVisibility, method, newName, newType, parameterInfo, thrownExceptions);
+ myChangeInfo = new JavaChangeInfoImpl(newVisibility, method, newName, newType, parameterInfo, thrownExceptions, generateDelegate, myPropagateParametersMethods, myPropagateExceptionsMethods);
LOG.assertTrue(myChangeInfo.getMethod().isValid());
}
@NotNull
protected UsageInfo[] findUsages() {
- ArrayList<UsageInfo> result = new ArrayList<UsageInfo>();
- final PsiMethod method = myChangeInfo.getMethod();
-
- findSimpleUsages(method, result);
-
- final UsageInfo[] usageInfos = result.toArray(new UsageInfo[result.size()]);
- return UsageViewUtil.removeDuplicatedUsages(usageInfos);
- }
-
- 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) {
-
- GlobalSearchScope projectScope = GlobalSearchScope.projectScope(myProject);
- PsiMethod[] overridingMethods = OverridingMethodsSearch.search(method, method.getUseScope(), true).toArray(PsiMethod.EMPTY_ARRAY);
-
- for (PsiMethod overridingMethod : overridingMethods) {
- result.add(new OverriderUsageInfo(overridingMethod, method, isOriginal, isToModifyArgs, isToThrowExceptions));
- }
-
- boolean needToChangeCalls = !myGenerateDelegate && (myChangeInfo.isNameChanged || myChangeInfo.isParameterSetOrOrderChanged || myChangeInfo.isExceptionSetOrOrderChanged || myChangeInfo.isVisibilityChanged/*for checking inaccessible*/);
- if (needToChangeCalls) {
- int parameterCount = method.getParameterList().getParametersCount();
-
- PsiReference[] refs = MethodReferencesSearch.search(method, projectScope, true).toArray(PsiReference.EMPTY_ARRAY);
- for (PsiReference ref : refs) {
- PsiElement element = ref.getElement();
- boolean isToCatchExceptions = isToThrowExceptions && needToCatchExceptions(RefactoringUtil.getEnclosingMethod(element));
- if (!isToCatchExceptions) {
- if (RefactoringUtil.isMethodUsage(element)) {
- PsiExpressionList list = RefactoringUtil.getArgumentListByMethodReference(element);
- if (!method.isVarArgs() && list.getExpressions().length != parameterCount) continue;
- }
- }
- if (RefactoringUtil.isMethodUsage(element)) {
- result.add(new MethodCallUsageInfo(element, isToModifyArgs, isToCatchExceptions));
- }
- else if (element instanceof PsiDocTagValue) {
- result.add(new UsageInfo(ref.getElement()));
- }
- else if (element instanceof PsiMethod && ((PsiMethod)element).isConstructor()) {
- DefaultConstructorImplicitUsageInfo implicitUsageInfo = new DefaultConstructorImplicitUsageInfo((PsiMethod)element,
- ((PsiMethod)element).getContainingClass(), method);
- result.add(implicitUsageInfo);
- }
- else if(element instanceof PsiClass) {
- LOG.assertTrue(method.isConstructor());
- final PsiClass psiClass = (PsiClass)element;
- if (shouldPropagateToNonPhysicalMethod(method, result, psiClass, myPropagateParametersMethods)) continue;
- if (shouldPropagateToNonPhysicalMethod(method, result, psiClass, myPropagateExceptionsMethods)) continue;
- result.add(new NoConstructorClassUsageInfo(psiClass));
- }
- else if (ref instanceof PsiCallReference) {
- result.add(new CallReferenceUsageInfo((PsiCallReference) ref));
- }
- else {
- result.add(new MoveRenameUsageInfo(element, ref, method));
- }
- }
-
- //if (method.isConstructor() && parameterCount == 0) {
- // RefactoringUtil.visitImplicitConstructorUsages(method.getContainingClass(),
- // new DefaultConstructorUsageCollector(result));
- //}
- }
- else if (myChangeInfo.isParameterTypesChanged) {
- PsiReference[] refs = MethodReferencesSearch.search(method, projectScope, true).toArray(PsiReference.EMPTY_ARRAY);
- for (PsiReference reference : refs) {
- final PsiElement element = reference.getElement();
- if (element instanceof PsiDocTagValue) {
- result.add(new UsageInfo(reference));
- }
- else if (element instanceof XmlElement) {
- result.add(new MoveRenameUsageInfo(reference, method));
- }
- }
- }
-
- // Conflicts
- detectLocalsCollisionsInMethod(method, result, isOriginal);
- for (final PsiMethod overridingMethod : overridingMethods) {
- detectLocalsCollisionsInMethod(overridingMethod, result, isOriginal);
- }
-
- return overridingMethods;
- }
-
- private static boolean shouldPropagateToNonPhysicalMethod(PsiMethod method, ArrayList<UsageInfo> result, PsiClass containingClass, final Set<PsiMethod> propagateMethods) {
- for (PsiMethod psiMethod : propagateMethods) {
- if (!psiMethod.isPhysical() && Comparing.strEqual(psiMethod.getName(), containingClass.getName())) {
- result.add(new DefaultConstructorImplicitUsageInfo(psiMethod, containingClass, method));
- return true;
- }
- }
- return false;
- }
-
- private void findUsagesInCallers(final ArrayList<UsageInfo> usages) {
- for (PsiMethod caller : myPropagateParametersMethods) {
- usages.add(new CallerUsageInfo(caller, true, myPropagateExceptionsMethods.contains(caller)));
- }
- for (PsiMethod caller : myPropagateExceptionsMethods) {
- usages.add(new CallerUsageInfo(caller, myPropagateParametersMethods.contains(caller), true));
- }
- Set<PsiMethod> merged = new HashSet<PsiMethod>();
- merged.addAll(myPropagateParametersMethods);
- merged.addAll(myPropagateExceptionsMethods);
- for (final PsiMethod method : merged) {
- findSimpleUsagesWithoutParameters(method, usages, myPropagateParametersMethods.contains(method),
- myPropagateExceptionsMethods.contains(method), false);
- }
- }
-
- private boolean needToChangeCalls() {
- return myChangeInfo.isNameChanged || myChangeInfo.isParameterSetOrOrderChanged || myChangeInfo.isExceptionSetOrOrderChanged;
- }
-
- private boolean needToCatchExceptions(PsiMethod caller) {
- return myChangeInfo.isExceptionSetOrOrderChanged && !myPropagateExceptionsMethods.contains(caller);
- }
+ List<UsageInfo> infos = new ArrayList<UsageInfo>();
- private void detectLocalsCollisionsInMethod(final PsiMethod method,
- final ArrayList<UsageInfo> result,
- boolean isOriginal) {
- final PsiParameter[] parameters = method.getParameterList().getParameters();
- final Set<PsiParameter> deletedOrRenamedParameters = new HashSet<PsiParameter>();
- if (isOriginal) {
- deletedOrRenamedParameters.addAll(Arrays.asList(parameters));
- for (ParameterInfoImpl parameterInfo : myChangeInfo.newParms) {
- if (parameterInfo.oldParameterIndex >= 0) {
- final PsiParameter parameter = parameters[parameterInfo.oldParameterIndex];
- if (parameterInfo.getName().equals(parameter.getName())) {
- deletedOrRenamedParameters.remove(parameter);
- }
- }
- }
- }
-
- for (ParameterInfoImpl parameterInfo : myChangeInfo.newParms) {
- final int oldParameterIndex = parameterInfo.oldParameterIndex;
- final String newName = parameterInfo.getName();
- if (oldParameterIndex >= 0) {
- if (isOriginal) { //Name changes take place only in primary method
- final PsiParameter parameter = parameters[oldParameterIndex];
- if (!newName.equals(parameter.getName())) {
- JavaUnresolvableLocalCollisionDetector.visitLocalsCollisions(parameter, newName, method.getBody(), null, new JavaUnresolvableLocalCollisionDetector.CollidingVariableVisitor() {
- public void visitCollidingElement(final PsiVariable collidingVariable) {
- if (!deletedOrRenamedParameters.contains(collidingVariable)) {
- result.add(new RenamedParameterCollidesWithLocalUsageInfo(parameter, collidingVariable, method));
- }
- }
- });
- }
- }
- }
- else {
- JavaUnresolvableLocalCollisionDetector.visitLocalsCollisions(method, newName, method.getBody(), null, new JavaUnresolvableLocalCollisionDetector.CollidingVariableVisitor() {
- public void visitCollidingElement(PsiVariable collidingVariable) {
- if (!deletedOrRenamedParameters.contains(collidingVariable)) {
- result.add(new NewParameterCollidesWithLocalUsageInfo(collidingVariable, collidingVariable, method));
- }
- }
- });
- }
+ final ChangeSignatureUsageProcessor[] processors = ChangeSignatureUsageProcessor.EP_NAME.getExtensions();
+ for (ChangeSignatureUsageProcessor processor : processors) {
+ infos.addAll(Arrays.asList(processor.findUsages(myChangeInfo)));
}
+ return infos.toArray(new UsageInfo[infos.size()]);
}
- private void findParametersUsage(final PsiMethod method, ArrayList<UsageInfo> result, PsiMethod[] overriders) {
- PsiParameter[] parameters = method.getParameterList().getParameters();
- for (ParameterInfoImpl info : myChangeInfo.newParms) {
- if (info.oldParameterIndex >= 0) {
- PsiParameter parameter = parameters[info.oldParameterIndex];
- if (!info.getName().equals(parameter.getName())) {
- addParameterUsages(parameter, result, info);
-
- for (PsiMethod overrider : overriders) {
- PsiParameter parameter1 = overrider.getParameterList().getParameters()[info.oldParameterIndex];
- if (parameter.getName().equals(parameter1.getName())) {
- addParameterUsages(parameter1, result, info);
- }
- }
- }
- }
- }
- }
protected void refreshElements(PsiElement[] elements) {
boolean condition = elements.length == 1 && elements[0] instanceof PsiMethod;
myChangeInfo.updateMethod((PsiMethod) elements[0]);
}
- private void addMethodConflicts(MultiMap<PsiElement, String> conflicts) {
- String newMethodName = myChangeInfo.newName;
-
- try {
- PsiMethod prototype;
- PsiManager manager = PsiManager.getInstance(myProject);
- PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory();
- final PsiMethod method = myChangeInfo.getMethod();
- final CanonicalTypes.Type returnType = myChangeInfo.newReturnType;
- if (returnType != null) {
- prototype = factory.createMethod(newMethodName, returnType.getType(method, manager));
- }
- else {
- prototype = factory.createConstructor();
- prototype.setName(newMethodName);
- }
- ParameterInfoImpl[] parameters = myChangeInfo.newParms;
-
-
- for (ParameterInfoImpl info : parameters) {
- final PsiType parameterType = info.createType(method, manager);
- PsiParameter param = factory.createParameter(info.getName(), parameterType);
- prototype.getParameterList().add(param);
+ protected boolean preprocessUsages(Ref<UsageInfo[]> refUsages) {
+ MultiMap<PsiElement, String> conflictDescriptions = new MultiMap<PsiElement, String>();
+ for (ChangeSignatureUsageProcessor usageProcessor : ChangeSignatureUsageProcessor.EP_NAME.getExtensions()) {
+ final MultiMap<PsiElement, String> conflicts = usageProcessor.findConflicts(myChangeInfo, refUsages);
+ for (PsiElement key : conflicts.keySet()) {
+ Collection<String> collection = conflictDescriptions.get(key);
+ if (collection.size() == 0) collection = new HashSet<String>();
+ collection.addAll(conflicts.get(key));
+ conflictDescriptions.put(key, collection);
}
-
- ConflictsUtil.checkMethodConflicts(
- method.getContainingClass(),
- method,
- prototype, conflicts);
- }
- catch (IncorrectOperationException e) {
- LOG.error(e);
}
- }
-
- protected boolean preprocessUsages(Ref<UsageInfo[]> refUsages) {
- MultiMap<PsiElement, String> conflictDescriptions = new MultiMap<PsiElement, String>();
final UsageInfo[] usagesIn = refUsages.get();
- addMethodConflicts(conflictDescriptions);
RenameUtil.addConflictDescriptions(usagesIn, conflictDescriptions);
Set<UsageInfo> usagesSet = new HashSet<UsageInfo>(Arrays.asList(usagesIn));
RenameUtil.removeConflictUsages(usagesSet);
- if (myChangeInfo.isVisibilityChanged) {
- try {
- addInaccessibilityDescriptions(usagesSet, conflictDescriptions);
- }
- catch (IncorrectOperationException e) {
- LOG.error(e);
- }
- }
-
if (myPrepareSuccessfulSwingThreadCallback != null && !conflictDescriptions.isEmpty()) {
ConflictsDialog dialog = new ConflictsDialog(myProject, conflictDescriptions, new Runnable(){
public void run() {
}
});
dialog.show();
- if (!dialog.isOK()){
+ if (!dialog.isOK()) {
if (dialog.isShowConflicts()) prepareSuccessful();
return false;
}
}
- if (myChangeInfo.isReturnTypeChanged) {
- askToRemoveCovariantOverriders (usagesSet);
+ if (myChangeInfo.isReturnTypeChanged()) {
+ askToRemoveCovariantOverriders(usagesSet);
}
refUsages.set(usagesSet.toArray(new UsageInfo[usagesSet.size()]));
return true;
}
- private void addInaccessibilityDescriptions(Set<UsageInfo> usages, MultiMap<PsiElement, String> conflictDescriptions) throws IncorrectOperationException {
- PsiMethod method = myChangeInfo.getMethod();
- PsiModifierList modifierList = (PsiModifierList)method.getModifierList().copy();
- VisibilityUtil.setVisibility(modifierList, myNewVisibility);
-
- for (Iterator<UsageInfo> iterator = usages.iterator(); iterator.hasNext();) {
- UsageInfo usageInfo = iterator.next();
- PsiElement element = usageInfo.getElement();
- if (element != null) {
- if (element instanceof PsiReferenceExpression) {
- PsiClass accessObjectClass = null;
- PsiExpression qualifier = ((PsiReferenceExpression)element).getQualifierExpression();
- if (qualifier != null) {
- accessObjectClass = (PsiClass)PsiUtil.getAccessObjectClass(qualifier).getElement();
- }
-
- if (!JavaPsiFacade.getInstance(element.getProject()).getResolveHelper()
- .isAccessible(method, modifierList, element, accessObjectClass, null)) {
- String message =
- RefactoringBundle.message("0.with.1.visibility.is.not.accesible.from.2",
- RefactoringUIUtil.getDescription(method, true),
- myNewVisibility,
- RefactoringUIUtil.getDescription(ConflictsUtil.getContainer(element), true));
- conflictDescriptions.putValue(method, message);
- if (!needToChangeCalls()) {
- iterator.remove();
- }
- }
- }
- }
- }
- }
-
private void askToRemoveCovariantOverriders(Set<UsageInfo> usages) {
if (PsiUtil.isLanguageLevel5OrHigher(myChangeInfo.getMethod())) {
List<UsageInfo> covariantOverriderInfos = new ArrayList<UsageInfo>();
protected void preprocessCovariantOverriders(final List<UsageInfo> covariantOverriderInfos) {
}
+ @Override
+ protected boolean isPreviewUsages(UsageInfo[] usages) {
+ for (ChangeSignatureUsageProcessor processor : ChangeSignatureUsageProcessor.EP_NAME.getExtensions()) {
+ if (processor.shouldPreviewUsages(myChangeInfo, usages)) return true;
+ }
+ return super.isPreviewUsages(usages);
+ }
+
protected boolean isProcessCovariantOverriders() {
- return Messages.showYesNoDialog(myProject, RefactoringBundle.message("do.you.want.to.process.overriding.methods.with.covariant.return.type"),
- ChangeSignatureHandler.REFACTORING_NAME, Messages.getQuestionIcon())
- == DialogWrapper.OK_EXIT_CODE;
+ return Messages
+ .showYesNoDialog(myProject, RefactoringBundle.message("do.you.want.to.process.overriding.methods.with.covariant.return.type"),
+ JavaChangeSignatureHandler.REFACTORING_NAME, Messages.getQuestionIcon()) == DialogWrapper.OK_EXIT_CODE;
}
protected void performRefactoring(UsageInfo[] usages) {
- PsiElementFactory factory = JavaPsiFacade.getInstance(myManager.getProject()).getElementFactory();
-
try {
- if (myChangeInfo.isNameChanged) {
- myChangeInfo.newNameIdentifier = factory.createIdentifier(myChangeInfo.newName);
- }
-
- if (myChangeInfo.isReturnTypeChanged) {
- myChangeInfo.newTypeElement = myChangeInfo.newReturnType.getType(myChangeInfo.getMethod(), myManager);
- }
-
- if (myGenerateDelegate) {
- generateDelegate();
- }
+ final ChangeSignatureUsageProcessor[] processors = ChangeSignatureUsageProcessor.EP_NAME.getExtensions();
for (UsageInfo usage : usages) {
- 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());
- }
+ for (ChangeSignatureUsageProcessor processor : processors) {
+ if (processor.processUsage(myChangeInfo, usage, true, usages)) break;
}
}
LOG.assertTrue(myChangeInfo.getMethod().isValid());
- processPrimaryMethod(myChangeInfo.getMethod(), null, true);
- List<UsageInfo> postponedUsages = new ArrayList<UsageInfo>();
-
- for (UsageInfo usage : usages) {
- PsiElement element = usage.getElement();
- if (element == null) continue;
-
- if (usage instanceof DefaultConstructorImplicitUsageInfo) {
- final DefaultConstructorImplicitUsageInfo defConstructorUsage = (DefaultConstructorImplicitUsageInfo)usage;
- PsiMethod constructor = defConstructorUsage.getConstructor();
- if (!constructor.isPhysical()) {
- final boolean toPropagate = myPropagateParametersMethods.remove(constructor);
- final PsiClass containingClass = defConstructorUsage.getContainingClass();
- constructor = (PsiMethod)containingClass.add(constructor);
- PsiUtil.setModifierProperty(constructor, VisibilityUtil.getVisibilityModifier(containingClass.getModifierList()), true);
- if (toPropagate) {
- myPropagateParametersMethods.add(constructor);
- }
- }
- addSuperCall(constructor, defConstructorUsage.getBaseConstructor(),usages);
- }
- else if (usage instanceof NoConstructorClassUsageInfo) {
- addDefaultConstructor(((NoConstructorClassUsageInfo)usage).getPsiClass(),usages);
- }
- else if (element instanceof PsiJavaCodeReferenceElement) {
- if (usage instanceof MethodCallUsageInfo) {
- final MethodCallUsageInfo methodCallInfo = (MethodCallUsageInfo)usage;
- processMethodUsage(methodCallInfo.getElement(), myChangeInfo, methodCallInfo.isToChangeArguments(),
- methodCallInfo.isToCatchExceptions(), methodCallInfo.getReferencedMethod(), usages);
- }
- else if (usage instanceof MyParameterUsageInfo) {
- String newName = ((MyParameterUsageInfo)usage).newParameterName;
- String oldName = ((MyParameterUsageInfo)usage).oldParameterName;
- processParameterUsage((PsiReferenceExpression)element, oldName, newName);
- } else {
- postponedUsages.add(usage);
- }
- }
- else if (usage instanceof CallReferenceUsageInfo) {
- ((CallReferenceUsageInfo) usage).getReference().handleChangeSignature(myChangeInfo);
- }
- else if (element instanceof PsiEnumConstant) {
- fixActualArgumentsList(((PsiEnumConstant)element).getArgumentList(), myChangeInfo, true);
- }
- else if (!(usage instanceof OverriderUsageInfo)) {
- postponedUsages.add(usage);
- }
+ for (ChangeSignatureUsageProcessor processor : processors) {
+ if (processor.processPrimaryMethod(myChangeInfo)) break;
}
- for (UsageInfo usageInfo : postponedUsages) {
- PsiElement element = usageInfo.getElement();
- if (element == null) continue;
- PsiReference reference = usageInfo instanceof MoveRenameUsageInfo ?
- usageInfo.getReference() :
- element.getReference();
- if (reference != null) {
- PsiElement target = null;
- if (usageInfo instanceof MyParameterUsageInfo) {
- String newParameterName = ((MyParameterUsageInfo)usageInfo).newParameterName;
- PsiParameter[] newParams = myChangeInfo.getMethod().getParameterList().getParameters();
- for (PsiParameter newParam : newParams) {
- if (newParam.getName().equals(newParameterName)) {
- target = newParam;
- break;
- }
- }
- }
- else {
- target = myChangeInfo.getMethod();
- }
- if (target != null) {
- reference.bindToElement(target);
+ for (UsageInfo usage : usages) {
+ for (ChangeSignatureUsageProcessor processor : processors) {
+ if (processor.processUsage(myChangeInfo, usage, false, usages)) {
+ break;
}
}
}
LOG.assertTrue(myChangeInfo.getMethod().isValid());
- } catch (IncorrectOperationException e) {
- LOG.error(e);
}
- }
-
- private void generateDelegate() throws IncorrectOperationException {
- final PsiMethod delegate = (PsiMethod)myChangeInfo.getMethod().copy();
- final PsiClass targetClass = myChangeInfo.getMethod().getContainingClass();
- LOG.assertTrue(!targetClass.isInterface());
- makeEmptyBody(myFactory, delegate);
- final PsiCallExpression callExpression = addDelegatingCallTemplate(delegate, myChangeInfo.newName);
- addDelegateArguments(callExpression);
- targetClass.addBefore(delegate, myChangeInfo.getMethod());
- }
-
- private void addDelegateArguments(final PsiCallExpression callExpression) throws IncorrectOperationException {
- final ParameterInfoImpl[] newParms = myChangeInfo.newParms;
- for (int i = 0; i < newParms.length; i++) {
- ParameterInfoImpl newParm = newParms[i];
- final PsiExpression actualArg;
- if (newParm.oldParameterIndex >= 0) {
- actualArg = myFactory.createExpressionFromText(myChangeInfo.oldParameterNames[newParm.oldParameterIndex], callExpression);
- }
- else {
- actualArg = myChangeInfo.getValue(i, callExpression);
- }
- callExpression.getArgumentList().add(actualArg);
+ catch (IncorrectOperationException e) {
+ LOG.error(e);
}
}
PsiUtil.setModifierProperty(delegate, PsiModifier.ABSTRACT, false);
}
+ @Nullable
public static PsiCallExpression addDelegatingCallTemplate(final PsiMethod delegate, final String newName) throws IncorrectOperationException {
Project project = delegate.getProject();
PsiElementFactory factory = JavaPsiFacade.getInstance(project).getElementFactory();
return callExpression;
}
- private void addDefaultConstructor(PsiClass aClass, final UsageInfo[] usages) throws IncorrectOperationException {
- if (!(aClass instanceof PsiAnonymousClass)) {
- PsiMethod defaultConstructor = myFactory.createMethodFromText(aClass.getName() + "(){}", aClass);
- defaultConstructor = (PsiMethod) CodeStyleManager.getInstance(myProject).reformat(defaultConstructor);
- defaultConstructor = (PsiMethod) aClass.add(defaultConstructor);
- PsiUtil.setModifierProperty(defaultConstructor, VisibilityUtil.getVisibilityModifier(aClass.getModifierList()), true);
- addSuperCall(defaultConstructor, null, usages);
- } else {
- final PsiElement parent = aClass.getParent();
- if (parent instanceof PsiNewExpression) {
- final PsiExpressionList argumentList = ((PsiNewExpression) parent).getArgumentList();
- fixActualArgumentsList(argumentList, myChangeInfo, true);
- }
- }
- }
-
- private void addSuperCall(PsiMethod constructor, PsiMethod callee, final UsageInfo[] usages) throws IncorrectOperationException {
- PsiExpressionStatement superCall = (PsiExpressionStatement) myFactory.createStatementFromText("super();", constructor);
- PsiCodeBlock body = constructor.getBody();
- assert body != null;
- PsiStatement[] statements = body.getStatements();
- if (statements.length > 0) {
- superCall = (PsiExpressionStatement) body.addBefore(superCall, statements[0]);
- } else {
- superCall = (PsiExpressionStatement) body.add(superCall);
- }
- PsiMethodCallExpression callExpression = (PsiMethodCallExpression) superCall.getExpression();
- processMethodUsage(callExpression.getMethodExpression(), myChangeInfo, true, false, callee, usages);
- }
-
- private PsiParameter createNewParameter(ParameterInfoImpl newParm,
- PsiSubstitutor substitutor) throws IncorrectOperationException {
- final PsiElementFactory factory = JavaPsiFacade.getInstance(myProject).getElementFactory();
- final PsiType type = substitutor.substitute(newParm.createType(myChangeInfo.getMethod().getParameterList(), myManager));
- return factory.createParameter(newParm.getName(), type);
- }
-
protected String getCommandName() {
return RefactoringBundle.message("changing.signature.of.0", UsageViewUtil.getDescriptiveName(myChangeInfo.getMethod()));
}
- private void processMethodUsage(PsiElement ref,
- ChangeInfoImpl changeInfo,
- boolean toChangeArguments,
- boolean toCatchExceptions,
- PsiMethod callee, final UsageInfo[] usages) throws IncorrectOperationException {
- if (changeInfo.isNameChanged) {
- if (ref instanceof PsiJavaCodeReferenceElement) {
- PsiElement last = ((PsiJavaCodeReferenceElement)ref).getReferenceNameElement();
- if (last instanceof PsiIdentifier && last.getText().equals(changeInfo.oldName)) {
- last.replace(changeInfo.newNameIdentifier);
- }
- }
- }
-
- 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 && callerSignatureIsAboutToChangeToo(caller, usages)) {
- toInsertDefaultValue = false;
- }
- }
-
- 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 static boolean callerSignatureIsAboutToChangeToo(final PsiMethod caller, final UsageInfo[] usages) {
- for (UsageInfo usage : usages) {
- if (usage instanceof MethodCallUsageInfo && MethodSignatureUtil.isSuperMethod(((MethodCallUsageInfo)usage).getReferencedMethod(), caller)) return true;
- }
- return false;
- }
-
- private static PsiClassType[] getCalleeChangedExceptionInfo(final PsiMethod callee) {
- return callee.getThrowsList().getReferencedTypes(); //Callee method's throws list is already modified!
- }
-
- private PsiClassType[] getPrimaryChangedExceptionInfo(ChangeInfoImpl 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(), myManager); //context really does not matter here
- }
- return newExceptions;
- }
-
- private void fixExceptions(PsiElement ref, PsiClassType[] newExceptions) throws IncorrectOperationException {
- //methods' throws lists are already modified, may use ExceptionUtil.collectUnhandledExceptions
- newExceptions = filterCheckedExceptions(newExceptions);
-
- PsiElement context = PsiTreeUtil.getParentOfType(ref, PsiTryStatement.class, PsiMethod.class);
- if (context instanceof PsiTryStatement) {
- PsiTryStatement tryStatement = (PsiTryStatement)context;
- PsiCodeBlock tryBlock = tryStatement.getTryBlock();
-
- //Remove unused catches
- Collection<PsiClassType> classes = ExceptionUtil.collectUnhandledExceptions(tryBlock, tryBlock);
- PsiParameter[] catchParameters = tryStatement.getCatchBlockParameters();
- for (PsiParameter parameter : catchParameters) {
- final PsiType caughtType = parameter.getType();
-
- if (!(caughtType instanceof PsiClassType)) continue;
- if (ExceptionUtil.isUncheckedExceptionOrSuperclass((PsiClassType)caughtType)) continue;
-
- if (!isCatchParameterRedundant((PsiClassType)caughtType, classes)) continue;
- parameter.getParent().delete(); //delete catch section
- }
-
- PsiClassType[] exceptionsToAdd = filterUnhandledExceptions(newExceptions, tryBlock);
- addExceptions(exceptionsToAdd, tryStatement);
-
- adjustPossibleEmptyTryStatement(tryStatement);
- }
- else {
- newExceptions = filterUnhandledExceptions(newExceptions, ref);
- if (newExceptions.length > 0) {
- //Add new try statement
- PsiElementFactory elementFactory = JavaPsiFacade.getInstance(myManager.getProject()).getElementFactory();
- PsiTryStatement tryStatement = (PsiTryStatement)elementFactory.createStatementFromText("try {} catch (Exception e) {}", null);
- PsiStatement anchor = PsiTreeUtil.getParentOfType(ref, PsiStatement.class);
- LOG.assertTrue(anchor != null);
- tryStatement.getTryBlock().add(anchor);
- tryStatement = (PsiTryStatement)anchor.getParent().addAfter(tryStatement, anchor);
-
- addExceptions(newExceptions, tryStatement);
- anchor.delete();
- tryStatement.getCatchSections()[0].delete(); //Delete dummy catch section
- }
- }
- }
-
- private static PsiClassType[] filterCheckedExceptions(PsiClassType[] exceptions) {
- List<PsiClassType> result = new ArrayList<PsiClassType>();
- for (PsiClassType exceptionType : exceptions) {
- if (!ExceptionUtil.isUncheckedException(exceptionType)) result.add(exceptionType);
- }
- return result.toArray(new PsiClassType[result.size()]);
- }
-
- private static void adjustPossibleEmptyTryStatement(PsiTryStatement tryStatement) throws IncorrectOperationException {
- PsiCodeBlock tryBlock = tryStatement.getTryBlock();
- if (tryBlock != null) {
- if (tryStatement.getCatchSections().length == 0 &&
- tryStatement.getFinallyBlock() == null) {
- PsiElement firstBodyElement = tryBlock.getFirstBodyElement();
- if (firstBodyElement != null) {
- tryStatement.getParent().addRangeAfter(firstBodyElement, tryBlock.getLastBodyElement(), tryStatement);
- }
- tryStatement.delete();
- }
- }
- }
-
- private static void addExceptions(PsiClassType[] exceptionsToAdd, PsiTryStatement tryStatement) throws IncorrectOperationException {
- for (PsiClassType type : exceptionsToAdd) {
- final JavaCodeStyleManager styleManager = JavaCodeStyleManager.getInstance(tryStatement.getProject());
- String name = styleManager.suggestVariableName(VariableKind.PARAMETER, null, null, type).names[0];
- name = styleManager.suggestUniqueVariableName(name, tryStatement, false);
-
- PsiCatchSection catchSection =
- JavaPsiFacade.getInstance(tryStatement.getProject()).getElementFactory().createCatchSection(type, name, tryStatement);
- tryStatement.add(catchSection);
- }
- }
-
- private void fixPrimaryThrowsLists(PsiMethod method, PsiClassType[] newExceptions) throws IncorrectOperationException {
- PsiElementFactory elementFactory = JavaPsiFacade.getInstance(myManager.getProject()).getElementFactory();
- PsiJavaCodeReferenceElement[] refs = new PsiJavaCodeReferenceElement[newExceptions.length];
- for (int i = 0; i < refs.length; i++) {
- refs[i] = elementFactory.createReferenceElementByType(newExceptions[i]);
- }
- PsiReferenceList throwsList = elementFactory.createReferenceList(refs);
-
- replaceThrowsList(method, throwsList);
- }
-
- private void replaceThrowsList(PsiMethod method, PsiReferenceList throwsList) throws IncorrectOperationException {
- PsiReferenceList methodThrowsList = (PsiReferenceList)method.getThrowsList().replace(throwsList);
- methodThrowsList = (PsiReferenceList)JavaCodeStyleManager.getInstance(myProject).shortenClassReferences(methodThrowsList);
- myManager.getCodeStyleManager().reformatRange(method, method.getParameterList().getTextRange().getEndOffset(),
- methodThrowsList.getTextRange().getEndOffset());
- }
-
- private static PsiClassType[] filterUnhandledExceptions(PsiClassType[] exceptions, PsiElement place) {
- List<PsiClassType> result = new ArrayList<PsiClassType>();
- for (PsiClassType exception : exceptions) {
- if (!ExceptionUtil.isHandled(exception, place)) result.add(exception);
- }
- return result.toArray(new PsiClassType[result.size()]);
- }
-
- private static boolean isCatchParameterRedundant (PsiClassType catchParamType, Collection<PsiClassType> thrownTypes) {
- for (PsiType exceptionType : thrownTypes) {
- if (exceptionType.isConvertibleFrom(catchParamType)) return false;
- }
- return true;
- }
-
- private static int getNonVarargCount(ChangeInfoImpl changeInfo, PsiExpression[] args) {
- if (!changeInfo.wasVararg) return args.length;
- return changeInfo.oldParameterTypes.length - 1;
- }
-
- //This methods works equally well for primary usages as well as for propagated callers' usages
- private void fixActualArgumentsList(PsiExpressionList list,
- ChangeInfoImpl changeInfo,
- boolean toInsertDefaultValue) throws IncorrectOperationException {
- final PsiElementFactory factory = JavaPsiFacade.getInstance(list.getProject()).getElementFactory();
- if (changeInfo.isParameterSetOrOrderChanged) {
- if (changeInfo.isPropagationEnabled) {
- final ParameterInfoImpl[] createdParmsInfo = changeInfo.getCreatedParmsInfoWithoutVarargs();
- for (ParameterInfoImpl info : createdParmsInfo) {
- PsiExpression newArg;
- if (toInsertDefaultValue) {
- newArg = createDefaultValue(factory, info, list);
- }
- else {
- newArg = factory.createExpressionFromText(info.getName(), list);
- }
- list.add(newArg);
- }
- }
- else {
- final PsiExpression[] args = list.getExpressions();
- final int nonVarargCount = getNonVarargCount(changeInfo, args);
- final int varargCount = args.length - nonVarargCount;
- PsiExpression[] newVarargInitializers = null;
-
- final int newArgsLength;
- final int newNonVarargCount;
- if (changeInfo.arrayToVarargs) {
- newNonVarargCount = changeInfo.newParms.length - 1;
- final ParameterInfoImpl lastNewParm = changeInfo.newParms[changeInfo.newParms.length - 1];
- final PsiExpression arrayToConvert = args[lastNewParm.oldParameterIndex];
- if (arrayToConvert instanceof PsiNewExpression) {
- final PsiNewExpression expression = (PsiNewExpression)arrayToConvert;
- final PsiArrayInitializerExpression arrayInitializer = expression.getArrayInitializer();
- if (arrayInitializer != null) {
- newVarargInitializers = arrayInitializer.getInitializers();
- }
- }
- newArgsLength = newVarargInitializers == null ? changeInfo.newParms.length : newNonVarargCount + newVarargInitializers.length;
- }
- else 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++) {
- newArgs [i] = createActualArgument(list, changeInfo.newParms [i], toInsertDefaultValue, args);
- }
- if (changeInfo.arrayToVarargs) {
- if (newVarargInitializers == null) {
- newArgs [newNonVarargCount] = createActualArgument(list, changeInfo.newParms [newNonVarargCount], toInsertDefaultValue, args);
- }
- else {
- for (int i = 0; i < newVarargInitializers.length; i++) {
- newArgs [i + newNonVarargCount] = newVarargInitializers [i];
- }
- }
- }
- else {
- 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);
- }
- }
- }
-
- private PsiExpression createActualArgument(final PsiExpressionList list, final ParameterInfoImpl info, final boolean toInsertDefaultValue,
- final PsiExpression[] args) throws IncorrectOperationException {
- final PsiElementFactory factory = JavaPsiFacade.getInstance(list.getProject()).getElementFactory();
- final int index = info.oldParameterIndex;
- if (index >= 0) {
- return args[index];
- } else {
- if (toInsertDefaultValue) {
- return createDefaultValue(factory, info, list);
- } else {
- return factory.createExpressionFromText(info.getName(), list);
- }
- }
- }
-
- private PsiExpression createDefaultValue(final PsiElementFactory factory, final ParameterInfoImpl info, final PsiExpressionList list)
- throws IncorrectOperationException {
- if (info.useAnySingleVariable) {
- final PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(list.getProject()).getResolveHelper();
- final PsiType type = info.getTypeWrapper().getType(myChangeInfo.getMethod(), myManager);
- final VariablesProcessor processor = new VariablesProcessor(false) {
- protected boolean check(PsiVariable var, ResolveState state) {
- if (var instanceof PsiField && !resolveHelper.isAccessible((PsiField)var, list, null)) return false;
- final PsiType varType = state.get(PsiSubstitutor.KEY).substitute(var.getType());
- return type.isAssignableFrom(varType);
- }
-
- public boolean execute(PsiElement pe, ResolveState state) {
- super.execute(pe, state);
- return size() < 2;
- }
- };
- PsiScopesUtil.treeWalkUp(processor, list, null);
- if (processor.size() == 1) {
- final PsiVariable result = processor.getResult(0);
- return factory.createExpressionFromText(result.getName(), list);
- }
- }
- final PsiCallExpression callExpression = PsiTreeUtil.getParentOfType(list, PsiCallExpression.class);
- return callExpression != null ? info.getValue(callExpression) : factory.createExpressionFromText(info.defaultValue, list);
- }
-
- private static void addParameterUsages(PsiParameter parameter,
- ArrayList<UsageInfo> results,
- ParameterInfoImpl info) {
- PsiManager manager = parameter.getManager();
- GlobalSearchScope projectScope = GlobalSearchScope.projectScope(manager.getProject());
- for (PsiReference psiReference : ReferencesSearch.search(parameter, projectScope, false)) {
- PsiElement parmRef = psiReference.getElement();
- UsageInfo usageInfo = new MyParameterUsageInfo(parmRef, parameter.getName(), info.getName());
- results.add(usageInfo);
- }
- }
-
- 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 ParameterInfoImpl[] primaryNewParms = myChangeInfo.newParms;
- PsiSubstitutor substitutor = baseMethod == null ? PsiSubstitutor.EMPTY : calculateSubstitutor(caller, baseMethod);
- for (ParameterInfoImpl info : primaryNewParms) {
- if (info.oldParameterIndex < 0) newParameters.add(createNewParameter(info, 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 (ThrownExceptionInfo thrownExceptionInfo : primaryNewExns) {
- if (thrownExceptionInfo.oldIndex < 0) {
- final PsiClassType type = (PsiClassType)thrownExceptionInfo.createType(caller, myManager);
- final PsiJavaCodeReferenceElement ref =
- JavaPsiFacade.getInstance(caller.getProject()).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 = JavaPsiFacade.getInstance(method.getProject()).getElementFactory();
-
- if (myChangeInfo.isVisibilityChanged) {
- PsiModifierList modifierList = method.getModifierList();
- final String highestVisibility = isOriginal ?
- myNewVisibility :
- VisibilityUtil.getHighestVisibility(myNewVisibility, VisibilityUtil.getVisibilityModifier(modifierList));
- VisibilityUtil.setVisibility(modifierList, highestVisibility);
- }
-
- if (myChangeInfo.isNameChanged) {
- String newName = baseMethod == null ? myChangeInfo.newName :
- RefactoringUtil.suggestNewOverriderName(method.getName(), baseMethod.getName(), myChangeInfo.newName);
-
- if (newName != null && !newName.equals(method.getName())) {
- final PsiIdentifier nameId = method.getNameIdentifier();
- assert nameId != null;
- nameId.replace(JavaPsiFacade.getInstance(myManager.getProject()).getElementFactory().createIdentifier(newName));
- }
- }
-
- final PsiSubstitutor substitutor = baseMethod == null ? PsiSubstitutor.EMPTY : calculateSubstitutor(method, baseMethod);
-
- if (myChangeInfo.isReturnTypeChanged) {
- final PsiType returnType = substitutor.substitute(myChangeInfo.newTypeElement);
- // don't modify return type for non-Java overriders (EJB)
- if (method.getName().equals(myChangeInfo.newName)) {
- final PsiTypeElement typeElement = method.getReturnTypeElement();
- if (typeElement != null) {
- typeElement.replace(factory.createTypeElement(returnType));
- }
- }
- }
-
- PsiParameterList list = method.getParameterList();
- PsiParameter[] parameters = list.getParameters();
-
- PsiParameter[] newParms = new PsiParameter[myChangeInfo.newParms.length];
- for (int i = 0; i < newParms.length; i++) {
- ParameterInfoImpl info = myChangeInfo.newParms[i];
- int index = info.oldParameterIndex;
- if (index >= 0) {
- PsiParameter parameter = parameters[index];
- newParms[i] = parameter;
-
- String oldName = myChangeInfo.oldParameterNames[index];
- if (!oldName.equals(info.getName()) && oldName.equals(parameter.getName())) {
- PsiIdentifier newIdentifier = factory.createIdentifier(info.getName());
- parameter.getNameIdentifier().replace(newIdentifier);
- }
-
- String oldType = myChangeInfo.oldParameterTypes[index];
- if (!oldType.equals(info.getTypeText())) {
- parameter.normalizeDeclaration();
- PsiType newType = substitutor.substitute(info.createType(myChangeInfo.getMethod().getParameterList(), myManager));
-
- parameter.getTypeElement().replace(factory.createTypeElement(newType));
- }
- } else {
- newParms[i] = createNewParameter(info, substitutor);
- }
- }
-
- resolveParameterVsFieldsConflicts(newParms, method, list, myChangeInfo.toRemoveParm);
- fixJavadocsForChangedMethod(method);
- if (myChangeInfo.isExceptionSetOrOrderChanged) {
- final PsiClassType[] newExceptions = getPrimaryChangedExceptionInfo(myChangeInfo);
- fixPrimaryThrowsLists(method, newExceptions);
- }
- }
-
- private static void resolveParameterVsFieldsConflicts(final PsiParameter[] newParms,
- final PsiMethod method,
- final PsiParameterList list,
- boolean[] toRemoveParm) throws IncorrectOperationException {
- List<FieldConflictsResolver> conflictResolvers = new ArrayList<FieldConflictsResolver>();
- for (PsiParameter parameter : newParms) {
- conflictResolvers.add(new FieldConflictsResolver(parameter.getName(), method.getBody()));
- }
- ChangeSignatureUtil.synchronizeList(list, Arrays.asList(newParms), ParameterList.INSTANCE, toRemoveParm);
- JavaCodeStyleManager.getInstance(list.getProject()).shortenClassReferences(list);
- for (FieldConflictsResolver fieldConflictsResolver : conflictResolvers) {
- fieldConflictsResolver.fix();
- }
- }
-
- private static PsiSubstitutor calculateSubstitutor(PsiMethod derivedMethod, PsiMethod baseMethod) {
+ public static PsiSubstitutor calculateSubstitutor(PsiMethod derivedMethod, PsiMethod baseMethod) {
PsiSubstitutor substitutor;
if (derivedMethod.getManager().areElementsEquivalent(derivedMethod, baseMethod)) {
substitutor = PsiSubstitutor.EMPTY;
return substitutor;
}
- private static void processParameterUsage(PsiReferenceExpression ref, String oldName, String newName)
- throws IncorrectOperationException {
-
- PsiElement last = ref.getReferenceNameElement();
- if (last instanceof PsiIdentifier && last.getText().equals(oldName)) {
- PsiElementFactory factory = JavaPsiFacade.getInstance(ref.getProject()).getElementFactory();
- PsiIdentifier newNameIdentifier = factory.createIdentifier(newName);
- last.replace(newNameIdentifier);
- }
- }
-
- private static class MyParameterUsageInfo extends UsageInfo {
- final String oldParameterName;
- final String newParameterName;
-
- public MyParameterUsageInfo(PsiElement element, String oldParameterName, String newParameterName) {
- super(element);
- this.oldParameterName = oldParameterName;
- this.newParameterName = newParameterName;
- }
- }
-
- private static class RenamedParameterCollidesWithLocalUsageInfo extends UnresolvableCollisionUsageInfo {
- private final PsiElement myCollidingElement;
- private final PsiMethod myMethod;
-
- public RenamedParameterCollidesWithLocalUsageInfo(PsiParameter parameter, PsiElement collidingElement, PsiMethod method) {
- super(parameter, collidingElement);
- myCollidingElement = collidingElement;
- myMethod = method;
- }
-
- public String getDescription() {
- return RefactoringBundle.message("there.is.already.a.0.in.the.1.it.will.conflict.with.the.renamed.parameter",
- RefactoringUIUtil.getDescription(myCollidingElement, true),
- RefactoringUIUtil.getDescription(myMethod, true));
- }
- }
- private void fixJavadocsForChangedMethod(PsiMethod method) throws IncorrectOperationException {
- final PsiParameter[] parameters = method.getParameterList().getParameters();
- final ParameterInfoImpl[] newParms = myChangeInfo.newParms;
- LOG.assertTrue(parameters.length == newParms.length);
- final Set<PsiParameter> newParameters = new HashSet<PsiParameter>();
- for (int i = 0; i < newParms.length; i++) {
- ParameterInfoImpl newParm = newParms[i];
- if (newParm.oldParameterIndex < 0 ||
- !newParm.getName().equals(myChangeInfo.oldParameterNames[newParm.oldParameterIndex])) {
- newParameters.add(parameters[i]);
- }
- }
- RefactoringUtil.fixJavadocsForParams(method, newParameters);
- }
-
- private static class ExpressionList implements ChangeSignatureUtil.ChildrenGenerator<PsiExpressionList, PsiExpression> {
- public static final ExpressionList INSTANCE = new ExpressionList();
- public List<PsiExpression> getChildren(PsiExpressionList psiExpressionList) {
- return Arrays.asList(psiExpressionList.getExpressions());
- }
- }
-
- private static class ParameterList implements ChangeSignatureUtil.ChildrenGenerator<PsiParameterList, PsiParameter> {
- public static final ParameterList INSTANCE = new ParameterList();
- public List<PsiParameter> getChildren(PsiParameterList psiParameterList) {
- return Arrays.asList(psiParameterList.getParameters());
- }
- }
-
- private static class ThrowsList implements ChangeSignatureUtil.ChildrenGenerator<PsiReferenceList, PsiJavaCodeReferenceElement> {
- public static final ThrowsList INSTANCE = new ThrowsList();
- public List<PsiJavaCodeReferenceElement> getChildren(PsiReferenceList throwsList) {
- return Arrays.asList(throwsList.getReferenceElements());
- }
- }
}
+++ /dev/null
-/*
- * Copyright 2000-2009 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.
- */
-
-/*
- * User: anna
- * Date: 24-Nov-2009
- */
-package com.intellij.refactoring.changeSignature;
-
-import com.intellij.openapi.editor.Editor;
-import com.intellij.psi.*;
-import com.intellij.psi.util.PsiTreeUtil;
-import org.jetbrains.annotations.Nullable;
-
-public class ChangeSignatureTargetUtil {
- private ChangeSignatureTargetUtil() {}
-
- @Nullable
- public static PsiMember findTargetMember(PsiFile file, Editor editor) {
- PsiElement element = file.findElementAt(editor.getCaretModel().getOffset());
- if (PsiTreeUtil.getParentOfType(element, PsiParameterList.class) != null) {
- return PsiTreeUtil.getParentOfType(element, PsiMethod.class);
- }
-
- final PsiCallExpression expression = PsiTreeUtil.getParentOfType(element, PsiCallExpression.class);
- if (expression != null) {
- assert element != null;
- final PsiExpression qualifierExpression = expression instanceof PsiMethodCallExpression ? ((PsiMethodCallExpression)expression).getMethodExpression().getQualifierExpression()
- : expression instanceof PsiNewExpression ? ((PsiNewExpression)expression).getQualifier() : null;
- if (PsiTreeUtil.isAncestor(qualifierExpression, element, false)) {
- final PsiExpressionList expressionList = PsiTreeUtil.getParentOfType(qualifierExpression, PsiExpressionList.class);
- if (expressionList != null) {
- final PsiElement parent = expressionList.getParent();
- if (parent instanceof PsiMethodCallExpression) {
- return ((PsiMethodCallExpression)parent).resolveMethod();
- }
- }
- } else {
- return expression.resolveMethod();
- }
- }
-
- final PsiTypeParameterList typeParameterList = PsiTreeUtil.getParentOfType(element, PsiTypeParameterList.class);
- if (typeParameterList != null) {
- return PsiTreeUtil.getParentOfType(typeParameterList, PsiMember.class);
- }
-
- final PsiReferenceParameterList referenceParameterList = PsiTreeUtil.getParentOfType(element, PsiReferenceParameterList.class);
- if (referenceParameterList != null) {
- final PsiJavaCodeReferenceElement referenceElement =
- PsiTreeUtil.getParentOfType(referenceParameterList, PsiJavaCodeReferenceElement.class);
- if (referenceElement != null) {
- final PsiElement resolved = referenceElement.resolve();
- if (resolved instanceof PsiClass) {
- return (PsiMember)resolved;
- }
- else if (resolved instanceof PsiMethod) {
- return (PsiMember)resolved;
- }
- }
- }
- return null;
- }
-
-}
* @author dsl
*/
public class ChangeSignatureUtil {
- private ChangeSignatureUtil() {}
+ private ChangeSignatureUtil() {
+ }
- public static <Parent extends PsiElement, Child extends PsiElement>
- void synchronizeList(Parent list, final List<Child> newElements, ChildrenGenerator<Parent, Child> generator, final boolean[] shouldRemoveChild)
+ public static <Parent extends PsiElement, Child extends PsiElement> void synchronizeList(Parent list,
+ final List<Child> newElements,
+ ChildrenGenerator<Parent, Child> generator,
+ final boolean[] shouldRemoveChild)
throws IncorrectOperationException {
ArrayList<Child> elementsToRemove = null;
*/
package com.intellij.refactoring.changeSignature;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiMethod;
import com.intellij.refactoring.RefactoringBundle;
import com.intellij.usageView.UsageViewBundle;
import com.intellij.usageView.UsageViewDescriptor;
import com.intellij.usageView.UsageViewUtil;
-import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.annotations.NotNull;
-class ChangeSignatureViewDescriptor implements UsageViewDescriptor {
+public class ChangeSignatureViewDescriptor implements UsageViewDescriptor {
private final PsiMethod myMethod;
private final String myProcessedElementsHeader;
/**
* @author ven
*/
-class ExceptionsTableModel extends AbstractTableModel implements RowEditableTableModel {
+public class ExceptionsTableModel extends AbstractTableModel implements RowEditableTableModel {
private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.changeSignature.ParameterTableModel");
private List<PsiTypeCodeFragment> myTypeCodeFraments;
}
public void addRow() {
- myExceptionInfos.add(new ThrownExceptionInfo());
+ myExceptionInfos.add(new JavaThrownExceptionInfo());
myTypeCodeFraments.add(createParameterTypeCodeFragment("", myContext));
fireTableRowsInserted(myTypeCodeFraments.size() - 1, myTypeCodeFraments.size() - 1);
}
}
}
- PsiType getTypeByRow(int row) {
- Object typeValueAt = getValueAt(row, 0);
- LOG.assertTrue(typeValueAt instanceof PsiTypeCodeFragment);
- PsiType type;
- try {
- type = ((PsiTypeCodeFragment)typeValueAt).getType();
- }
- catch (PsiTypeCodeFragment.TypeSyntaxException e1) {
- type = null;
- }
- catch (PsiTypeCodeFragment.NoTypeException e1) {
- type = null;
- }
- return type;
- }
-
public void setTypeInfos(PsiMethod method) {
PsiClassType[] referencedTypes = method.getThrowsList().getReferencedTypes();
myTypeCodeFraments = new ArrayList<PsiTypeCodeFragment>(referencedTypes.length);
final PsiTypeCodeFragment typeCodeFragment = createParameterTypeCodeFragment(typeWrapper.getTypeText(), method.getThrowsList());
typeWrapper.addImportsTo(typeCodeFragment);
myTypeCodeFraments.add(typeCodeFragment);
- myExceptionInfos.add(new ThrownExceptionInfo(i, referencedTypes[i]));
+ myExceptionInfos.add(new JavaThrownExceptionInfo(i, referencedTypes[i]));
}
}
- PsiTypeCodeFragment createParameterTypeCodeFragment(final String typeText, PsiElement context) {
+ public PsiTypeCodeFragment createParameterTypeCodeFragment(final String typeText, PsiElement context) {
return JavaPsiFacade.getInstance(myContext.getProject()).getElementFactory().createTypeCodeFragment(
typeText, context, false, true, true
);
}
- PsiTypeCodeFragment[] getTypeCodeFragments() {
+ public PsiTypeCodeFragment[] getTypeCodeFragments() {
return myTypeCodeFraments.toArray(new PsiTypeCodeFragment[myTypeCodeFraments.size()]);
}
--- /dev/null
+/*
+ * 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 com.intellij.refactoring.changeSignature;
+
+import com.intellij.psi.*;
+import com.intellij.refactoring.util.CanonicalTypes;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Maxim.Medvedev
+ */
+public interface JavaChangeInfo extends ChangeInfo {
+ boolean isVisibilityChanged();
+
+ boolean isExceptionSetChanged();
+
+ boolean isExceptionSetOrOrderChanged();
+
+ PsiMethod getMethod();
+
+ CanonicalTypes.Type getNewReturnType();
+
+ @NotNull
+ JavaParameterInfo[] getNewParameters();
+
+ @Modifier
+ String getNewVisibility();
+
+ @NotNull
+ String[] getOldParameterNames();
+
+ @NotNull
+ String[] getOldParameterTypes();
+
+ ThrownExceptionInfo[] getNewExceptions();
+
+ boolean isRetainsVarargs();
+
+ boolean isObtainsVarags();
+
+ boolean isArrayToVarargs();
+
+ PsiIdentifier getNewNameIdentifier();
+
+ String getOldName();
+
+ boolean wasVararg();
+
+ boolean[] toRemoveParm();
+
+ PsiExpression getValue(int i, PsiCallExpression callExpression);
+}
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
*/
package com.intellij.refactoring.changeSignature;
+import com.intellij.lang.Language;
+import com.intellij.lang.StdLanguages;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.*;
import com.intellij.refactoring.util.CanonicalTypes;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.Set;
-class ChangeInfoImpl implements ChangeInfo {
- private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.changeSignature.ChangeInfoImpl");
+class JavaChangeInfoImpl implements JavaChangeInfo {
+ private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.changeSignature.JavaChangeInfoImpl");
+ @Modifier
final String newVisibility;
private PsiMethod method;
final String oldName;
final boolean obtainsVarags;
final boolean arrayToVarargs;
PsiIdentifier newNameIdentifier;
- PsiType newTypeElement;
+// PsiType newTypeElement;
final PsiExpression[] defaultValues;
+ final boolean isGenerateDelegate;
+ final Set<PsiMethod> propagateParametersMethods;
+ final Set<PsiMethod> propagateExceptionsMethods;
+
/**
* @param newExceptions null if not changed
*/
- public ChangeInfoImpl(@Modifier String newVisibility,
+ public JavaChangeInfoImpl(@Modifier String newVisibility,
PsiMethod method,
String newName,
CanonicalTypes.Type newType,
@NotNull ParameterInfoImpl[] newParms,
- ThrownExceptionInfo[] newExceptions) {
+ ThrownExceptionInfo[] newExceptions,
+ boolean generateDelegate,
+ Set<PsiMethod> propagateParametersMethods,
+ Set<PsiMethod> propagateExceptionsMethods) {
this.newVisibility = newVisibility;
this.method = method;
this.newName = newName;
this.newParms = newParms;
wasVararg = method.isVarArgs();
+ this.isGenerateDelegate =generateDelegate;
+ this.propagateExceptionsMethods=propagateExceptionsMethods;
+ this.propagateParametersMethods=propagateParametersMethods;
+
oldName = method.getName();
final PsiManager manager = method.getManager();
if (!method.isConstructor()){
arrayToVarargs = false;
}
}
+
+ if (isNameChanged) {
+ newNameIdentifier = factory.createIdentifier(newName);
+ }
+
}
@NotNull
- public ParameterInfo[] getNewParameters() {
+ public JavaParameterInfo[] getNewParameters() {
return newParms;
}
+ @Modifier
+ public String getNewVisibility() {
+ return newVisibility;
+ }
+
public boolean isParameterSetOrOrderChanged() {
return isParameterSetOrOrderChanged;
}
if (!isExceptionSetChanged) {
for (int i = 0; i < newExceptions.length; i++) {
try {
- if (newExceptions[i].oldIndex < 0 || !types[i].equals(newExceptions[i].myType.getType(method, method.getManager()))) {
+ if (newExceptions[i].getOldIndex() < 0 || !types[i].equals(newExceptions[i].createType(method, method.getManager()))) {
isExceptionSetChanged = true;
break;
}
catch (IncorrectOperationException e) {
isExceptionSetChanged = true;
}
- if (newExceptions[i].oldIndex != i) isExceptionSetOrOrderChanged = true;
+ if (newExceptions[i].getOldIndex() != i) isExceptionSetOrOrderChanged = true;
}
}
PsiClassType[] types = method.getThrowsList().getReferencedTypes();
ThrownExceptionInfo[] result = new ThrownExceptionInfo[types.length];
for (int i = 0; i < result.length; i++) {
- result[i] = new ThrownExceptionInfo(i, types[i]);
+ result[i] = new JavaThrownExceptionInfo(i, types[i]);
}
return result;
}
return method;
}
+ public CanonicalTypes.Type getNewReturnType() {
+ return newReturnType;
+ }
+
public void updateMethod(PsiMethod method) {
this.method = method;
}
if (defaultValues[i] != null) return defaultValues[i];
return newParms[i].getValue(expr);
}
+
+ public boolean isVisibilityChanged() {
+ return isVisibilityChanged;
+ }
+
+ public boolean isNameChanged() {
+ return isNameChanged;
+ }
+
+ public boolean isReturnTypeChanged() {
+ return isReturnTypeChanged;
+ }
+
+ public String getNewName() {
+ return newName;
+ }
+
+ public Language getLanguage() {
+ return StdLanguages.JAVA;
+ }
+
+ public boolean isExceptionSetChanged() {
+ return isExceptionSetChanged;
+ }
+
+ public boolean isExceptionSetOrOrderChanged() {
+ return isExceptionSetOrOrderChanged;
+ }
+
+ public boolean isParameterNamesChanged() {
+ return isParameterNamesChanged;
+ }
+
+ public boolean isParameterTypesChanged() {
+ return isParameterTypesChanged;
+ }
+
+ public boolean isGenerateDelegate() {
+ return isGenerateDelegate;
+ }
+
+ @NotNull
+ public String[] getOldParameterNames() {
+ return oldParameterNames;
+ }
+
+ @NotNull
+ public String[] getOldParameterTypes() {
+ return oldParameterTypes;
+ }
+
+ public ThrownExceptionInfo[] getNewExceptions() {
+ return newExceptions;
+ }
+
+ public boolean isRetainsVarargs() {
+ return retainsVarargs;
+ }
+
+ public boolean isObtainsVarags() {
+ return obtainsVarags;
+ }
+
+ public boolean isArrayToVarargs() {
+ return arrayToVarargs;
+ }
+
+ public PsiIdentifier getNewNameIdentifier() {
+ return newNameIdentifier;
+ }
+
+ public String getOldName() {
+ return oldName;
+ }
+
+ public boolean wasVararg() {
+ return wasVararg;
+ }
+
+ public boolean[] toRemoveParm() {
+ return toRemoveParm;
+ }
}
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
+import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.refactoring.HelpID;
-import com.intellij.refactoring.RefactoringActionHandler;
import com.intellij.refactoring.RefactoringBundle;
import com.intellij.refactoring.changeClassSignature.ChangeClassSignatureDialog;
import com.intellij.refactoring.util.CommonRefactoringUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-public class ChangeSignatureHandler implements RefactoringActionHandler {
- public static final String REFACTORING_NAME = RefactoringBundle.message("changeSignature.refactoring.name");
+public class JavaChangeSignatureHandler implements ChangeSignatureHandler {
public void invoke(@NotNull Project project, Editor editor, PsiFile file, DataContext dataContext) {
editor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE);
- PsiElement element = ChangeSignatureTargetUtil.findTargetMember(file, editor);
+ PsiElement element = findTargetMember(file, editor);
if (element == null) {
element = LangDataKeys.PSI_ELEMENT.getData(dataContext);
}
if (!CommonRefactoringUtil.checkReadOnlyStatus(project, method)) return;
final PsiClass containingClass = method.getContainingClass();
- if (containingClass != null && containingClass.isAnnotationType()) {
- CommonRefactoringUtil.showErrorHint(project, editor, REFACTORING_NAME + " is not supported for annotation types", REFACTORING_NAME, HelpID.CHANGE_SIGNATURE);
- return;
- }
final PsiReferenceExpression refExpr = editor != null ? TargetElementUtil.findReferenceExpression(editor) : null;
final ChangeSignatureDialog dialog = new ChangeSignatureDialog(project, method, containingClass != null && !containingClass.isInterface(),
refExpr);
ChangeClassSignatureDialog dialog = new ChangeClassSignatureDialog(aClass);
dialog.show();
}
+
+ @Nullable
+ public PsiElement findTargetMember(PsiFile file, Editor editor) {
+ PsiElement element = file.findElementAt(editor.getCaretModel().getOffset());
+ return findTargetMember(element);
+ }
+
+ public PsiElement findTargetMember(PsiElement element) {
+ if (PsiTreeUtil.getParentOfType(element, PsiParameterList.class) != null) {
+ return PsiTreeUtil.getParentOfType(element, PsiMethod.class);
+ }
+
+ if (element.getParent() instanceof PsiMethod && ((PsiMethod)element.getParent()).getNameIdentifier()==element) {
+ return element.getParent();
+ }
+
+ final PsiMethodCallExpression expression = PsiTreeUtil.getParentOfType(element, PsiMethodCallExpression.class);
+ if (expression != null) {
+ assert element != null;
+ final PsiExpression qualifierExpression = expression.getMethodExpression().getQualifierExpression();
+ if (PsiTreeUtil.isAncestor(qualifierExpression, element, false)) {
+ final PsiExpressionList expressionList = PsiTreeUtil.getParentOfType(qualifierExpression, PsiExpressionList.class);
+ if (expressionList != null) {
+ final PsiElement parent = expressionList.getParent();
+ if (parent instanceof PsiMethodCallExpression) {
+ return ((PsiMethodCallExpression)parent).resolveMethod();
+ }
+ }
+ }
+ else {
+ return expression.resolveMethod();
+ }
+ }
+
+ final PsiTypeParameterList typeParameterList = PsiTreeUtil.getParentOfType(element, PsiTypeParameterList.class);
+ if (typeParameterList != null) {
+ return PsiTreeUtil.getParentOfType(typeParameterList, PsiMember.class);
+ }
+
+ final PsiReferenceParameterList referenceParameterList = PsiTreeUtil.getParentOfType(element, PsiReferenceParameterList.class);
+ if (referenceParameterList != null) {
+ final PsiJavaCodeReferenceElement referenceElement =
+ PsiTreeUtil.getParentOfType(referenceParameterList, PsiJavaCodeReferenceElement.class);
+ if (referenceElement != null) {
+ final PsiElement resolved = referenceElement.resolve();
+ if (resolved instanceof PsiClass) {
+ return resolved;
+ }
+ else if (resolved instanceof PsiMethod) {
+ return resolved;
+ }
+ }
+ }
+ return null;
+ }
}
--- /dev/null
+/*
+ * 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 com.intellij.refactoring.changeSignature;
+
+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;
+import com.intellij.psi.codeStyle.VariableKind;
+import com.intellij.psi.scope.processor.VariablesProcessor;
+import com.intellij.psi.scope.util.PsiScopesUtil;
+import com.intellij.psi.util.*;
+import com.intellij.refactoring.RefactoringBundle;
+import com.intellij.refactoring.rename.RenameUtil;
+import com.intellij.refactoring.util.*;
+import com.intellij.refactoring.util.usageInfo.DefaultConstructorImplicitUsageInfo;
+import com.intellij.refactoring.util.usageInfo.NoConstructorClassUsageInfo;
+import com.intellij.usageView.UsageInfo;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.VisibilityUtil;
+import com.intellij.util.containers.HashSet;
+import com.intellij.util.containers.MultiMap;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.*;
+
+/**
+ * @author Maxim.Medvedev
+ */
+public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsageProcessor {
+ private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.changeSignature.JavaChangeSignatureUsageProcessor");
+
+ private static boolean isJavaUsage(UsageInfo info) {
+ final PsiElement element = info.getElement();
+ if (element == null) return false;
+ return element.getLanguage() == StdLanguages.JAVA;
+ }
+
+ public UsageInfo[] findUsages(ChangeInfo info) {
+ if (info instanceof JavaChangeInfo) {
+ return new JavaChangeSignatureUsageSearcher((JavaChangeInfo)info).findUsages();
+ }
+ else {
+ return UsageInfo.EMPTY_ARRAY;
+ }
+ }
+
+ public MultiMap<PsiElement, String> findConflicts(ChangeInfo info, Ref<UsageInfo[]> refUsages) {
+ if (info instanceof JavaChangeInfo) {
+ return new ConflictSearcher((JavaChangeInfo)info).findConflicts(refUsages);
+ }
+ else {
+ return new MultiMap<PsiElement, String>();
+ }
+ }
+
+ public boolean processUsage(ChangeInfo changeInfo, UsageInfo usage, boolean beforeMethodChange, UsageInfo[] usages) {
+ if (!isJavaUsage(usage)) return false;
+ if (!(changeInfo instanceof JavaChangeInfo)) return false;
+
+
+ if (beforeMethodChange) {
+ if (usage instanceof CallerUsageInfo) {
+ final CallerUsageInfo callerUsageInfo = (CallerUsageInfo)usage;
+ processCallerMethod((JavaChangeInfo)changeInfo, callerUsageInfo.getMethod(), null, callerUsageInfo.isToInsertParameter(),
+ callerUsageInfo.isToInsertException());
+ return true;
+ }
+ else if (usage instanceof OverriderUsageInfo) {
+ OverriderUsageInfo info = (OverriderUsageInfo)usage;
+ final PsiMethod method = info.getElement();
+ final PsiMethod baseMethod = info.getBaseMethod();
+ if (info.isOriginalOverrider()) {
+ processPrimaryMethod((JavaChangeInfo)changeInfo, method, baseMethod, false);
+ }
+ else {
+ processCallerMethod((JavaChangeInfo)changeInfo, method, baseMethod, info.isToInsertArgs(), info.isToCatchExceptions());
+ }
+ return true;
+ }
+
+ }
+ else {
+ PsiElement element = usage.getElement();
+ LOG.assertTrue(element != null);
+
+ if (usage instanceof DefaultConstructorImplicitUsageInfo) {
+ final DefaultConstructorImplicitUsageInfo defConstructorUsage = (DefaultConstructorImplicitUsageInfo)usage;
+ PsiMethod constructor = defConstructorUsage.getConstructor();
+ if (!constructor.isPhysical()) {
+ final boolean toPropagate =
+ changeInfo instanceof JavaChangeInfoImpl && ((JavaChangeInfoImpl)changeInfo).propagateParametersMethods.remove(constructor);
+ final PsiClass containingClass = defConstructorUsage.getContainingClass();
+ constructor = (PsiMethod)containingClass.add(constructor);
+ PsiUtil.setModifierProperty(constructor, VisibilityUtil.getVisibilityModifier(containingClass.getModifierList()), true);
+ if (toPropagate) {
+ ((JavaChangeInfoImpl)changeInfo).propagateParametersMethods.add(constructor);
+ }
+ }
+ addSuperCall((JavaChangeInfo)changeInfo, constructor, defConstructorUsage.getBaseConstructor(), usages);
+ return true;
+ }
+ else if (usage instanceof NoConstructorClassUsageInfo) {
+ addDefaultConstructor(((JavaChangeInfo)changeInfo), ((NoConstructorClassUsageInfo)usage).getPsiClass(), usages);
+ return true;
+ }
+ else if (usage instanceof MethodCallUsageInfo) {
+ final MethodCallUsageInfo methodCallInfo = (MethodCallUsageInfo)usage;
+ processMethodUsage(methodCallInfo.getElement(), (JavaChangeInfo)changeInfo, methodCallInfo.isToChangeArguments(),
+ methodCallInfo.isToCatchExceptions(), methodCallInfo.getReferencedMethod(), methodCallInfo.getSubstitutor(), usages);
+ return true;
+ }
+ else if (usage instanceof ChangeSignatureParameterUsageInfo) {
+ String newName = ((ChangeSignatureParameterUsageInfo)usage).newParameterName;
+ String oldName = ((ChangeSignatureParameterUsageInfo)usage).oldParameterName;
+ processParameterUsage((PsiReferenceExpression)element, oldName, newName);
+ return true;
+ }
+ else if (usage instanceof CallReferenceUsageInfo) {
+ ((CallReferenceUsageInfo)usage).getReference().handleChangeSignature(changeInfo);
+ return true;
+ }
+ else if (element instanceof PsiEnumConstant) {
+ fixActualArgumentsList(((PsiEnumConstant)element).getArgumentList(), (JavaChangeInfo)changeInfo, true, PsiSubstitutor.EMPTY);
+ return true;
+ }
+ else if (!(usage instanceof OverriderUsageInfo)) {
+ PsiReference reference = usage instanceof MoveRenameUsageInfo ? usage.getReference() : element.getReference();
+ if (reference != null) {
+ PsiElement target = changeInfo.getMethod();
+ if (target != null) {
+ reference.bindToElement(target);
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ private static void processParameterUsage(PsiReferenceExpression ref, String oldName, String newName)
+ throws IncorrectOperationException {
+
+ PsiElement last = ref.getReferenceNameElement();
+ if (last instanceof PsiIdentifier && last.getText().equals(oldName)) {
+ PsiElementFactory factory = JavaPsiFacade.getInstance(ref.getProject()).getElementFactory();
+ PsiIdentifier newNameIdentifier = factory.createIdentifier(newName);
+ last.replace(newNameIdentifier);
+ }
+ }
+
+
+ private static void addDefaultConstructor(JavaChangeInfo changeInfo, PsiClass aClass, final UsageInfo[] usages)
+ throws IncorrectOperationException {
+ if (!(aClass instanceof PsiAnonymousClass)) {
+ PsiElementFactory factory = JavaPsiFacade.getElementFactory(aClass.getProject());
+ PsiMethod defaultConstructor = factory.createMethodFromText(aClass.getName() + "(){}", aClass);
+ defaultConstructor = (PsiMethod)CodeStyleManager.getInstance(aClass.getProject()).reformat(defaultConstructor);
+ defaultConstructor = (PsiMethod)aClass.add(defaultConstructor);
+ PsiUtil.setModifierProperty(defaultConstructor, VisibilityUtil.getVisibilityModifier(aClass.getModifierList()), true);
+ addSuperCall(changeInfo, defaultConstructor, null, usages);
+ }
+ else {
+ final PsiElement parent = aClass.getParent();
+ if (parent instanceof PsiNewExpression) {
+ final PsiExpressionList argumentList = ((PsiNewExpression)parent).getArgumentList();
+ final PsiClass baseClass = changeInfo.getMethod().getContainingClass();
+ final PsiSubstitutor substitutor = TypeConversionUtil.getSuperClassSubstitutor(baseClass, aClass, PsiSubstitutor.EMPTY);
+ fixActualArgumentsList(argumentList, changeInfo, true, substitutor);
+ }
+ }
+ }
+
+ private static void addSuperCall(JavaChangeInfo changeInfo, PsiMethod constructor, PsiMethod callee, final UsageInfo[] usages)
+ throws IncorrectOperationException {
+ final PsiElementFactory factory = JavaPsiFacade.getElementFactory(constructor.getProject());
+ PsiExpressionStatement superCall = (PsiExpressionStatement)factory.createStatementFromText("super();", constructor);
+ PsiCodeBlock body = constructor.getBody();
+ assert body != null;
+ PsiStatement[] statements = body.getStatements();
+ if (statements.length > 0) {
+ superCall = (PsiExpressionStatement)body.addBefore(superCall, statements[0]);
+ }
+ else {
+ superCall = (PsiExpressionStatement)body.add(superCall);
+ }
+ PsiMethodCallExpression callExpression = (PsiMethodCallExpression)superCall.getExpression();
+ 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, PsiSubstitutor subsitutor, final UsageInfo[] usages) throws IncorrectOperationException {
+ if (changeInfo.isNameChanged()) {
+ if (ref instanceof PsiJavaCodeReferenceElement) {
+ PsiElement last = ((PsiJavaCodeReferenceElement)ref).getReferenceNameElement();
+ if (last instanceof PsiIdentifier && last.getText().equals(changeInfo.getOldName())) {
+ last.replace(changeInfo.getNewNameIdentifier());
+ }
+ }
+ }
+
+ final PsiMethod caller = RefactoringUtil.getEnclosingMethod(ref);
+ if (toChangeArguments) {
+ final PsiExpressionList list = RefactoringUtil.getArgumentListByMethodReference(ref);
+ boolean toInsertDefaultValue = !(changeInfo instanceof JavaChangeInfoImpl) || !((JavaChangeInfoImpl)changeInfo).propagateParametersMethods.contains(caller);
+ if (toInsertDefaultValue && ref instanceof PsiReferenceExpression) {
+ final PsiExpression qualifierExpression = ((PsiReferenceExpression)ref).getQualifierExpression();
+ if (qualifierExpression instanceof PsiSuperExpression && callerSignatureIsAboutToChangeToo(caller, usages)) {
+ toInsertDefaultValue = false;
+ }
+ }
+
+ fixActualArgumentsList(list, changeInfo, toInsertDefaultValue, subsitutor);
+ }
+
+ if (toCatchExceptions) {
+ if (!(ref instanceof PsiReferenceExpression &&
+ ((PsiReferenceExpression)ref).getQualifierExpression() instanceof PsiSuperExpression)) {
+ if (needToCatchExceptions(changeInfo, caller)) {
+ PsiClassType[] newExceptions =
+ callee != null ? getCalleeChangedExceptionInfo(callee) : getPrimaryChangedExceptionInfo(changeInfo);
+ fixExceptions(ref, newExceptions);
+ }
+ }
+ }
+ }
+
+ private static boolean callerSignatureIsAboutToChangeToo(final PsiMethod caller, final UsageInfo[] usages) {
+ for (UsageInfo usage : usages) {
+ if (usage instanceof MethodCallUsageInfo &&
+ MethodSignatureUtil.isSuperMethod(((MethodCallUsageInfo)usage).getReferencedMethod(), caller)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static PsiClassType[] getCalleeChangedExceptionInfo(final PsiMethod callee) {
+ return callee.getThrowsList().getReferencedTypes(); //Callee method's throws list is already modified!
+ }
+
+ private static void fixExceptions(PsiElement ref, PsiClassType[] newExceptions) throws IncorrectOperationException {
+ //methods' throws lists are already modified, may use ExceptionUtil.collectUnhandledExceptions
+ newExceptions = filterCheckedExceptions(newExceptions);
+
+ PsiElement context = PsiTreeUtil.getParentOfType(ref, PsiTryStatement.class, PsiMethod.class);
+ if (context instanceof PsiTryStatement) {
+ PsiTryStatement tryStatement = (PsiTryStatement)context;
+ PsiCodeBlock tryBlock = tryStatement.getTryBlock();
+
+ //Remove unused catches
+ Collection<PsiClassType> classes = ExceptionUtil.collectUnhandledExceptions(tryBlock, tryBlock);
+ PsiParameter[] catchParameters = tryStatement.getCatchBlockParameters();
+ for (PsiParameter parameter : catchParameters) {
+ final PsiType caughtType = parameter.getType();
+
+ if (!(caughtType instanceof PsiClassType)) continue;
+ if (ExceptionUtil.isUncheckedExceptionOrSuperclass((PsiClassType)caughtType)) continue;
+
+ if (!isCatchParameterRedundant((PsiClassType)caughtType, classes)) continue;
+ parameter.getParent().delete(); //delete catch section
+ }
+
+ PsiClassType[] exceptionsToAdd = filterUnhandledExceptions(newExceptions, tryBlock);
+ addExceptions(exceptionsToAdd, tryStatement);
+
+ adjustPossibleEmptyTryStatement(tryStatement);
+ }
+ else {
+ newExceptions = filterUnhandledExceptions(newExceptions, ref);
+ if (newExceptions.length > 0) {
+ //Add new try statement
+ PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(ref.getProject());
+ PsiTryStatement tryStatement = (PsiTryStatement)elementFactory.createStatementFromText("try {} catch (Exception e) {}", null);
+ PsiStatement anchor = PsiTreeUtil.getParentOfType(ref, PsiStatement.class);
+ LOG.assertTrue(anchor != null);
+ tryStatement.getTryBlock().add(anchor);
+ tryStatement = (PsiTryStatement)anchor.getParent().addAfter(tryStatement, anchor);
+
+ addExceptions(newExceptions, tryStatement);
+ anchor.delete();
+ tryStatement.getCatchSections()[0].delete(); //Delete dummy catch section
+ }
+ }
+ }
+
+ private static PsiClassType[] filterCheckedExceptions(PsiClassType[] exceptions) {
+ List<PsiClassType> result = new ArrayList<PsiClassType>();
+ for (PsiClassType exceptionType : exceptions) {
+ if (!ExceptionUtil.isUncheckedException(exceptionType)) result.add(exceptionType);
+ }
+ return result.toArray(new PsiClassType[result.size()]);
+ }
+
+ private static void adjustPossibleEmptyTryStatement(PsiTryStatement tryStatement) throws IncorrectOperationException {
+ PsiCodeBlock tryBlock = tryStatement.getTryBlock();
+ if (tryBlock != null) {
+ if (tryStatement.getCatchSections().length == 0 &&
+ tryStatement.getFinallyBlock() == null) {
+ PsiElement firstBodyElement = tryBlock.getFirstBodyElement();
+ if (firstBodyElement != null) {
+ tryStatement.getParent().addRangeAfter(firstBodyElement, tryBlock.getLastBodyElement(), tryStatement);
+ }
+ tryStatement.delete();
+ }
+ }
+ }
+
+ private static void addExceptions(PsiClassType[] exceptionsToAdd, PsiTryStatement tryStatement) throws IncorrectOperationException {
+ for (PsiClassType type : exceptionsToAdd) {
+ final JavaCodeStyleManager styleManager = JavaCodeStyleManager.getInstance(tryStatement.getProject());
+ String name = styleManager.suggestVariableName(VariableKind.PARAMETER, null, null, type).names[0];
+ name = styleManager.suggestUniqueVariableName(name, tryStatement, false);
+
+ PsiCatchSection catchSection =
+ JavaPsiFacade.getInstance(tryStatement.getProject()).getElementFactory().createCatchSection(type, name, tryStatement);
+ tryStatement.add(catchSection);
+ }
+ }
+
+ private static PsiClassType[] filterUnhandledExceptions(PsiClassType[] exceptions, PsiElement place) {
+ List<PsiClassType> result = new ArrayList<PsiClassType>();
+ for (PsiClassType exception : exceptions) {
+ if (!ExceptionUtil.isHandled(exception, place)) result.add(exception);
+ }
+ return result.toArray(new PsiClassType[result.size()]);
+ }
+
+ private static boolean isCatchParameterRedundant(PsiClassType catchParamType, Collection<PsiClassType> thrownTypes) {
+ for (PsiType exceptionType : thrownTypes) {
+ if (exceptionType.isConvertibleFrom(catchParamType)) return false;
+ }
+ return true;
+ }
+
+ //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, PsiSubstitutor substitutor) throws IncorrectOperationException {
+ final PsiElementFactory factory = JavaPsiFacade.getInstance(list.getProject()).getElementFactory();
+ if (changeInfo.isParameterSetOrOrderChanged()) {
+ if (changeInfo instanceof JavaChangeInfoImpl && ((JavaChangeInfoImpl)changeInfo).isPropagationEnabled) {
+ final ParameterInfoImpl[] createdParmsInfo = ((JavaChangeInfoImpl)changeInfo).getCreatedParmsInfoWithoutVarargs();
+ for (ParameterInfoImpl info : createdParmsInfo) {
+ PsiExpression newArg;
+ if (toInsertDefaultValue) {
+ newArg = createDefaultValue(changeInfo, factory, info, list);
+ }
+ else {
+ newArg = factory.createExpressionFromText(info.getName(), list);
+ }
+ list.add(newArg);
+ }
+ }
+ else {
+ final PsiExpression[] args = list.getExpressions();
+ final int nonVarargCount = getNonVarargCount(changeInfo, args);
+ final int varargCount = args.length - nonVarargCount;
+ PsiExpression[] newVarargInitializers = null;
+
+ final int newArgsLength;
+ final int newNonVarargCount;
+ final JavaParameterInfo[] newParms = changeInfo.getNewParameters();
+ if (changeInfo.isArrayToVarargs()) {
+ newNonVarargCount = newParms.length - 1;
+ final JavaParameterInfo lastNewParm = newParms[newParms.length - 1];
+ final PsiExpression arrayToConvert = args[lastNewParm.getOldIndex()];
+ if (arrayToConvert instanceof PsiNewExpression) {
+ final PsiNewExpression expression = (PsiNewExpression)arrayToConvert;
+ final PsiArrayInitializerExpression arrayInitializer = expression.getArrayInitializer();
+ if (arrayInitializer != null) {
+ newVarargInitializers = arrayInitializer.getInitializers();
+ }
+ }
+ newArgsLength = newVarargInitializers == null ? newParms.length : newNonVarargCount + newVarargInitializers.length;
+ }
+ else if (changeInfo.isRetainsVarargs()) {
+ newNonVarargCount = newParms.length - 1;
+ newArgsLength = newNonVarargCount + varargCount;
+ }
+ else if (changeInfo.isObtainsVarags()) {
+ newNonVarargCount = newParms.length - 1;
+ newArgsLength = newNonVarargCount;
+ }
+ else {
+ 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()) {
+ if (newVarargInitializers == null) {
+ newArgs[newNonVarargCount] =
+ createActualArgument(changeInfo, list, newParms[newNonVarargCount], toInsertDefaultValue, args);
+ }
+ else {
+ System.arraycopy(newVarargInitializers, 0, newArgs, newNonVarargCount, newVarargInitializers.length);
+ }
+ }
+ else {
+ final int newVarargCount = newArgsLength - newNonVarargCount;
+ LOG.assertTrue(newVarargCount == 0 || newVarargCount == varargCount);
+ System.arraycopy(args, nonVarargCount, newArgs, newNonVarargCount, newVarargCount);
+ }
+ ChangeSignatureUtil.synchronizeList(list, Arrays.asList(newArgs), ExpressionList.INSTANCE, changeInfo.toRemoveParm());
+ }
+ }
+ }
+
+ private static int getNonVarargCount(JavaChangeInfo changeInfo, PsiExpression[] args) {
+ if (!changeInfo.wasVararg()) return args.length;
+ return changeInfo.getOldParameterTypes().length - 1;
+ }
+
+
+ @Nullable
+ private static PsiExpression createActualArgument(JavaChangeInfo changeInfo,
+ final PsiExpressionList list,
+ final JavaParameterInfo info,
+ final boolean toInsertDefaultValue,
+ final PsiExpression[] args) throws IncorrectOperationException {
+ final PsiElementFactory factory = JavaPsiFacade.getInstance(list.getProject()).getElementFactory();
+ final int index = info.getOldIndex();
+ if (index >= 0) {
+ return args[index];
+ }
+ else {
+ if (toInsertDefaultValue) {
+ return createDefaultValue(changeInfo, factory, info, list);
+ }
+ else {
+ return factory.createExpressionFromText(info.getName(), list);
+ }
+ }
+ }
+
+ @Nullable
+ private static PsiExpression createDefaultValue(JavaChangeInfo changeInfo,
+ final PsiElementFactory factory,
+ final JavaParameterInfo info,
+ final PsiExpressionList list)
+ throws IncorrectOperationException {
+ if (info.isUseAnySingleVariable()) {
+ final PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(list.getProject()).getResolveHelper();
+ final PsiType type = info.getTypeWrapper().getType(changeInfo.getMethod(), list.getManager());
+ final VariablesProcessor processor = new VariablesProcessor(false) {
+ protected boolean check(PsiVariable var, ResolveState state) {
+ if (var instanceof PsiField && !resolveHelper.isAccessible((PsiField)var, list, null)) return false;
+ final PsiType varType = state.get(PsiSubstitutor.KEY).substitute(var.getType());
+ return type.isAssignableFrom(varType);
+ }
+
+ public boolean execute(PsiElement pe, ResolveState state) {
+ super.execute(pe, state);
+ return size() < 2;
+ }
+ };
+ PsiScopesUtil.treeWalkUp(processor, list, null);
+ if (processor.size() == 1) {
+ final PsiVariable result = processor.getResult(0);
+ return factory.createExpressionFromText(result.getName(), list);
+ }
+ }
+ final PsiCallExpression callExpression = PsiTreeUtil.getParentOfType(list, PsiCallExpression.class);
+ return callExpression != null ? info.getValue(callExpression) : factory.createExpressionFromText(info.getDefaultValue(), list);
+ }
+
+
+ public boolean processPrimaryMethod(ChangeInfo changeInfo) {
+ if (!StdLanguages.JAVA.equals(changeInfo.getLanguage()) || !(changeInfo instanceof JavaChangeInfo)) return false;
+ final PsiElement element = changeInfo.getMethod();
+ LOG.assertTrue(element instanceof PsiMethod);
+ if (changeInfo.isGenerateDelegate()) {
+ generateDelegate((JavaChangeInfo)changeInfo);
+ }
+ processPrimaryMethod((JavaChangeInfo)changeInfo, (PsiMethod)element, null, true);
+ return true;
+ }
+
+ public boolean shouldPreviewUsages(ChangeInfo changeInfo, UsageInfo[] usages) {
+ return false;
+ }
+
+ private static void generateDelegate(JavaChangeInfo changeInfo) throws IncorrectOperationException {
+ final PsiMethod delegate = (PsiMethod)changeInfo.getMethod().copy();
+ final PsiClass targetClass = changeInfo.getMethod().getContainingClass();
+ LOG.assertTrue(!targetClass.isInterface());
+ PsiElementFactory factory = JavaPsiFacade.getElementFactory(targetClass.getProject());
+ ChangeSignatureProcessor.makeEmptyBody(factory, delegate);
+ final PsiCallExpression callExpression = ChangeSignatureProcessor.addDelegatingCallTemplate(delegate, changeInfo.getNewName());
+ addDelegateArguments(changeInfo, factory, callExpression);
+ targetClass.addBefore(delegate, changeInfo.getMethod());
+ }
+
+
+ private static void addDelegateArguments(JavaChangeInfo changeInfo, PsiElementFactory factory, final PsiCallExpression callExpression) throws IncorrectOperationException {
+ final JavaParameterInfo[] newParms = changeInfo.getNewParameters();
+ final String[] oldParameterNames = changeInfo.getOldParameterNames();
+ for (int i = 0; i < newParms.length; i++) {
+ JavaParameterInfo newParm = newParms[i];
+ final PsiExpression actualArg;
+ if (newParm.getOldIndex() >= 0) {
+ actualArg = factory.createExpressionFromText(oldParameterNames[newParm.getOldIndex()], callExpression);
+ }
+ else {
+ actualArg = changeInfo.getValue(i, callExpression);
+ }
+ callExpression.getArgumentList().add(actualArg);
+ }
+ }
+
+ private static void processPrimaryMethod(JavaChangeInfo changeInfo, PsiMethod method,
+ PsiMethod baseMethod,
+ boolean isOriginal) throws IncorrectOperationException {
+ PsiElementFactory factory = JavaPsiFacade.getInstance(method.getProject()).getElementFactory();
+
+ if (changeInfo.isVisibilityChanged()) {
+ PsiModifierList modifierList = method.getModifierList();
+ final String highestVisibility = isOriginal
+ ? changeInfo.getNewVisibility()
+ : VisibilityUtil.getHighestVisibility(changeInfo.getNewVisibility(),
+ VisibilityUtil.getVisibilityModifier(modifierList));
+ VisibilityUtil.setVisibility(modifierList, highestVisibility);
+ }
+
+ if (changeInfo.isNameChanged()) {
+ String newName = baseMethod == null ? changeInfo.getNewName() :
+ RefactoringUtil.suggestNewOverriderName(method.getName(), baseMethod.getName(), changeInfo.getNewName());
+
+ if (newName != null && !newName.equals(method.getName())) {
+ final PsiIdentifier nameId = method.getNameIdentifier();
+ assert nameId != null;
+ nameId.replace(JavaPsiFacade.getInstance(method.getProject()).getElementFactory().createIdentifier(newName));
+ }
+ }
+
+ final PsiSubstitutor substitutor = baseMethod == null ? PsiSubstitutor.EMPTY : calculateSubstitutor(method, baseMethod);
+
+ if (changeInfo.isReturnTypeChanged()) {
+ PsiType newTypeElement = changeInfo.getNewReturnType().getType(changeInfo.getMethod().getParameterList(), method.getManager());
+ final PsiType returnType = substitutor.substitute(newTypeElement);
+ // don't modify return type for non-Java overriders (EJB)
+ if (method.getName().equals(changeInfo.getNewName())) {
+ final PsiTypeElement typeElement = method.getReturnTypeElement();
+ if (typeElement != null) {
+ typeElement.replace(factory.createTypeElement(returnType));
+ }
+ }
+ }
+
+ PsiParameterList list = method.getParameterList();
+ PsiParameter[] parameters = list.getParameters();
+
+ final JavaParameterInfo[] parameterInfos = changeInfo.getNewParameters();
+ PsiParameter[] newParms = new PsiParameter[parameterInfos.length];
+ final String[] oldParameterNames = changeInfo.getOldParameterNames();
+ final String[] oldParameterTypes = changeInfo.getOldParameterTypes();
+ for (int i = 0; i < newParms.length; i++) {
+ JavaParameterInfo info = parameterInfos[i];
+ int index = info.getOldIndex();
+ if (index >= 0) {
+ PsiParameter parameter = parameters[index];
+ newParms[i] = parameter;
+
+ String oldName = oldParameterNames[index];
+ if (!oldName.equals(info.getName()) && oldName.equals(parameter.getName())) {
+ PsiIdentifier newIdentifier = factory.createIdentifier(info.getName());
+ parameter.getNameIdentifier().replace(newIdentifier);
+ }
+
+ String oldType = oldParameterTypes[index];
+ if (!oldType.equals(info.getTypeText())) {
+ parameter.normalizeDeclaration();
+ PsiType newType = substitutor.substitute(info.createType(changeInfo.getMethod().getParameterList(), method.getManager()));
+
+ parameter.getTypeElement().replace(factory.createTypeElement(newType));
+ }
+ }
+ else {
+ newParms[i] = createNewParameter(changeInfo, info, substitutor);
+ }
+ }
+
+
+ resolveParameterVsFieldsConflicts(newParms, method, list, changeInfo.toRemoveParm());
+ fixJavadocsForChangedMethod(method, changeInfo);
+ if (changeInfo.isExceptionSetOrOrderChanged()) {
+ final PsiClassType[] newExceptions = getPrimaryChangedExceptionInfo(changeInfo);
+ fixPrimaryThrowsLists(method, newExceptions);
+ }
+ }
+
+ private static PsiClassType[] getPrimaryChangedExceptionInfo(JavaChangeInfo changeInfo) throws IncorrectOperationException {
+ final ThrownExceptionInfo[] newExceptionInfos = changeInfo.getNewExceptions();
+ PsiClassType[] newExceptions = new PsiClassType[newExceptionInfos.length];
+ final PsiMethod method = changeInfo.getMethod();
+ for (int i = 0; i < newExceptions.length; i++) {
+ newExceptions[i] =
+ (PsiClassType)newExceptionInfos[i].createType(method, method.getManager()); //context really does not matter here
+ }
+ return newExceptions;
+ }
+
+
+ private static void processCallerMethod(JavaChangeInfo changeInfo, 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 JavaParameterInfo[] primaryNewParms = changeInfo.getNewParameters();
+ PsiSubstitutor substitutor = baseMethod == null ? PsiSubstitutor.EMPTY : calculateSubstitutor(caller, baseMethod);
+ for (JavaParameterInfo info : primaryNewParms) {
+ if (info.getOldIndex() < 0) newParameters.add(createNewParameter(changeInfo, info, 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 = changeInfo.getNewExceptions();
+ for (ThrownExceptionInfo thrownExceptionInfo : primaryNewExns) {
+ if (thrownExceptionInfo.getOldIndex() < 0) {
+ final PsiClassType type = (PsiClassType)thrownExceptionInfo.createType(caller, caller.getManager());
+ final PsiJavaCodeReferenceElement ref =
+ JavaPsiFacade.getInstance(caller.getProject()).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 static void fixPrimaryThrowsLists(PsiMethod method, PsiClassType[] newExceptions) throws IncorrectOperationException {
+ PsiElementFactory elementFactory = JavaPsiFacade.getInstance(method.getProject()).getElementFactory();
+ PsiJavaCodeReferenceElement[] refs = new PsiJavaCodeReferenceElement[newExceptions.length];
+ for (int i = 0; i < refs.length; i++) {
+ refs[i] = elementFactory.createReferenceElementByType(newExceptions[i]);
+ }
+ PsiReferenceList throwsList = elementFactory.createReferenceList(refs);
+
+ PsiReferenceList methodThrowsList = (PsiReferenceList)method.getThrowsList().replace(throwsList);
+ methodThrowsList = (PsiReferenceList)JavaCodeStyleManager.getInstance(method.getProject()).shortenClassReferences(methodThrowsList);
+ method.getManager().getCodeStyleManager().reformatRange(method, method.getParameterList().getTextRange().getEndOffset(),
+ methodThrowsList.getTextRange().getEndOffset());
+ }
+
+ private static void fixJavadocsForChangedMethod(PsiMethod method, JavaChangeInfo changeInfo) throws IncorrectOperationException {
+ final PsiParameter[] parameters = method.getParameterList().getParameters();
+ final JavaParameterInfo[] newParms = changeInfo.getNewParameters();
+ LOG.assertTrue(parameters.length == newParms.length);
+ final Set<PsiParameter> newParameters = new HashSet<PsiParameter>();
+ final String[] oldParameterNames = changeInfo.getOldParameterNames();
+ for (int i = 0; i < newParms.length; i++) {
+ JavaParameterInfo newParm = newParms[i];
+ if (newParm.getOldIndex() < 0 ||
+ !newParm.getName().equals(oldParameterNames[newParm.getOldIndex()])) {
+ newParameters.add(parameters[i]);
+ }
+ }
+ RefactoringUtil.fixJavadocsForParams(method, newParameters);
+ }
+
+ private static PsiParameter createNewParameter(JavaChangeInfo changeInfo, JavaParameterInfo newParm,
+ PsiSubstitutor substitutor) throws IncorrectOperationException {
+ final PsiParameterList list = changeInfo.getMethod().getParameterList();
+ final PsiElementFactory factory = JavaPsiFacade.getInstance(list.getProject()).getElementFactory();
+ final PsiType type = substitutor.substitute(newParm.createType(list, list.getManager()));
+ return factory.createParameter(newParm.getName(), type);
+ }
+
+ private static void resolveParameterVsFieldsConflicts(final PsiParameter[] newParms,
+ final PsiMethod method,
+ final PsiParameterList list,
+ boolean[] toRemoveParm) throws IncorrectOperationException {
+ List<FieldConflictsResolver> conflictResolvers = new ArrayList<FieldConflictsResolver>();
+ for (PsiParameter parameter : newParms) {
+ conflictResolvers.add(new FieldConflictsResolver(parameter.getName(), method.getBody()));
+ }
+ ChangeSignatureUtil.synchronizeList(list, Arrays.asList(newParms), ParameterList.INSTANCE, toRemoveParm);
+ JavaCodeStyleManager.getInstance(list.getProject()).shortenClassReferences(list);
+ for (FieldConflictsResolver fieldConflictsResolver : conflictResolvers) {
+ fieldConflictsResolver.fix();
+ }
+ }
+
+ private static PsiSubstitutor calculateSubstitutor(PsiMethod derivedMethod, PsiMethod baseMethod) {
+ PsiSubstitutor substitutor;
+ if (derivedMethod.getManager().areElementsEquivalent(derivedMethod, baseMethod)) {
+ substitutor = PsiSubstitutor.EMPTY;
+ }
+ else {
+ 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 {
+ substitutor = PsiSubstitutor.EMPTY;
+ }
+ }
+ return substitutor;
+ }
+
+ private static boolean needToCatchExceptions(JavaChangeInfo changeInfo, PsiMethod caller) {
+ return changeInfo.isExceptionSetOrOrderChanged() &&
+ !(changeInfo instanceof JavaChangeInfoImpl && ((JavaChangeInfoImpl)changeInfo).propagateExceptionsMethods.contains(caller));
+ }
+
+ private static class ParameterList implements ChangeSignatureUtil.ChildrenGenerator<PsiParameterList, PsiParameter> {
+ public static final ParameterList INSTANCE = new ParameterList();
+
+ public List<PsiParameter> getChildren(PsiParameterList psiParameterList) {
+ return Arrays.asList(psiParameterList.getParameters());
+ }
+ }
+
+ private static class ThrowsList implements ChangeSignatureUtil.ChildrenGenerator<PsiReferenceList, PsiJavaCodeReferenceElement> {
+ public static final ThrowsList INSTANCE = new ThrowsList();
+
+ public List<PsiJavaCodeReferenceElement> getChildren(PsiReferenceList throwsList) {
+ return Arrays.asList(throwsList.getReferenceElements());
+ }
+ }
+
+ private static class ConflictSearcher {
+ private final JavaChangeInfo myChangeInfo;
+
+ private ConflictSearcher(JavaChangeInfo changeInfo) {
+ this.myChangeInfo = changeInfo;
+ }
+
+ public MultiMap<PsiElement, String> findConflicts(Ref<UsageInfo[]> refUsages) {
+ MultiMap<PsiElement, String> conflictDescriptions = new MultiMap<PsiElement, String>();
+ addMethodConflicts(conflictDescriptions);
+ Set<UsageInfo> usagesSet = new HashSet<UsageInfo>(Arrays.asList(refUsages.get()));
+ RenameUtil.removeConflictUsages(usagesSet);
+ if (myChangeInfo.isVisibilityChanged()) {
+ try {
+ addInaccessibilityDescriptions(usagesSet, conflictDescriptions);
+ }
+ catch (IncorrectOperationException e) {
+ LOG.error(e);
+ }
+ }
+
+ return conflictDescriptions;
+ }
+
+ private boolean needToChangeCalls() {
+ return myChangeInfo.isNameChanged() || myChangeInfo.isParameterSetOrOrderChanged() || myChangeInfo.isExceptionSetOrOrderChanged();
+ }
+
+
+ private void addInaccessibilityDescriptions(Set<UsageInfo> usages, MultiMap<PsiElement, String> conflictDescriptions)
+ throws IncorrectOperationException {
+ PsiMethod method = myChangeInfo.getMethod();
+ PsiModifierList modifierList = (PsiModifierList)method.getModifierList().copy();
+ VisibilityUtil.setVisibility(modifierList, myChangeInfo.getNewVisibility());
+
+ for (Iterator<UsageInfo> iterator = usages.iterator(); iterator.hasNext();) {
+ UsageInfo usageInfo = iterator.next();
+ PsiElement element = usageInfo.getElement();
+ if (element != null && StdLanguages.JAVA.equals(element.getLanguage())) {
+ if (element instanceof PsiReferenceExpression) {
+ PsiClass accessObjectClass = null;
+ PsiExpression qualifier = ((PsiReferenceExpression)element).getQualifierExpression();
+ if (qualifier != null) {
+ accessObjectClass = (PsiClass)PsiUtil.getAccessObjectClass(qualifier).getElement();
+ }
+
+ if (!JavaPsiFacade.getInstance(element.getProject()).getResolveHelper()
+ .isAccessible(method, modifierList, element, accessObjectClass, null)) {
+ String message =
+ RefactoringBundle.message("0.with.1.visibility.is.not.accesible.from.2",
+ RefactoringUIUtil.getDescription(method, true),
+ myChangeInfo.getNewVisibility(),
+ RefactoringUIUtil.getDescription(ConflictsUtil.getContainer(element), true));
+ conflictDescriptions.putValue(method, message);
+ if (!needToChangeCalls()) {
+ iterator.remove();
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ private void addMethodConflicts(MultiMap<PsiElement, String> conflicts) {
+ String newMethodName = myChangeInfo.getNewName();
+ if (!(myChangeInfo instanceof JavaChangeInfo)) {
+ return;
+ }
+ try {
+ PsiMethod prototype;
+ final PsiMethod method = myChangeInfo.getMethod();
+ if (!StdLanguages.JAVA.equals(method.getLanguage())) return;
+ PsiManager manager = PsiManager.getInstance(method.getProject());
+ PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory();
+ final CanonicalTypes.Type returnType = myChangeInfo.getNewReturnType();
+ if (returnType != null) {
+ prototype = factory.createMethod(newMethodName, returnType.getType(method, manager));
+ }
+ else {
+ prototype = factory.createConstructor();
+ prototype.setName(newMethodName);
+ }
+ JavaParameterInfo[] parameters = myChangeInfo.getNewParameters();
+
+
+ for (JavaParameterInfo info : parameters) {
+ 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);
+ }
+
+ ConflictsUtil.checkMethodConflicts(method.getContainingClass(), method, prototype, conflicts);
+ }
+ catch (IncorrectOperationException e) {
+ LOG.error(e);
+ }
+ }
+ }
+
+ private static class ExpressionList implements ChangeSignatureUtil.ChildrenGenerator<PsiExpressionList, PsiExpression> {
+ public static final ExpressionList INSTANCE = new ExpressionList();
+
+ public List<PsiExpression> getChildren(PsiExpressionList psiExpressionList) {
+ return Arrays.asList(psiExpressionList.getExpressions());
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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 com.intellij.refactoring.changeSignature;
+
+import com.intellij.lang.StdLanguages;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.Comparing;
+import com.intellij.psi.*;
+import com.intellij.psi.javadoc.PsiDocTagValue;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.search.searches.MethodReferencesSearch;
+import com.intellij.psi.search.searches.OverridingMethodsSearch;
+import com.intellij.psi.search.searches.ReferencesSearch;
+import com.intellij.psi.xml.XmlElement;
+import com.intellij.refactoring.RefactoringBundle;
+import com.intellij.refactoring.rename.JavaUnresolvableLocalCollisionDetector;
+import com.intellij.refactoring.rename.UnresolvableCollisionUsageInfo;
+import com.intellij.refactoring.util.MoveRenameUsageInfo;
+import com.intellij.refactoring.util.RefactoringUIUtil;
+import com.intellij.refactoring.util.RefactoringUtil;
+import com.intellij.refactoring.util.usageInfo.DefaultConstructorImplicitUsageInfo;
+import com.intellij.refactoring.util.usageInfo.NoConstructorClassUsageInfo;
+import com.intellij.usageView.UsageInfo;
+import com.intellij.usageView.UsageViewUtil;
+import com.intellij.util.containers.HashSet;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Set;
+
+/**
+ * @author Maxim.Medvedev
+ */
+class JavaChangeSignatureUsageSearcher {
+ private final JavaChangeInfo myChangeInfo;
+ private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.changeSignature.JavaChangeSignatureUsageSearcher");
+
+ JavaChangeSignatureUsageSearcher(JavaChangeInfo changeInfo) {
+ this.myChangeInfo = changeInfo;
+ }
+
+ public UsageInfo[] findUsages() {
+ ArrayList<UsageInfo> result = new ArrayList<UsageInfo>();
+ final PsiElement element = myChangeInfo.getMethod();
+ if (element instanceof PsiMethod) {
+ final PsiMethod method = (PsiMethod)element;
+
+ findSimpleUsages(method, result);
+
+ final UsageInfo[] usageInfos = result.toArray(new UsageInfo[result.size()]);
+ return UsageViewUtil.removeDuplicatedUsages(usageInfos);
+ }
+ return UsageInfo.EMPTY_ARRAY;
+ }
+
+
+ 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 void findUsagesInCallers(final ArrayList<UsageInfo> usages) {
+ if (myChangeInfo instanceof JavaChangeInfoImpl) {
+ JavaChangeInfoImpl changeInfo = (JavaChangeInfoImpl)myChangeInfo;
+
+ for (PsiMethod caller : changeInfo.propagateParametersMethods) {
+ usages.add(new CallerUsageInfo(caller, true, changeInfo.propagateExceptionsMethods.contains(caller)));
+ }
+ for (PsiMethod caller : changeInfo.propagateExceptionsMethods) {
+ usages.add(new CallerUsageInfo(caller, changeInfo.propagateParametersMethods.contains(caller), true));
+ }
+ Set<PsiMethod> merged = new HashSet<PsiMethod>();
+ merged.addAll(changeInfo.propagateParametersMethods);
+ merged.addAll(changeInfo.propagateExceptionsMethods);
+ for (final PsiMethod method : merged) {
+ findSimpleUsagesWithoutParameters(method, usages, changeInfo.propagateParametersMethods.contains(method),
+ changeInfo.propagateExceptionsMethods.contains(method), false);
+ }
+ }
+ }
+
+ private void detectLocalsCollisionsInMethod(final PsiMethod method, final ArrayList<UsageInfo> result, boolean isOriginal) {
+ if (!StdLanguages.JAVA.equals(method.getLanguage())) return;
+
+ final PsiParameter[] parameters = method.getParameterList().getParameters();
+ final Set<PsiParameter> deletedOrRenamedParameters = new HashSet<PsiParameter>();
+ if (isOriginal) {
+ deletedOrRenamedParameters.addAll(Arrays.asList(parameters));
+ for (ParameterInfo parameterInfo : myChangeInfo.getNewParameters()) {
+ if (parameterInfo.getOldIndex() >= 0) {
+ final PsiParameter parameter = parameters[parameterInfo.getOldIndex()];
+ if (parameterInfo.getName().equals(parameter.getName())) {
+ deletedOrRenamedParameters.remove(parameter);
+ }
+ }
+ }
+ }
+
+ for (ParameterInfo parameterInfo : myChangeInfo.getNewParameters()) {
+ final int oldParameterIndex = parameterInfo.getOldIndex();
+ final String newName = parameterInfo.getName();
+ if (oldParameterIndex >= 0) {
+ if (isOriginal) { //Name changes take place only in primary method
+ final PsiParameter parameter = parameters[oldParameterIndex];
+ if (!newName.equals(parameter.getName())) {
+ JavaUnresolvableLocalCollisionDetector.visitLocalsCollisions(
+ parameter, newName, method.getBody(), null,
+ new JavaUnresolvableLocalCollisionDetector.CollidingVariableVisitor() {
+ public void visitCollidingElement(final PsiVariable collidingVariable) {
+ if (!deletedOrRenamedParameters.contains(collidingVariable)) {
+ result.add(new RenamedParameterCollidesWithLocalUsageInfo(parameter, collidingVariable, method));
+ }
+ }
+ });
+ }
+ }
+ }
+ else {
+ JavaUnresolvableLocalCollisionDetector.visitLocalsCollisions(
+ method, newName, method.getBody(), null,
+ new JavaUnresolvableLocalCollisionDetector.CollidingVariableVisitor() {
+ public void visitCollidingElement(PsiVariable collidingVariable) {
+ if (!deletedOrRenamedParameters.contains(collidingVariable)) {
+ result.add(new NewParameterCollidesWithLocalUsageInfo(
+ collidingVariable, collidingVariable, method));
+ }
+ }
+ });
+ }
+ }
+ }
+
+ private void findParametersUsage(final PsiMethod method, ArrayList<UsageInfo> result, PsiMethod[] overriders) {
+ if (StdLanguages.JAVA.equals(myChangeInfo.getLanguage())) {
+ PsiParameter[] parameters = method.getParameterList().getParameters();
+ for (ParameterInfo info : myChangeInfo.getNewParameters()) {
+ if (info.getOldIndex() >= 0) {
+ PsiParameter parameter = parameters[info.getOldIndex()];
+ if (!info.getName().equals(parameter.getName())) {
+ addParameterUsages(parameter, result, info);
+
+ for (PsiMethod overrider : overriders) {
+ PsiParameter parameter1 = overrider.getParameterList().getParameters()[info.getOldIndex()];
+ if (parameter.getName().equals(parameter1.getName())) {
+ addParameterUsages(parameter1, result, info);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private static boolean shouldPropagateToNonPhysicalMethod(PsiMethod method,
+ ArrayList<UsageInfo> result,
+ PsiClass containingClass,
+ final Set<PsiMethod> propagateMethods) {
+ for (PsiMethod psiMethod : propagateMethods) {
+ if (!psiMethod.isPhysical() && Comparing.strEqual(psiMethod.getName(), containingClass.getName())) {
+ result.add(new DefaultConstructorImplicitUsageInfo(psiMethod, containingClass, method));
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private PsiMethod[] findSimpleUsagesWithoutParameters(final PsiMethod method,
+ final ArrayList<UsageInfo> result,
+ boolean isToModifyArgs,
+ boolean isToThrowExceptions,
+ boolean isOriginal) {
+
+ GlobalSearchScope projectScope = GlobalSearchScope.projectScope(method.getProject());
+ PsiMethod[] overridingMethods = OverridingMethodsSearch.search(method, method.getUseScope(), true).toArray(PsiMethod.EMPTY_ARRAY);
+
+ for (PsiMethod overridingMethod : overridingMethods) {
+ result.add(new OverriderUsageInfo(overridingMethod, method, isOriginal, isToModifyArgs, isToThrowExceptions));
+ }
+
+ boolean needToChangeCalls =
+ !myChangeInfo.isGenerateDelegate() && (myChangeInfo.isNameChanged() ||
+ myChangeInfo.isParameterSetOrOrderChanged() ||
+ myChangeInfo.isExceptionSetOrOrderChanged() ||
+ myChangeInfo.isVisibilityChanged()/*for checking inaccessible*/);
+ if (needToChangeCalls) {
+ int parameterCount = method.getParameterList().getParametersCount();
+
+ PsiReference[] refs = MethodReferencesSearch.search(method, projectScope, true).toArray(PsiReference.EMPTY_ARRAY);
+ for (PsiReference ref : refs) {
+ PsiElement element = ref.getElement();
+
+ boolean isToCatchExceptions = isToThrowExceptions && needToCatchExceptions(RefactoringUtil.getEnclosingMethod(element));
+ if (!isToCatchExceptions) {
+ if (RefactoringUtil.isMethodUsage(element)) {
+ PsiExpressionList list = RefactoringUtil.getArgumentListByMethodReference(element);
+ if (!method.isVarArgs() && list.getExpressions().length != parameterCount) continue;
+ }
+ }
+ if (RefactoringUtil.isMethodUsage(element)) {
+ result.add(new MethodCallUsageInfo(element, isToModifyArgs, isToCatchExceptions));
+ }
+ else if (element instanceof PsiDocTagValue) {
+ result.add(new UsageInfo(element));
+ }
+ else if (element instanceof PsiMethod && ((PsiMethod)element).isConstructor()) {
+ if (StdLanguages.JAVA.equals(element.getLanguage())) {
+ DefaultConstructorImplicitUsageInfo implicitUsageInfo =
+ new DefaultConstructorImplicitUsageInfo((PsiMethod)element, ((PsiMethod)element).getContainingClass(), method);
+ result.add(implicitUsageInfo);
+ }
+ }
+ else if (element instanceof PsiClass) {
+ LOG.assertTrue(method.isConstructor());
+ final PsiClass psiClass = (PsiClass)element;
+ if (StdLanguages.JAVA.equals(psiClass.getLanguage())) {
+ if (myChangeInfo instanceof JavaChangeInfoImpl) {
+ if (shouldPropagateToNonPhysicalMethod(method, result, psiClass,
+ ((JavaChangeInfoImpl)myChangeInfo).propagateParametersMethods)) {
+ continue;
+ }
+ if (shouldPropagateToNonPhysicalMethod(method, result, psiClass,
+ ((JavaChangeInfoImpl)myChangeInfo).propagateExceptionsMethods)) {
+ continue;
+ }
+ }
+ result.add(new NoConstructorClassUsageInfo(psiClass));
+ }
+ }
+ else if (ref instanceof PsiCallReference) {
+ result.add(new CallReferenceUsageInfo((PsiCallReference)ref));
+ }
+ else {
+ result.add(new MoveRenameUsageInfo(element, ref, method));
+ }
+ }
+
+ //if (method.isConstructor() && parameterCount == 0) {
+ // RefactoringUtil.visitImplicitConstructorUsages(method.getContainingClass(),
+ // new DefaultConstructorUsageCollector(result));
+ //}
+ }
+ else if (myChangeInfo.isParameterTypesChanged()) {
+ PsiReference[] refs = MethodReferencesSearch.search(method, projectScope, true).toArray(PsiReference.EMPTY_ARRAY);
+ for (PsiReference reference : refs) {
+ final PsiElement element = reference.getElement();
+ if (element instanceof PsiDocTagValue) {
+ result.add(new UsageInfo(reference));
+ }
+ else if (element instanceof XmlElement) {
+ result.add(new MoveRenameUsageInfo(reference, method));
+ }
+ }
+ }
+
+ // Conflicts
+ detectLocalsCollisionsInMethod(method, result, isOriginal);
+ for (final PsiMethod overridingMethod : overridingMethods) {
+ detectLocalsCollisionsInMethod(overridingMethod, result, isOriginal);
+ }
+
+ return overridingMethods;
+ }
+
+
+ private static void addParameterUsages(PsiParameter parameter, ArrayList<UsageInfo> results, ParameterInfo info) {
+ PsiManager manager = parameter.getManager();
+ GlobalSearchScope projectScope = GlobalSearchScope.projectScope(manager.getProject());
+ for (PsiReference psiReference : ReferencesSearch.search(parameter, projectScope, false)) {
+ PsiElement parmRef = psiReference.getElement();
+ UsageInfo usageInfo = new ChangeSignatureParameterUsageInfo(parmRef, parameter.getName(), info.getName());
+ results.add(usageInfo);
+ }
+ }
+
+ private boolean needToCatchExceptions(PsiMethod caller) {
+ if (myChangeInfo instanceof JavaChangeInfoImpl) {
+ return myChangeInfo.isExceptionSetOrOrderChanged() &&
+ !((JavaChangeInfoImpl)myChangeInfo).propagateExceptionsMethods.contains(caller);
+ }
+ else {
+ return myChangeInfo.isExceptionSetOrOrderChanged();
+ }
+ }
+
+ private static class RenamedParameterCollidesWithLocalUsageInfo extends UnresolvableCollisionUsageInfo {
+ private final PsiElement myCollidingElement;
+ private final PsiMethod myMethod;
+
+ public RenamedParameterCollidesWithLocalUsageInfo(PsiParameter parameter, PsiElement collidingElement, PsiMethod method) {
+ super(parameter, collidingElement);
+ myCollidingElement = collidingElement;
+ myMethod = method;
+ }
+
+ public String getDescription() {
+ return RefactoringBundle.message("there.is.already.a.0.in.the.1.it.will.conflict.with.the.renamed.parameter",
+ RefactoringUIUtil.getDescription(myCollidingElement, true),
+ RefactoringUIUtil.getDescription(myMethod, true));
+ }
+ }
+}
--- /dev/null
+/*
+ * 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 com.intellij.refactoring.changeSignature;
+
+import com.intellij.psi.*;
+import com.intellij.refactoring.util.CanonicalTypes;
+import com.intellij.util.IncorrectOperationException;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Maxim.Medvedev
+ */
+public interface JavaParameterInfo extends ParameterInfo {
+ @Nullable
+ PsiType createType(PsiElement context, final PsiManager manager) throws IncorrectOperationException;
+
+ String getTypeText();
+
+ CanonicalTypes.Type getTypeWrapper();
+
+ PsiExpression getValue(PsiCallExpression callExpression);
+
+ boolean isVarargType();
+
+ boolean isUseAnySingleVariable();
+}
--- /dev/null
+/*
+ * 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 com.intellij.refactoring.changeSignature;
+
+import com.intellij.psi.*;
+import com.intellij.refactoring.util.CanonicalTypes;
+import com.intellij.util.IncorrectOperationException;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Maxim.Medvedev
+ */
+public class JavaThrownExceptionInfo implements ThrownExceptionInfo {
+ private final int oldIndex;
+ private CanonicalTypes.Type myType;
+
+ public JavaThrownExceptionInfo() {
+ oldIndex = -1;
+ }
+
+ public JavaThrownExceptionInfo(int oldIndex) {
+ this.oldIndex = oldIndex;
+ }
+
+ public JavaThrownExceptionInfo(int oldIndex, PsiClassType type) {
+ this.oldIndex = oldIndex;
+ setType(type);
+ }
+
+ public void setType(PsiClassType type) {
+ myType = CanonicalTypes.createTypeWrapper(type);
+ }
+
+ @Nullable
+ public PsiType createType(PsiElement context, final PsiManager manager) throws IncorrectOperationException {
+ if (myType != null) {
+ return myType.getType(context, manager);
+ }
+ else {
+ return null;
+ }
+ }
+
+ public void updateFromMethod(PsiMethod method) {
+ if (myType != null) return;
+ PsiClassType[] types = method.getThrowsList().getReferencedTypes();
+ if (oldIndex >= 0) {
+ setType(types[oldIndex]);
+ }
+ }
+
+ public int getOldIndex() {
+ return oldIndex;
+ }
+}
private final boolean myToChangeArguments;
private final boolean myToCatchExceptions;
private final PsiMethod myReferencedMethod;
+ private final PsiSubstitutor mySubstitutor;
public boolean isToCatchExceptions() {
return myToCatchExceptions;
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");
public PsiMethod getReferencedMethod() {
return myReferencedMethod;
}
+
+ public PsiSubstitutor getSubstitutor() {
+ return mySubstitutor;
+ }
}
import java.util.ArrayList;
import java.util.List;
-public class ParameterInfoImpl implements ParameterInfo {
+public class ParameterInfoImpl implements JavaParameterInfo {
private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.changeSignature.ParameterInfoImpl");
public final int oldParameterIndex;
boolean useAnySingleVariable;
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
if (rowIndex < 0 || rowIndex >= myParameterInfos.size()) return;
- String s = aValue instanceof String ? (String)aValue : null;
- if (s == null) s = "";
+ String s = aValue instanceof String ? (String)aValue : "";
s = s.trim();
ParameterInfoImpl info = myParameterInfos.get(rowIndex);
switch (columnIndex) {
}
private JavaCodeFragment createDefaultValueCodeFragment(final String expressionText, final PsiType expectedType) {
- PsiExpressionCodeFragment codeFragment = JavaPsiFacade.getInstance(myParameterList.getProject()).getElementFactory().createExpressionCodeFragment(expressionText,
- myReferenceExpression, expectedType, true);
+ PsiExpressionCodeFragment codeFragment = JavaPsiFacade.getInstance(myParameterList.getProject()).getElementFactory()
+ .createExpressionCodeFragment(expressionText, myReferenceExpression, expectedType, true);
codeFragment.setVisibilityChecker(JavaCodeFragment.VisibilityChecker.EVERYTHING_VISIBLE);
return codeFragment;
}
--- /dev/null
+/*
+ * 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 com.intellij.refactoring.changeSignature;
+
+/**
+ * All Usages that may be incorrect must implement this interface. In other case incorrect usages will be processed by default processor
+ * @author Maxim.Medvedev
+ */
+public interface PossiblyIncorrectUsage {
+ boolean isCorrect();
+}
package com.intellij.refactoring.changeSignature;
import com.intellij.psi.*;
-import com.intellij.refactoring.util.CanonicalTypes;
import com.intellij.util.IncorrectOperationException;
+import org.jetbrains.annotations.Nullable;
/**
* @author ven
*/
-public class ThrownExceptionInfo {
- int oldIndex;
- CanonicalTypes.Type myType;
+public interface ThrownExceptionInfo {
+ void setType(PsiClassType type);
- public ThrownExceptionInfo() {
- oldIndex = -1;
- }
+ @Nullable
+ PsiType createType(PsiElement context, final PsiManager manager) throws IncorrectOperationException;
- public ThrownExceptionInfo(int oldIndex) {
- this.oldIndex = oldIndex;
- }
+ void updateFromMethod(PsiMethod method);
- public ThrownExceptionInfo(int oldIndex, PsiClassType type) {
- this.oldIndex = oldIndex;
- setType(type);
- }
-
- public void setType(PsiClassType type) {
- myType = CanonicalTypes.createTypeWrapper(type);
- }
-
- public PsiType createType(PsiElement context, final PsiManager manager) throws IncorrectOperationException {
- if (myType != null) {
- return myType.getType(context, manager);
- } else {
- return null;
- }
- }
-
- String getTypeText() {
- if (myType != null) {
- return myType.getTypeText();
- }
- else {
- return "";
- }
- }
-
- public void updateFromMethod(PsiMethod method) {
- if (myType != null) return;
- PsiClassType[] types = method.getThrowsList().getReferencedTypes();
- if (oldIndex >= 0) {
- setType(types[oldIndex]);
- }
- }
-
- public int getOldIndex() {
- return oldIndex;
- }
+ int getOldIndex();
}
import com.intellij.refactoring.util.occurences.OccurenceManager;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+
import java.util.ArrayList;
public class IntroduceConstantHandler extends BaseExpressionToFieldHandler {
import com.intellij.refactoring.JavaRefactoringActionHandlerFactory;
import com.intellij.refactoring.RefactoringActionHandler;
import com.intellij.refactoring.anonymousToInner.AnonymousToInnerHandler;
-import com.intellij.refactoring.changeSignature.ChangeSignatureHandler;
+import com.intellij.refactoring.changeSignature.JavaChangeSignatureHandler;
import com.intellij.refactoring.convertToInstanceMethod.ConvertToInstanceMethodHandler;
import com.intellij.refactoring.encapsulateFields.EncapsulateFieldsHandler;
import com.intellij.refactoring.extractInterface.ExtractInterfaceHandler;
}
public RefactoringActionHandler createChangeSignatureHandler() {
- return new ChangeSignatureHandler();
+ return new JavaChangeSignatureHandler();
}
public RefactoringActionHandler createExtractSuperclassHandler() {
-import java.io.*;
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InterruptedIOException;
public interface Idea4780 {
/**
-import java.util.*;
+import java.util.Map;
class Test {
Map someMap;
package br.com.vivo.torpedeiro.pull.impl;
-import javax.sql.DataSource;
-import org.springframework.jdbc.core.JdbcTemplate;
import br.com.vivo.torpedeiro.pull.MensagemPull;
import br.com.vivo.torpedeiro.pull.PullDAO;
+import org.springframework.jdbc.core.JdbcTemplate;
+
+import javax.sql.DataSource;
/**
* Implementa? padr?de {@link PullDAO} que realiza todas as opera?s utilizando SQL atrav?de um {@link
package br.com.vivo.torpedeiro.pull.impl;
-import javax.sql.DataSource;
-
-import org.springframework.jdbc.core.JdbcTemplate;
import br.com.vivo.torpedeiro.pull.MensagemPull;
import br.com.vivo.torpedeiro.pull.PullDAO;
+import org.springframework.jdbc.core.JdbcTemplate;
+
+import javax.sql.DataSource;
/**
* Implementa? padr?de {@link PullDAO} que realiza todas as opera?s utilizando SQL atrav?de um {@link
--- /dev/null
+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>());
+ }
+}
+
--- /dev/null
+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");
+ }
+}
+
-import java.util.*;
class A1<T> {
A1(){}
import com.intellij.psi.search.searches.ClassInheritorsSearch;
import com.intellij.psi.search.searches.MethodReferencesSearch;
import com.intellij.refactoring.changeSignature.ChangeSignatureProcessor;
+import com.intellij.refactoring.changeSignature.JavaThrownExceptionInfo;
import com.intellij.refactoring.changeSignature.ParameterInfoImpl;
import com.intellij.refactoring.changeSignature.ThrownExceptionInfo;
import com.intellij.refactoring.util.CanonicalTypes;
private void exceptionPropagationTest(final PsiMethod method, final Set<PsiMethod> methodsToPropagateExceptions) throws Exception {
PsiClassType newExceptionType = JavaPsiFacade.getElementFactory(getProject()).createTypeByFQClassName("java.lang.Exception", GlobalSearchScope.allScope(getProject()));
- final ThrownExceptionInfo[] newExceptions = new ThrownExceptionInfo[]{new ThrownExceptionInfo(-1, newExceptionType)};
+ final ThrownExceptionInfo[] newExceptions = new ThrownExceptionInfo[]{new JavaThrownExceptionInfo(-1, newExceptionType)};
doTest(new ParameterInfoImpl[0], newExceptions, null, methodsToPropagateExceptions, method);
}
final PsiClassType[] exceptions = method.getThrowsList().getReferencedTypes();
ThrownExceptionInfo[] result = new ThrownExceptionInfo[exceptions.length + newExceptions.length];
for (int i = 0; i < exceptions.length; i++) {
- result[i] = new ThrownExceptionInfo(i);
+ result[i] = new JavaThrownExceptionInfo(i);
}
System.arraycopy(newExceptions, 0, result, exceptions.length, newExceptions.length);
return result;
import com.intellij.JavaTestUtil;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.impl.JavaSdkImpl;
+import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiMember;
-import com.intellij.refactoring.changeSignature.ChangeSignatureTargetUtil;
+import com.intellij.refactoring.changeSignature.JavaChangeSignatureHandler;
import com.intellij.testFramework.LightCodeInsightTestCase;
import org.jetbrains.annotations.NonNls;
String basePath = "/refactoring/changeSignatureTarget/" + getTestName(true);
@NonNls final String filePath = basePath + ".java";
configureByFile(filePath);
- final PsiMember member = ChangeSignatureTargetUtil.findTargetMember(getFile(), getEditor());
+ final PsiElement member = new JavaChangeSignatureHandler().findTargetMember(getFile(), getEditor());
assertNotNull(member);
- assertEquals(expectedMemberName, member.getName());
+ assertEquals(expectedMemberName, ((PsiMember)member).getName());
}
}
import com.intellij.codeInsight.TargetElementUtilBase;
import com.intellij.psi.*;
import com.intellij.refactoring.changeSignature.ChangeSignatureProcessor;
+import com.intellij.refactoring.changeSignature.JavaThrownExceptionInfo;
import com.intellij.refactoring.changeSignature.ParameterInfoImpl;
import com.intellij.refactoring.changeSignature.ThrownExceptionInfo;
import com.intellij.testFramework.LightCodeInsightTestCase;
public void testReorderExceptions() throws Exception {
doTest(null, null, null, new SimpleParameterGen(new ParameterInfoImpl[0]),
- new SimpleExceptionsGen(new ThrownExceptionInfo[]{new ThrownExceptionInfo(1), new ThrownExceptionInfo(0)}),
+ new SimpleExceptionsGen(new ThrownExceptionInfo[]{new JavaThrownExceptionInfo(1), new JavaThrownExceptionInfo(0)}),
false);
}
new GenExceptions() {
public ThrownExceptionInfo[] genExceptions(PsiMethod method) {
return new ThrownExceptionInfo[] {
- new ThrownExceptionInfo(-1, JavaPsiFacade.getInstance(method.getProject()).getElementFactory().createTypeByFQClassName("java.lang.Exception", method.getResolveScope()))
+ new JavaThrownExceptionInfo(-1, JavaPsiFacade.getInstance(method.getProject()).getElementFactory().createTypeByFQClassName("java.lang.Exception", method.getResolveScope()))
};
}
},
new GenExceptions() {
public ThrownExceptionInfo[] genExceptions(PsiMethod method) {
return new ThrownExceptionInfo[] {
- new ThrownExceptionInfo(-1, JavaPsiFacade.getInstance(method.getProject()).getElementFactory().createTypeByFQClassName("java.lang.RuntimeException", method.getResolveScope()))
+ new JavaThrownExceptionInfo(-1, JavaPsiFacade.getInstance(method.getProject()).getElementFactory().createTypeByFQClassName("java.lang.RuntimeException", method.getResolveScope()))
};
}
},
new GenExceptions() {
public ThrownExceptionInfo[] genExceptions(PsiMethod method) {
return new ThrownExceptionInfo[] {
- new ThrownExceptionInfo(-1, JavaPsiFacade.getInstance(method.getProject()).getElementFactory().createTypeByFQClassName("java.lang.Exception", method.getResolveScope()))
+ new JavaThrownExceptionInfo(-1, JavaPsiFacade.getInstance(method.getProject()).getElementFactory().createTypeByFQClassName("java.lang.Exception", method.getResolveScope()))
};
}
},
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);
}
*/
package com.intellij.refactoring;
+import com.intellij.JavaTestUtil;
import com.intellij.codeInsight.TargetElementUtilBase;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.refactoring.makeStatic.Settings;
import com.intellij.refactoring.util.ParameterTablePanel;
import com.intellij.testFramework.LightCodeInsightTestCase;
-import com.intellij.JavaTestUtil;
import java.util.ArrayList;
import com.intellij.psi.PsiElement;
import com.intellij.refactoring.RefactoringActionHandler;
+import com.intellij.refactoring.changeSignature.ChangeSignatureHandler;
import org.jetbrains.annotations.Nullable;
/**
public boolean doInplaceRenameFor(final PsiElement element, final PsiElement context) {
return false;
}
+
+ public ChangeSignatureHandler getChangeSignatureHandler() {
+ return null;
+ }
}
import com.intellij.psi.PsiElement;
import com.intellij.refactoring.RefactoringActionHandler;
+import com.intellij.refactoring.changeSignature.ChangeSignatureHandler;
import org.jetbrains.annotations.Nullable;
/**
*/
@Nullable RefactoringActionHandler getExtractSuperClassHandler();
+ /**
+ * @return handler for changing signature in this language
+ * @see com.intellij.refactoring.RefactoringActionHandler
+ */
+ @Nullable ChangeSignatureHandler getChangeSignatureHandler();
+
boolean doInplaceRenameFor(PsiElement element, PsiElement context);
}
package com.intellij.refactoring.changeSignature;
+import com.intellij.lang.Language;
+import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
/**
ParameterInfo[] getNewParameters();
boolean isParameterSetOrOrderChanged();
+
+ boolean isParameterTypesChanged();
+
+ boolean isParameterNamesChanged();
+
+ boolean isGenerateDelegate();
+
+ boolean isNameChanged();
+
+ PsiElement getMethod();
+
+ boolean isReturnTypeChanged();
+
+ String getNewName();
+
+ Language getLanguage();
}
--- /dev/null
+/*
+ * 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 com.intellij.refactoring.changeSignature;
+
+import com.intellij.openapi.editor.Editor;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.refactoring.RefactoringActionHandler;
+import com.intellij.refactoring.RefactoringBundle;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Maxim.Medvedev
+ */
+public interface ChangeSignatureHandler extends RefactoringActionHandler {
+ String REFACTORING_NAME = RefactoringBundle.message("changeSignature.refactoring.name");
+
+ @Nullable
+ PsiElement findTargetMember(PsiFile file, Editor editor);
+
+ @Nullable
+ PsiElement findTargetMember(PsiElement element);
+}
--- /dev/null
+/*
+ * 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 com.intellij.refactoring.changeSignature;
+
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.openapi.util.Ref;
+import com.intellij.psi.PsiElement;
+import com.intellij.usageView.UsageInfo;
+import com.intellij.util.containers.MultiMap;
+
+/**
+ * @author Maxim.Medvedev
+ */
+public interface ChangeSignatureUsageProcessor {
+ ExtensionPointName<ChangeSignatureUsageProcessor> EP_NAME =
+ new ExtensionPointName<ChangeSignatureUsageProcessor>("com.intellij.refactoring.changeSignatureUsageProcessor");
+
+ UsageInfo[] findUsages(ChangeInfo info);
+
+ MultiMap<PsiElement, String> findConflicts(ChangeInfo info, Ref<UsageInfo[]> refUsages);
+
+ boolean processUsage(ChangeInfo changeInfo, UsageInfo usageInfo, boolean beforeMethodChange, UsageInfo[] usages);
+
+ boolean processPrimaryMethod(ChangeInfo changeInfo);
+
+ boolean shouldPreviewUsages(ChangeInfo changeInfo, UsageInfo[] usages);
+}
import com.intellij.openapi.fileEditor.impl.FileEditorManagerImpl;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.StdFileTypes;
-import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.DialogBuilder;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.TextRange;
import com.intellij.history.core.tree.DirectoryEntry;
import com.intellij.history.core.tree.Entry;
import com.intellij.history.core.tree.FileEntry;
-import com.intellij.history.core.tree.RootEntry;
import java.io.DataInput;
import java.io.DataOutput;
for (Change each : changes) {
actual.add(((StructuralChange)each).getPath());
}
-
+
List<String> expected = new ArrayList<String>(Arrays.asList(dir1, dir2, f1, f2));
Collections.sort(actual);
ReadOnlyAttributeUtil.setReadOnlyAttribute(f, false);
assertEquals(3, getRevisionsFor(f).size());
}
-
+
public void testIgnoringROStstusChangeForUnversionedFiles() throws Exception {
int before = getRevisionsFor(myRoot).size();
assertEquals(before, getRevisionsFor(myRoot).size());
}
-
+
public void testDeletion() throws Exception {
VirtualFile f = createDirectory("f.txt");
public void testCreationAndDeletionOfUnversionedFile() throws IOException {
addExcludedDir(myRoot.getPath() + "/dir");
-
+
Module m = createModule("foo");
addContentRoot(m, myRoot.getPath() + "/dir/subDir");
package com.intellij.ui.content;
import com.intellij.openapi.Disposable;
-import com.intellij.openapi.util.ActionCallback;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.DataProvider;
+import com.intellij.openapi.util.ActionCallback;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
-import javax.swing.tree.TreeModel;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import com.intellij.util.ui.UIUtil;
import javax.swing.*;
-import javax.swing.border.Border;
import java.awt.*;
import java.util.ArrayList;
import java.util.Arrays;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.PopupHandler;
-import com.intellij.ui.UIBundle;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.ShadowAction;
import com.intellij.openapi.ui.Queryable;
+import com.intellij.openapi.ui.ShadowAction;
import com.intellij.openapi.util.*;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.IdeFocusManager;
import java.awt.event.KeyEvent;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
-import java.util.Iterator;
import java.util.Map;
import java.util.Set;
package com.intellij.openapi.wm.impl;
import com.intellij.openapi.Disposable;
-import com.intellij.openapi.ui.MessageType;
-import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.DataProvider;
+import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.util.ActionCallback;
-import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.ActiveRunnable;
+import com.intellij.openapi.util.Condition;
import com.intellij.openapi.wm.*;
import com.intellij.openapi.wm.ex.ToolWindowManagerEx;
import com.intellij.openapi.wm.ex.ToolWindowManagerListener;
import javax.swing.event.HyperlinkListener;
import java.awt.*;
import java.awt.event.InputEvent;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-import java.util.ArrayList;
@SuppressWarnings({"ConstantConditions"})
public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx {
changing.signature.of.0=Changing signature of {0}
there.is.already.a.0.in.1.it.will.conflict.with.the.new.parameter=There is already a {0} in {1}. It will conflict with the new parameter.
0.to.change.signature={0} to change signature
+New.name.of.method.is.not.java.identifier=New name of method is not Java identifier
references.to.be.changed=References to be changed {0}
source.folder.0.has.package.prefix.1=Source folder {0} has package prefix ''{1}''\nPackage ''{2}'' cannot be created there.
javadoc.as.is=&As is
<extensionPoint name="refactoring.safeDeleteProcessor" interface="com.intellij.refactoring.safeDelete.SafeDeleteProcessorDelegate"/>
<extensionPoint name="refactoring.extractIncludeHandler"
beanClass="com.intellij.lang.LanguageExtensionPoint"/>
+ <extensionPoint name="refactoring.changeSignatureUsageProcessor"
+ interface="com.intellij.refactoring.changeSignature.ChangeSignatureUsageProcessor"/>
<extensionPoint name="elementDescriptionProvider" interface="com.intellij.psi.ElementDescriptionProvider"/>
<extensions defaultExtensionNs="com.intellij">
<refactoring.introduceParameterMethodUsagesProcessor implementation="org.jetbrains.plugins.groovy.refactoring.introduceParameter.java2groovy.GroovyIntroduceParameterMethodUsagesProcessor"/>
+ <refactoring.changeSignatureUsageProcessor implementation="org.jetbrains.plugins.groovy.refactoring.changeSignature.GrChangeSignatureUsageProcessor" id="groovyProcessor" order="before javaProcessor"/>
<constantExpressionEvaluator language="Groovy" implementationClass="org.jetbrains.plugins.groovy.lang.psi.util.GroovyConstantExpressionEvaluator"/>
<annotationSupport language="Groovy" implementationClass="org.jetbrains.plugins.groovy.lang.psi.impl.auxiliary.annotation.GroovyAnnotationSupport"/>
property.name.expected=Property name expected
add.method.body=Add method body
wildcards.are.not.allowed.in.extends.list=A super type may not specify a wildcard type
-method.doesnot.override.super=Method does not override method from its superclass
-method.duplicate={0} is already defined
+method.doesnot.override.super=Method does not override method from its super class
+method.duplicate=Method with signature {0} is already defined in the class ''{1}''
ambiguous.code.block=Ambiguous code block
import com.intellij.psi.infos.CandidateInfo;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.searches.SuperMethodsSearch;
+import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.MethodSignature;
import com.intellij.psi.util.MethodSignatureBackedByPsiMethod;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.plugins.groovy.codeInspection.GroovyImportsTracker;
import org.jetbrains.plugins.groovy.config.GroovyConfigUtils;
import org.jetbrains.plugins.groovy.highlighter.DefaultHighlighter;
+import org.jetbrains.plugins.groovy.lang.documentation.GroovyPresentationUtil;
import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.*;
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
import org.jetbrains.plugins.groovy.lang.lexer.TokenSets;
import org.jetbrains.plugins.groovy.overrideImplement.GroovyOverrideImplementUtil;
import org.jetbrains.plugins.groovy.overrideImplement.quickFix.ImplementMethodsQuickFix;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
/**
* @author ven
if (argumentTypes == null ||
argumentTypes.length == 0 ||
(argumentTypes.length == 1 &&
- PsiUtil.createMapType(newExpression.getManager(), newExpression.getResolveScope()).isAssignableFrom(argumentTypes[0]))) {
+ InheritanceUtil.isInheritor(argumentTypes[0], CommonClassNames.JAVA_UTIL_MAP))) {
checkDefaultMapConstructor(myHolder, argList, element);
}
else {
}
private static void checkDuplicateMethod(GrMethod[] methods, AnnotationHolder holder) {
- Map<MethodSignature, List<GrMethod>> map = GrClosureSignatureUtil.findMethodSignatures(methods);
+ MultiMap<MethodSignature, PsiMethod> map = GrClosureSignatureUtil.findMethodSignatures(methods);
processMethodDuplicates(map, holder);
}
- protected static void processMethodDuplicates(Map<MethodSignature, List<GrMethod>> map, AnnotationHolder holder) {
+ protected static void processMethodDuplicates(MultiMap<MethodSignature, PsiMethod> map, AnnotationHolder holder) {
for (MethodSignature signature : map.keySet()) {
- List<GrMethod> methods = map.get(signature);
+ Collection<PsiMethod> methods = map.get(signature);
if (methods.size() > 1) {
- String signaturePresentation = getSignaturePresentation(signature);
- for (GrMethod method : methods) {
- holder.createErrorAnnotation(method.getNameIdentifierGroovy(), GroovyBundle.message("method.duplicate", signaturePresentation));
+ String signaturePresentation = GroovyPresentationUtil.getSignaturePresentation(signature);
+ for (PsiMethod method : methods) {
+ holder.createErrorAnnotation(method.getNameIdentifier(), GroovyBundle.message("method.duplicate", signaturePresentation, method.getContainingClass().getName()));
}
}
}
}
- private static String getSignaturePresentation(MethodSignature signature) {
- StringBuilder builder = new StringBuilder();
- builder.append(signature.getName()).append('(');
- PsiType[] types = signature.getParameterTypes();
- for (PsiType type : types) {
- builder.append(type.getPresentableText()).append(", ");
- }
- if (types.length > 0) builder.delete(builder.length() - 2, builder.length());
- builder.append(")");
- return builder.toString();
- }
-
private static void checkTypeDefinition(AnnotationHolder holder, GrTypeDefinition typeDefinition) {
final GroovyConfigUtils configUtils = GroovyConfigUtils.getInstance();
if (typeDefinition.isAnnotationType()) {
private static void highlightInapplicableMethodUsage(GroovyResolveResult methodResolveResult, PsiElement place, AnnotationHolder holder,
PsiMethod method, PsiType[] argumentTypes) {
- PsiElement elementToHighlight = PsiUtil.getArgumentsElement(place);
+ PsiElement elementToHighlight = PsiUtil.getArgumentsList(place);
if (elementToHighlight == null) {
elementToHighlight = place;
}
final String typesString = buildArgTypesList(argumentTypes);
String message = GroovyBundle.message("cannot.apply.method.or.closure", variable.getName(), typesString);
- PsiElement elementToHighlight = PsiUtil.getArgumentsElement(place);
+ PsiElement elementToHighlight = PsiUtil.getArgumentsList(place);
if (elementToHighlight == null) elementToHighlight = place;
holder.createWarningAnnotation(elementToHighlight, message);
}
final String[] argumentsTypes = QuickfixUtil.getArgumentsTypes(myPairs);
final GrMethod method = GroovyPsiElementFactory.getInstance(manager.getProject())
- .createMethodFromText(staticModifier, getName(), type, argumentsTypes);
+ .createMethodFromText(staticModifier, getName(), type, argumentsTypes, null);
myImplicitMethod = new GrDynamicImplicitMethod(manager, method, containingClassName) {
@Override
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.util.Computable;
+import com.intellij.openapi.util.NullableComputable;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.impl.light.LightMemberReference;
import com.intellij.psi.search.searches.DirectClassInheritorsSearch;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.util.Processor;
+import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrConstructorInvocation;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrNewExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
+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.GrCodeReferenceElement;
public static boolean execute(final PsiMethod constructor, final SearchScope searchScope, final Processor<PsiReference> consumer) {
if (!constructor.isConstructor()) return true;
-
- final PsiClass clazz = constructor.getContainingClass();
+ final PsiClass clazz = ApplicationManager.getApplication().runReadAction(new NullableComputable<PsiClass>(){
+ public PsiClass compute() {
+ return constructor.getContainingClass();
+ }
+ });
if (clazz == null) return true;
- ReferencesSearch.search(clazz, searchScope, true).forEach(new Processor<PsiReference>() {
- public boolean process(PsiReference ref) {
- final PsiElement element = ref.getElement();
- if (element instanceof GrCodeReferenceElement && element.getParent() instanceof GrNewExpression) {
- final GrNewExpression newExpression = (GrNewExpression)element.getParent();
- final PsiMethod resolvedConstructor = newExpression.resolveConstructor();
- final PsiManager manager = constructor.getManager();
- if (manager.areElementsEquivalent(resolvedConstructor, constructor) && !consumer.process(ref)) return false;
+ //enum constants
+ if (!ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
+ public Boolean compute() {
+ if (!clazz.isEnum()) return true;
+ if (!(clazz instanceof GroovyPsiElement)) return true;
+ final PsiField[] fields = clazz.getFields();
+ for (PsiField field : fields) {
+ if (field instanceof GrEnumConstant) {
+ final PsiReference ref = field.getReference();
+ if (ref.isReferenceTo(constructor)) {
+ if (!consumer.process(ref)) return false;
+ }
+ }
}
return true;
}
+ })) {
+ return false;
+ }
+
+
+ ReferencesSearch.search(clazz, searchScope, true).forEach(new Processor<PsiReference>() {
+ public boolean process(final PsiReference ref) {
+ return ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
+ public Boolean compute() {
+ final PsiElement element = ref.getElement();
+ if (element instanceof GrCodeReferenceElement && element.getParent() instanceof GrNewExpression) {
+ final GrNewExpression newExpression = (GrNewExpression)element.getParent();
+ final PsiMethod resolvedConstructor = newExpression.resolveConstructor();
+ final PsiManager manager = constructor.getManager();
+ if (manager.areElementsEquivalent(resolvedConstructor, constructor) && !consumer.process(ref)) return false;
+ }
+ return true;
+ }
+ });
+ }
});
//this()
}
//Eliminate obsolete parameter from parameter list
- list.removeParameter(param);
+ param.delete();
//Remove old arguments from occurrences
import com.intellij.psi.PsiSubstitutor;
import com.intellij.psi.PsiType;
import com.intellij.psi.search.searches.ReferencesSearch;
+import com.intellij.psi.util.MethodSignature;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Processor;
import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement;
return builder.toString();
}
}
+
+ public static String getSignaturePresentation(MethodSignature signature) {
+ StringBuilder builder = new StringBuilder();
+ builder.append(signature.getName()).append('(');
+ PsiType[] types = signature.getParameterTypes();
+ for (PsiType type : types) {
+ builder.append(type.getPresentableText()).append(", ");
+ }
+ if (types.length > 0) builder.delete(builder.length() - 2, builder.length());
+ builder.append(")");
+ return builder.toString();
+ }
}
package org.jetbrains.plugins.groovy.lang.groovydoc.psi.impl;
-import com.intellij.codeInsight.lookup.LookupItem;
import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.codeInsight.lookup.LookupItem;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
return getManager().areElementsEquivalent(element, resolve());
}
+ @Nullable
public PsiElement bindToElement(@NotNull PsiElement element) throws IncorrectOperationException {
if (isReferenceTo(element)) return this;
+
+ if (element instanceof PsiClass) {
+ GrDocReferenceElement holder = getReferenceHolder();
+ if (holder != null) {
+ return replace(holder.getReferenceElement().bindToElement(element).getParent());
+ }
+ GrDocReferenceElement ref =
+ GroovyPsiElementFactory.getInstance(getProject()).createDocReferenceElementFromFQN(((PsiClass)element).getQualifiedName());
+ return replace(ref);
+ }
+ else if (element instanceof PsiMember) {
+ PsiClass clazz = ((PsiMember)element).getContainingClass();
+ if (clazz == null) return null;
+ String qName = clazz.getQualifiedName();
+ String memberRefText;
+ if (element instanceof PsiField) {
+ memberRefText = ((PsiField)element).getName();
+ }
+ else if (element instanceof PsiMethod) {
+ PsiParameterList list = ((PsiMethod)element).getParameterList();
+ StringBuilder builder = new StringBuilder();
+ builder.append(((PsiMethod)element).getName()).append("(");
+ PsiParameter[] params = list.getParameters();
+ for (int i = 0; i < params.length; i++) {
+ PsiParameter parameter = params[i];
+ PsiType type = parameter.getType();
+ if (i > 0) builder.append(", ");
+ builder.append(type.getPresentableText());
+ }
+ builder.append(")");
+ memberRefText = builder.toString();
+ }
+ else {
+ return null;
+ }
+ GrDocMemberReference ref = GroovyPsiElementFactory.getInstance(getProject()).createDocMemberReferenceFromText(qName, memberRefText);
+ return replace(ref);
+ }
return null;
}
return child;
}
+ @Override
+ public PsiElement resolve() {
+ String name = getReferenceName();
+ GrDocReferenceElement holder = getReferenceHolder();
+ PsiElement resolved;
+ if (holder != null) {
+ GrCodeReferenceElement referenceElement = holder.getReferenceElement();
+ resolved = referenceElement != null ? referenceElement.resolve() : null;
+ } else {
+ resolved = getEnclosingClass(this);
+ }
+ if (resolved instanceof PsiClass) {
+ PsiType[] parameterTypes = getParameterList().getParameterTypes();
+ PsiType thisType = JavaPsiFacade.getInstance(getProject()).getElementFactory().createType((PsiClass)resolved, PsiSubstitutor.EMPTY);
+
+ MethodResolverProcessor processor = new MethodResolverProcessor(name, this, false, thisType, parameterTypes, PsiType.EMPTY_ARRAY);
+ resolved.processDeclarations(processor, ResolveState.initial(), resolved, this);
+ if (processor.hasApplicableCandidates()) {
+ return processor.getCandidates()[0].getElement();
+ }
+
+ MethodResolverProcessor constructorProcessor =
+ new MethodResolverProcessor(name, this, true, thisType, parameterTypes, PsiType.EMPTY_ARRAY);
+ resolved.processDeclarations(constructorProcessor, ResolveState.initial(), resolved, this);
+ if (constructorProcessor.hasApplicableCandidates()) {
+ return constructorProcessor.getCandidates()[0].getElement();
+ }
+ }
+ return null;
+ }
+
protected ResolveResult[] multiResolveImpl() {
String name = getReferenceName();
GrDocReferenceElement holder = getReferenceHolder();
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiClassType;
import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiReferenceList;
import com.intellij.psi.PsiType;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocComment;
+import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocMemberReference;
+import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocReferenceElement;
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrLabel;
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotation;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrBlockStatement;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableDeclaration;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.*;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
public abstract GrReferenceExpression createReferenceExpressionFromText(String exprText);
+ public abstract GrReferenceExpression createReferenceExpressionFromText(String idText, PsiElement context) ;
+
public abstract GrCodeReferenceElement createReferenceElementFromText(String refName);
public abstract GrExpression createExpressionFromText(String exprText);
public abstract PsiElement createDocMemberReferenceNameFromText(String idText);
+ public abstract GrDocMemberReference createDocMemberReferenceFromText(String className, String text);
+
+ public abstract GrDocReferenceElement createDocReferenceElementFromFQN(String qName);
+
public abstract GrTopStatement createTopElementFromText(String text);
public abstract GrClosableBlock createClosureFromText(String s) throws IncorrectOperationException;
- public abstract GrParameter createParameter(String name, @Nullable String typeText, GroovyPsiElement context) throws IncorrectOperationException;
+ public GrParameter createParameter(String name, @Nullable String typeText, GroovyPsiElement context) throws IncorrectOperationException {
+ return createParameter(name, typeText, null, context);
+ }
+
+ public abstract GrParameter createParameter(String name,
+ @Nullable String typeText,
+ String initializer,
+ GroovyPsiElement context) throws IncorrectOperationException;
public abstract GrCodeReferenceElement createTypeOrPackageReference(String qName);
public abstract PsiElement createDotToken(String newDot);
- public abstract GrMethod createMethodFromText(String methodText);
+ public abstract GrMethod createMethodFromText(String methodText, PsiElement context);
+
+ public GrMethod createMethodFromText(String methodText) {
+ return createMethodFromText(methodText, null);
+ }
public abstract GrAnnotation createAnnotationFromText(String annoText);
public abstract GroovyFile createGroovyFile(String text, boolean isPhisical, PsiElement context);
- public abstract GrMethod createMethodFromText(String modifier, String name, String type, String[] paramTypes);
+ public abstract GrMethod createMethodFromText(String modifier, String name, String type, String[] paramTypes, PsiElement context);
- public abstract GrMethod createConstructorFromText(@NotNull String constructorName, String[] paramTypes, String[] paramNames, String body);
+ public abstract GrMethod createConstructorFromText(@NotNull String constructorName,
+ String[] paramTypes,
+ String[] paramNames,
+ String body,
+ PsiElement context);
+
+ public GrMethod createConstructorFromText(@NotNull String constructorName, String[] paramTypes, String[] paramNames, String body) {
+ return createConstructorFromText(constructorName, paramTypes, paramNames, body, null);
+ }
public abstract GrLabel createLabel(@NotNull String name);
public abstract GrDocComment createDocCommentFromText(String text) ;
+
+ public abstract GrConstructorInvocation createConstructorInvocation(String text);
+
+ public abstract PsiReferenceList createThrownList(PsiClassType[] exceptionTypes);
+
+ public abstract GrCatchClause createCatchClause(PsiClassType type, String parameterName);
+
+ public abstract GrArgumentList createArgumentList();
}
package org.jetbrains.plugins.groovy.lang.psi.api.statements;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock;
import org.jetbrains.annotations.Nullable;
*/
public interface GrTryCatchStatement extends GroovyPsiElement, GrStatement {
- public GrOpenBlock getTryBlock();
+ GrOpenBlock getTryBlock();
- public GrCatchClause[] getCatchClauses();
+ GrCatchClause[] getCatchClauses();
@Nullable
- public GrFinallyClause getFinallyClause();
-
+ GrFinallyClause getFinallyClause();
+ GrCatchClause addCatchClause(@NotNull GrCatchClause clause, @Nullable GrCatchClause anchorBefore);
}
package org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments;
+import com.intellij.psi.PsiElement;
+import com.intellij.util.IncorrectOperationException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
-import org.jetbrains.annotations.Nullable;
-import org.jetbrains.annotations.NotNull;
-import com.intellij.util.IncorrectOperationException;
-import com.intellij.psi.PsiElement;
/**
* @author ilyas
GrExpression removeArgument(int argNumber);
GrNamedArgument addNamedArgument(GrNamedArgument namedArgument);
-
-}
+}
\ No newline at end of file
package org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions;
import com.intellij.psi.PsiMethod;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList;
@Nullable
GrArgumentList getArgumentList();
+ @Nullable
PsiMethod resolveConstructor();
+ @NotNull
GroovyResolveResult resolveConstructorGenerics();
GroovyResolveResult[] multiResolveConstructor();
package org.jetbrains.plugins.groovy.lang.psi.api.statements.params;
-import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiParameterList;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
/**
void addParameterToEnd(GrParameter parameter);
- @Nullable
- PsiElement removeParameter(GrParameter parameter);
-
void addParameterToHead(GrParameter parameter);
int getParameterNumber(GrParameter parameter);
@Nullable
PsiType getReturnType();
+ @Nullable
+ GrTypeElement setReturnType(@Nullable PsiType newReturnType);
+
@NotNull
@NonNls
String getName();
import com.intellij.lang.ASTNode;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.search.ProjectScope;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.plugins.groovy.annotator.intentions.QuickfixUtil;
import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocComment;
import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocMemberReference;
+import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocReferenceElement;
import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocTag;
import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes;
import org.jetbrains.plugins.groovy.lang.psi.*;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrEnumTypeDefinition;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinitionBody;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrConstructor;
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.toplevel.GrTopStatement;
}
public PsiElement createDocMemberReferenceNameFromText(String idText) {
- PsiFile file = createGroovyFile("/** @see A#" + idText + " */");
+ GrDocMemberReference reference = createDocMemberReferenceFromText("Foo", idText);
+ assert reference != null : "DocMemberReference ponts to null";
+ return reference.getReferenceNameElement();
+ }
+
+ public GrDocMemberReference createDocMemberReferenceFromText(String className, String text) {
+ PsiFile file = createGroovyFile("/** @see " + className + "#" + text + " */");
PsiElement element = file.getFirstChild();
assert element instanceof GrDocComment;
GrDocTag tag = PsiTreeUtil.getChildOfType(element, GrDocTag.class);
assert tag != null : "Doc tag points to null";
- GrDocMemberReference reference = PsiTreeUtil.getChildOfType(tag, GrDocMemberReference.class);
- assert reference != null : "DocMemberReference ponts to null";
- return reference.getReferenceNameElement();
+ return PsiTreeUtil.getChildOfType(tag, GrDocMemberReference.class);
+ }
+
+ public GrDocReferenceElement createDocReferenceElementFromFQN(String qName) {
+ PsiFile file = createGroovyFile("/** @see " + qName + " */");
+ PsiElement element = file.getFirstChild();
+ assert element instanceof GrDocComment;
+ GrDocTag tag = PsiTreeUtil.getChildOfType(element, GrDocTag.class);
+ assert tag != null : "Doc tag points to null";
+ return PsiTreeUtil.getChildOfType(tag, GrDocReferenceElement.class);
}
public GrCodeReferenceElement createReferenceElementFromText(String refName) {
return (GrReferenceExpression) ((GroovyFileBase) file).getTopStatements()[0];
}
+ public GrReferenceExpression createReferenceExpressionFromText(String idText, PsiElement context) {
+ PsiFile file = createGroovyFile(idText, false, context);
+ return (GrReferenceExpression) ((GroovyFileBase) file).getTopStatements()[0];
+ }
+
+
public GrExpression createExpressionFromText(String text) {
GroovyFileImpl file = (GroovyFileImpl) createGroovyFile(text);
assert file.getTopStatements()[0] instanceof GrExpression;
return createDummyFile(s, false);
}
- public GrParameter createParameter(String name, @Nullable String typeText, GroovyPsiElement context) throws IncorrectOperationException {
- String fileText;
+ public GrParameter createParameter(String name, @Nullable String typeText, @Nullable String initializer, GroovyPsiElement context)
+ throws IncorrectOperationException {
+ StringBuilder fileText = new StringBuilder();
+ fileText.append("def foo(");
if (typeText != null) {
- fileText = "def foo(" + typeText + " " + name + ") {}";
+ fileText.append(typeText).append(" ");
} else {
- fileText = "def foo(" + name + ") {}";
+ fileText.append("def ");
+ }
+ fileText.append(name);
+ if (initializer != null && initializer.length() > 0) {
+ fileText.append(" = ").append(initializer);
}
- GroovyFileImpl groovyFile = createDummyFile(fileText);
+ fileText.append("){}");
+ GroovyFileImpl groovyFile = createDummyFile(fileText.toString());
groovyFile.setContext(context);
ASTNode node = groovyFile.getFirstChild().getNode();
- if (node.getElementType() != GroovyElementTypes.METHOD_DEFINITION)
+ if (node.getElementType() != GroovyElementTypes.METHOD_DEFINITION) {
throw new IncorrectOperationException("Invalid all text");
- return ((GrMethod) node.getPsi()).getParameters()[0];
+ }
+ return ((GrMethod)node.getPsi()).getParameters()[0];
}
public GrCodeReferenceElement createTypeOrPackageReference(String qName) {
return createReferenceExpressionFromText("a" + newDot + "b").getDotToken();
}
- public GrConstructorImpl createConstructorFromText(@NotNull String constructorName, @Nullable String[] paramTypes, String[] paramNames, String body) {
- final GrMethod method = createMethodFromText(null, constructorName, null, paramTypes, paramNames, body);
+ public GrConstructorImpl createConstructorFromText(@NotNull String constructorName,
+ @Nullable String[] paramTypes,
+ String[] paramNames,
+ String body,
+ PsiElement context) {
+ final GrMethod method = createMethodFromText(null, constructorName, null, paramTypes, paramNames, body, context);
- GroovyFileBase file = createDummyFile("class " + constructorName + "{" + method.getText() + "}");
+ GroovyFileImpl file = createDummyFile("class " + constructorName + "{" + method.getText() + "}");
+ file.setContext(context);
GrTopLevelDefintion defintion = file.getTopLevelDefinitions()[0];
assert defintion != null && defintion instanceof GrClassDefinition;
final PsiMethod constructor = ((GrClassDefinition) defintion).getMethods()[0];
return ((GrLabeledStatement)definition).getLabel();
}
- public GrMethod createMethodFromText(@NotNull String methodText) {
- GroovyFileBase file = createDummyFile(methodText);
+ public GrMethod createMethodFromText(@NotNull String methodText, PsiElement context) {
+ GroovyFileImpl file = createDummyFile(methodText);
+ if (context != null) {
+ file.setContext(context);
+ }
try {
GrTopLevelDefintion defintion = file.getTopLevelDefinitions()[0];
assert defintion != null && defintion instanceof GrMethod;
@Override
public GrAnnotation createAnnotationFromText(String annoText) {
- return createMethodFromText(annoText + " void foo() {}").getModifierList().getAnnotations()[0];
+ return createMethodFromText(annoText + " void foo() {}", null).getModifierList().getAnnotations()[0];
}
public PsiFile createGroovyFile(String idText) {
}
- private GrMethod createMethodFromText(String modifier, String name, String type, @Nullable String[] paramTypes, @NotNull String[] paramNames, String body) {
+ private GrMethod createMethodFromText(String modifier,
+ String name,
+ String type,
+ @Nullable String[] paramTypes,
+ @NotNull String[] paramNames,
+ String body,
+ PsiElement context) {
StringBuilder builder = new StringBuilder();
if (modifier != null){
builder.append("}");
}
- return createMethodFromText(builder.toString());
+ return createMethodFromText(builder.toString(), context);
}
- public GrMethod createMethodFromText(String modifier, String name, @Nullable String type, String[] paramTypes) {
+ public GrMethod createMethodFromText(String modifier, String name, @Nullable String type, String[] paramTypes, PsiElement context) {
PsiType psiType;
List<PsiType> res = new ArrayList<PsiType>();
final GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(myProject);
- for (int i = 0; i < paramTypes.length; i++) {
- String paramType = paramTypes[i];
-
+ for (String paramType : paramTypes) {
try {
psiType = factory.createTypeElement(paramType).getType();
- } catch (IncorrectOperationException e) {
+ }
+ catch (IncorrectOperationException e) {
psiType = PsiType.getJavaLangObject(PsiManager.getInstance(myProject), ProjectScope.getAllScope(myProject));
}
res.add(psiType);
}
- return createMethodFromText(modifier, name, type, paramTypes, QuickfixUtil.getMethodArgumentsNames(myProject, res.toArray(PsiType.EMPTY_ARRAY)), null);
+ return createMethodFromText(modifier, name, type, paramTypes,
+ QuickfixUtil.getMethodArgumentsNames(myProject, res.toArray(new PsiType[res.size()])), null, context);
}
public GrDocComment createDocCommentFromText(String text) {
builder.append(" def foo(){}");
return (GrDocComment)createGroovyFile(text+"def foo(){}").getFirstChild();
}
+
+ @Override
+ public GrConstructorInvocation createConstructorInvocation(String text) {
+ GroovyFile file = (GroovyFile)createGroovyFile("class Foo{ def Foo(){" + text + "}}");
+ return ((GrConstructor)file.getClasses()[0].getConstructors()[0]).getChainingConstructorInvocation();
+ }
+
+ @Override
+ public PsiReferenceList createThrownList(PsiClassType[] exceptionTypes) {
+ if (exceptionTypes.length == 0) {
+ return createMethodFromText("def foo(){}", null).getThrowsList();
+ }
+ String[] types = new String[exceptionTypes.length];
+ for (int i = 0; i < types.length; i++) {
+ types[i] = exceptionTypes[i].getCanonicalText();
+ }
+ final String end = StringUtil.join(types, ",");
+ return createMethodFromText("def foo() throws " + end + "{}", null).getThrowsList();
+ }
+
+ @Override
+ public GrCatchClause createCatchClause(PsiClassType type, String parameterName) {
+ StringBuffer buffer = new StringBuffer("try{} catch(");
+ if (type == null) {
+ buffer.append("Throwable ");
+ }
+ else {
+ buffer.append(type.getCanonicalText()).append(" ");
+ }
+ buffer.append(parameterName).append("){\n}");
+ final GrTryCatchStatement statement = (GrTryCatchStatement)createStatementFromText(buffer.toString());
+ return statement.getCatchClauses()[0];
+ }
+
+ @Override
+ public GrArgumentList createArgumentList() {
+ return ((GrCall)createExpressionFromText("foo()")).getArgumentList();
+ }
}
return element instanceof PsiMethod ? (PsiMethod) element : null;
}
+ @NotNull
public static GroovyResolveResult extractUniqueResult(@NotNull GroovyResolveResult[] results) {
if (results.length != 1) return GroovyResolveResult.EMPTY_RESULT;
return results[0];
if (name.equals(GrModifier.FINAL)) return findChildByType(GroovyElementTypes.kFINAL) != null;
if (name.equals(GrModifier.TRANSIENT)) return findChildByType(GroovyElementTypes.kTRANSIENT) != null;
if (name.equals(GrModifier.NATIVE)) return findChildByType(GroovyElementTypes.kNATIVE) != null;
+ if (name.equals(GrModifier.DEF)) return findChildByType(GroovyTokenTypes.kDEF) != null;
return name.equals(GrModifier.VOLATILE) && findChildByType(GroovyElementTypes.kVOLATILE) != null;
}
return PsiImplUtil.extractUniqueElement(multiResolveConstructor());
}
+ @NotNull
public GroovyResolveResult resolveConstructorGenerics() {
return PsiImplUtil.extractUniqueResult(multiResolveConstructor());
}
package org.jetbrains.plugins.groovy.lang.psi.impl.statements;
import com.intellij.lang.ASTNode;
+import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrCatchClause;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrFinallyClause;
public GrFinallyClause getFinallyClause() {
return findChildByClass(GrFinallyClause.class);
}
+
+ public GrCatchClause addCatchClause(@NotNull GrCatchClause clause, @Nullable GrCatchClause anchorBefore) {
+ PsiElement anchor = anchorBefore;
+ if (anchor == null) {
+ anchor = getTryBlock();
+ }
+ return (GrCatchClause)addAfter(clause, anchor);
+ }
}
\ No newline at end of file
PsiElement next = PsiUtil.getNextNonSpace(this);
ASTNode parentNode = parent.getNode();
assert parentNode != null;
- parentNode.removeChild(getNode());
+ super.delete();
if (prev != null && prev.getNode() != null && prev.getNode().getElementType() == GroovyTokenTypes.mCOMMA) {
- parentNode.removeChild(prev.getNode());
+ prev.delete();
} else if (next instanceof LeafPsiElement && next.getNode() != null && next.getNode().getElementType() == GroovyTokenTypes.mCOMMA) {
next.delete();
}
import com.intellij.psi.*;
import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry;
import com.intellij.psi.impl.source.resolve.reference.impl.PsiMultiReference;
+import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PropertyUtil;
import com.intellij.util.ArrayUtil;
if (resolvedMethod != null) {
final PsiParameter[] parameters = resolvedMethod.getParameterList().getParameters();
if (parameters.length > 0) {
- if (PsiUtil.createMapType(resolvedMethod.getManager(), resolvedMethod.getResolveScope()).isAssignableFrom(parameters[0].getType())) {
+ if (InheritanceUtil.isInheritor(parameters[0].getType(), CommonClassNames.JAVA_UTIL_MAP)) {
//call with named argument, not setting property
return null;
}
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiWhiteSpace;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.impl.source.tree.TreeUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
-import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mCOMMA;
import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument;
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiElementImpl;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
+import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mCOMMA;
+
/**
* @author ilyas
*/
@Nullable
public GrExpression removeArgument(final int argNumber) {
- for (int i = 0; i < getExpressionArguments().length; i++) {
- GrExpression expression = getExpressionArguments()[i];
- if (i == argNumber) {
- final ASTNode exprNode = expression.getNode();
- final PsiElement prevElem = PsiUtil.getPrevNonSpace(expression);
- final PsiElement nextElem = PsiUtil.getNextNonSpace(expression);
- getNode().removeChild(exprNode);
- if (nextElem != null && nextElem.getNode() != null && (nextElem.getNode().getElementType() == mCOMMA)) {
- final PsiElement n = nextElem.getNextSibling();
- getNode().removeChild(nextElem.getNode());
- if (n != null && n instanceof PsiWhiteSpace) {
- getNode().removeChild(n.getNode());
- }
- } else if (prevElem != null) {
- final ASTNode prev = prevElem.getNode();
- if (prev != null && prev.getElementType() == mCOMMA) {
- final PsiElement p = prevElem.getPrevSibling();
- getNode().removeChild(prev);
- getNode().removeChild(prevElem.getNode());
- if (p != null && p instanceof PsiWhiteSpace) {
- getNode().removeChild(p.getNode());
- }
- }
- }
- return expression;
- }
- }
- return null;
+ GrExpression[] arguments = getExpressionArguments();
+ if (argNumber < 0 || arguments.length <= argNumber) return null;
+
+ GrExpression expression = arguments[argNumber];
+ expression.delete();
+ return expression;
}
public GrNamedArgument addNamedArgument(final GrNamedArgument namedArgument) {
final int exprCount = args.length;
if (namedCount > 0) {
anchor = namedArguments[namedCount - 1];
- } else if (exprCount > 0) {
+ }
+ else if (exprCount > 0) {
anchor = args[exprCount - 1];
}
if (anchor != null) {
anchor = PsiUtil.getNextNonSpace(anchor);
- } else {
+ }
+ else {
anchor = getRightParen();
}
if (anchor != null) {
final ASTNode astNode = anchor.getNode();
getNode().addChild(newNode, astNode);
- } else {
+ }
+ else {
getNode().addChild(newNode);
}