mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
java safe delete: propagate callees search across fields and field initializers
This commit is contained in:
+46
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2000-2017 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.inCallers;
|
||||
|
||||
import com.intellij.openapi.fileTypes.StdFileTypes;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiMember;
|
||||
import com.intellij.refactoring.changeSignature.CallerChooserBase;
|
||||
import com.intellij.ui.treeStructure.Tree;
|
||||
import com.intellij.util.Consumer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public abstract class AbstractJavaMemberCallerChooser<M extends PsiMember> extends CallerChooserBase<M> {
|
||||
|
||||
public AbstractJavaMemberCallerChooser(M member, Project project, String title, Tree previousTree, Consumer<Set<M>> callback) {
|
||||
super(member, project, title, previousTree, "dummy." + StdFileTypes.JAVA.getDefaultExtension(), callback);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected abstract String getMemberTypePresentableText();
|
||||
|
||||
@Override
|
||||
protected String getEmptyCallerText() {
|
||||
return "Caller " + getMemberTypePresentableText() + " text \nwith highlighted callee call would be shown here";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getEmptyCalleeText() {
|
||||
return "Callee " + getMemberTypePresentableText() + " text would be shown here";
|
||||
}
|
||||
}
|
||||
+16
-17
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2010 JetBrains s.r.o.
|
||||
* Copyright 2000-2017 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.
|
||||
@@ -15,24 +15,33 @@
|
||||
*/
|
||||
package com.intellij.refactoring.changeSignature.inCallers;
|
||||
|
||||
import com.intellij.openapi.fileTypes.StdFileTypes;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.refactoring.changeSignature.CallerChooserBase;
|
||||
import com.intellij.refactoring.changeSignature.MemberNodeBase;
|
||||
import com.intellij.ui.treeStructure.Tree;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.containers.HashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public class JavaCallerChooser extends CallerChooserBase<PsiMethod> {
|
||||
public class JavaCallerChooser extends AbstractJavaMemberCallerChooser<PsiMethod> {
|
||||
public JavaCallerChooser(PsiMethod method,
|
||||
Project project,
|
||||
String title,
|
||||
Tree previousTree,
|
||||
Consumer<Set<PsiMethod>> callback) {
|
||||
super(method, project, title, previousTree, callback);
|
||||
}
|
||||
|
||||
public JavaCallerChooser(PsiMethod method, Project project, String title, Tree previousTree, Consumer<Set<PsiMethod>> callback) {
|
||||
super(method, project, title, previousTree, "dummy." + StdFileTypes.JAVA.getDefaultExtension(), callback);
|
||||
@NotNull
|
||||
@Override
|
||||
protected String getMemberTypePresentableText() {
|
||||
return "method";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JavaMethodNode createTreeNode(PsiMethod method, HashSet<PsiMethod> called, Runnable cancelCallback) {
|
||||
protected MemberNodeBase<PsiMethod> createTreeNode(PsiMethod method, HashSet<PsiMethod> called, Runnable cancelCallback) {
|
||||
return new JavaMethodNode(method, called, myProject, cancelCallback);
|
||||
}
|
||||
|
||||
@@ -40,14 +49,4 @@ public class JavaCallerChooser extends CallerChooserBase<PsiMethod> {
|
||||
protected PsiMethod[] findDeepestSuperMethods(PsiMethod method) {
|
||||
return method.findDeepestSuperMethods();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getEmptyCallerText() {
|
||||
return "Caller method text \nwith highlighted callee call would be shown here";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getEmptyCalleeText() {
|
||||
return "Callee method text would be shown here";
|
||||
}
|
||||
}
|
||||
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 2000-2017 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.inCallers;
|
||||
|
||||
import com.intellij.ide.hierarchy.JavaHierarchyUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.presentation.java.ClassPresentationUtil;
|
||||
import com.intellij.psi.util.PsiFormatUtil;
|
||||
import com.intellij.psi.util.PsiFormatUtilBase;
|
||||
import com.intellij.refactoring.changeSignature.MemberNodeBase;
|
||||
import com.intellij.ui.ColoredTreeCellRenderer;
|
||||
import com.intellij.ui.JBColor;
|
||||
import com.intellij.ui.SimpleTextAttributes;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public abstract class JavaMemberNode<M extends PsiMember> extends MemberNodeBase<M> {
|
||||
protected JavaMemberNode(final M member, Set<M> called, Project project, Runnable cancelCallback) {
|
||||
super(member, called, project, cancelCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void customizeRendererText(ColoredTreeCellRenderer renderer) {
|
||||
final StringBuilder buffer = new StringBuilder(128);
|
||||
final PsiClass containingClass = getMember().getContainingClass();
|
||||
if (containingClass != null) {
|
||||
buffer.append(ClassPresentationUtil.getNameForClass(containingClass, false));
|
||||
buffer.append('.');
|
||||
}
|
||||
buffer.append(formatMember(getMember()));
|
||||
|
||||
final SimpleTextAttributes attributes = isEnabled() ?
|
||||
new SimpleTextAttributes(SimpleTextAttributes.STYLE_PLAIN, UIUtil.getTreeForeground()) :
|
||||
SimpleTextAttributes.EXCLUDED_ATTRIBUTES;
|
||||
renderer.append(buffer.toString(), attributes);
|
||||
|
||||
if (containingClass != null) {
|
||||
|
||||
final String packageName = JavaHierarchyUtil.getPackageName(containingClass);
|
||||
renderer.append(" (" + packageName + ")", new SimpleTextAttributes(SimpleTextAttributes.STYLE_ITALIC, JBColor.GRAY));
|
||||
}
|
||||
}
|
||||
|
||||
private static String formatMember(@NotNull PsiMember member) {
|
||||
if (member instanceof PsiMethod) {
|
||||
return PsiFormatUtil.formatMethod(
|
||||
(PsiMethod)member,
|
||||
PsiSubstitutor.EMPTY, PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_PARAMETERS,
|
||||
PsiFormatUtilBase.SHOW_TYPE
|
||||
);
|
||||
} else {
|
||||
assert member instanceof PsiField;
|
||||
return PsiFormatUtil.formatVariable(
|
||||
(PsiField)member,
|
||||
PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_TYPE,
|
||||
PsiSubstitutor.EMPTY
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
+10
-44
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
* Copyright 2000-2017 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.
|
||||
@@ -15,40 +15,33 @@
|
||||
*/
|
||||
package com.intellij.refactoring.changeSignature.inCallers;
|
||||
|
||||
import com.intellij.ide.hierarchy.JavaHierarchyUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.presentation.java.ClassPresentationUtil;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.searches.MethodReferencesSearch;
|
||||
import com.intellij.psi.util.PsiFormatUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.refactoring.changeSignature.MethodNodeBase;
|
||||
import com.intellij.ui.ColoredTreeCellRenderer;
|
||||
import com.intellij.ui.JBColor;
|
||||
import com.intellij.ui.SimpleTextAttributes;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.intellij.refactoring.changeSignature.MemberNodeBase;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class JavaMethodNode extends MethodNodeBase<PsiMethod> {
|
||||
|
||||
protected JavaMethodNode(final PsiMethod method, Set<PsiMethod> called, Project project, Runnable cancelCallback) {
|
||||
public class JavaMethodNode extends JavaMemberNode<PsiMethod> {
|
||||
protected JavaMethodNode(PsiMethod method,
|
||||
Set<PsiMethod> called,
|
||||
Project project,
|
||||
Runnable cancelCallback) {
|
||||
super(method, called, project, cancelCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MethodNodeBase<PsiMethod> createNode(PsiMethod caller, HashSet<PsiMethod> called) {
|
||||
protected MemberNodeBase<PsiMethod> createNode(PsiMethod caller, HashSet<PsiMethod> called) {
|
||||
return new JavaMethodNode(caller, called, myProject, myCancelCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<PsiMethod> computeCallers() {
|
||||
final PsiReference[] refs =
|
||||
MethodReferencesSearch.search(myMethod, GlobalSearchScope.allScope(myProject), true).toArray(PsiReference.EMPTY_ARRAY);
|
||||
final PsiReference[] refs = MethodReferencesSearch.search(myMethod).toArray(PsiReference.EMPTY_ARRAY);
|
||||
|
||||
List<PsiMethod> result = new ArrayList<>();
|
||||
for (PsiReference ref : refs) {
|
||||
@@ -57,7 +50,7 @@ public class JavaMethodNode extends MethodNodeBase<PsiMethod> {
|
||||
!(((PsiReferenceExpression)element).getQualifierExpression() instanceof PsiSuperExpression)) {
|
||||
final PsiElement enclosingContext = PsiTreeUtil.getParentOfType(element, PsiMethod.class, PsiClass.class);
|
||||
if (enclosingContext instanceof PsiMethod && !result.contains(enclosingContext) &&
|
||||
!myMethod.equals(enclosingContext) && !myCalled.contains(myMethod)) { //do not add recursive methods
|
||||
!getMember().equals(enclosingContext) && !myCalled.contains(getMember())) { //do not add recursive methods
|
||||
result.add((PsiMethod)enclosingContext);
|
||||
}
|
||||
else if (element instanceof PsiClass) {
|
||||
@@ -71,31 +64,4 @@ public class JavaMethodNode extends MethodNodeBase<PsiMethod> {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void customizeRendererText(ColoredTreeCellRenderer renderer) {
|
||||
final StringBuilder buffer = new StringBuilder(128);
|
||||
final PsiClass containingClass = myMethod.getContainingClass();
|
||||
if (containingClass != null) {
|
||||
buffer.append(ClassPresentationUtil.getNameForClass(containingClass, false));
|
||||
buffer.append('.');
|
||||
}
|
||||
final String methodText = PsiFormatUtil.formatMethod(
|
||||
myMethod,
|
||||
PsiSubstitutor.EMPTY, PsiFormatUtil.SHOW_NAME | PsiFormatUtil.SHOW_PARAMETERS,
|
||||
PsiFormatUtil.SHOW_TYPE
|
||||
);
|
||||
buffer.append(methodText);
|
||||
|
||||
final SimpleTextAttributes attributes = isEnabled() ?
|
||||
new SimpleTextAttributes(SimpleTextAttributes.STYLE_PLAIN, UIUtil.getTreeForeground()) :
|
||||
SimpleTextAttributes.EXCLUDED_ATTRIBUTES;
|
||||
renderer.append(buffer.toString(), attributes);
|
||||
|
||||
if (containingClass != null) {
|
||||
|
||||
final String packageName = JavaHierarchyUtil.getPackageName(containingClass);
|
||||
renderer.append(" (" + packageName + ")", new SimpleTextAttributes(SimpleTextAttributes.STYLE_ITALIC, JBColor.GRAY));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+5
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
* Copyright 2000-2017 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.
|
||||
@@ -24,8 +24,7 @@ import com.intellij.psi.PsiModifier;
|
||||
import com.intellij.psi.search.searches.OverridingMethodsSearch;
|
||||
import com.intellij.psi.util.ClassUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.refactoring.changeSignature.MethodNodeBase;
|
||||
import com.intellij.refactoring.changeSignature.MemberNodeBase;
|
||||
import com.intellij.refactoring.changeSignature.inCallers.JavaCallerChooser;
|
||||
import com.intellij.refactoring.changeSignature.inCallers.JavaMethodNode;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
@@ -78,7 +77,7 @@ abstract class MakeStaticJavaCallerChooser extends JavaCallerChooser {
|
||||
Runnable cancelCallback) {
|
||||
final MakeStaticJavaMethodNode node =
|
||||
new MakeStaticJavaMethodNode(nodeMethod, called, cancelCallback, nodeMethod != null ? nodeMethod.getProject() : myProject);
|
||||
if (getTopMethod().equals(nodeMethod)) {
|
||||
if (getTopMember().equals(nodeMethod)) {
|
||||
node.setEnabled(false);
|
||||
node.setChecked(true);
|
||||
}
|
||||
@@ -95,7 +94,7 @@ abstract class MakeStaticJavaCallerChooser extends JavaCallerChooser {
|
||||
|
||||
@Override
|
||||
protected List<PsiMethod> computeCallers() {
|
||||
if (getTopMethod().equals(getMethod())) {
|
||||
if (getTopMember().equals(getMember())) {
|
||||
final ArrayList<UsageInfo> items = getTopLevelItems();
|
||||
return ContainerUtil.map(items, info -> (PsiMethod)info.getElement());
|
||||
}
|
||||
@@ -104,7 +103,7 @@ abstract class MakeStaticJavaCallerChooser extends JavaCallerChooser {
|
||||
|
||||
|
||||
@Override
|
||||
protected MethodNodeBase<PsiMethod> createNode(PsiMethod caller, HashSet<PsiMethod> called) {
|
||||
protected MemberNodeBase<PsiMethod> createNode(PsiMethod caller, HashSet<PsiMethod> called) {
|
||||
return new MakeStaticJavaMethodNode(caller, called, myCancelCallback, myProject);
|
||||
}
|
||||
|
||||
|
||||
+27
-19
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
* Copyright 2000-2017 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.
|
||||
@@ -41,7 +41,7 @@ import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.refactoring.JavaRefactoringSettings;
|
||||
import com.intellij.refactoring.RefactoringBundle;
|
||||
import com.intellij.refactoring.changeSignature.inCallers.JavaCallerChooser;
|
||||
import com.intellij.refactoring.changeSignature.inCallers.AbstractJavaMemberCallerChooser;
|
||||
import com.intellij.refactoring.safeDelete.usageInfo.*;
|
||||
import com.intellij.refactoring.util.ConflictsUtil;
|
||||
import com.intellij.refactoring.util.RefactoringChangeUtil;
|
||||
@@ -319,7 +319,7 @@ public class JavaSafeDeleteProcessor extends SafeDeleteProcessorDelegateBase {
|
||||
final ArrayList<UsageInfo> result = new ArrayList<>();
|
||||
final ArrayList<UsageInfo> overridingMethods = new ArrayList<>();
|
||||
final ArrayList<SafeDeleteParameterCallHierarchyUsageInfo> delegatingParams = new ArrayList<>();
|
||||
final ArrayList<SafeDeleteMethodCalleeUsageInfo> calleesSafeToDelete = new ArrayList<>();
|
||||
final ArrayList<SafeDeleteMemberCalleeUsageInfo> calleesSafeToDelete = new ArrayList<>();
|
||||
for (UsageInfo usage : usages) {
|
||||
if (usage.isNonCodeUsage) {
|
||||
if (usage instanceof SafeDeleteUsageInfo) {
|
||||
@@ -335,8 +335,8 @@ public class JavaSafeDeleteProcessor extends SafeDeleteProcessorDelegateBase {
|
||||
}
|
||||
result.add(usage);
|
||||
}
|
||||
else if (usage instanceof SafeDeleteMethodCalleeUsageInfo) {
|
||||
calleesSafeToDelete.add((SafeDeleteMethodCalleeUsageInfo)usage);
|
||||
else if (usage instanceof SafeDeleteMemberCalleeUsageInfo) {
|
||||
calleesSafeToDelete.add((SafeDeleteMemberCalleeUsageInfo)usage);
|
||||
}
|
||||
else if (usage instanceof SafeDeleteOverridingMethodUsageInfo) {
|
||||
overridingMethods.add(usage);
|
||||
@@ -389,7 +389,7 @@ public class JavaSafeDeleteProcessor extends SafeDeleteProcessorDelegateBase {
|
||||
final PsiMethod method = parameterHierarchyUsageInfo.getCalledMethod();
|
||||
final PsiParameter parameter = parameterHierarchyUsageInfo.getReferencedElement();
|
||||
final int parameterIndex = method.getParameterList().getParameterIndex(parameter);
|
||||
final JavaCallerChooser chooser = new SafeDeleteJavaCallerChooser(method, project, result) {
|
||||
final AbstractJavaMemberCallerChooser chooser = new SafeDeleteJavaCallerChooser(method, project, result) {
|
||||
@Override
|
||||
protected ArrayList<SafeDeleteParameterCallHierarchyUsageInfo> getTopLevelItems() {
|
||||
return delegatingParams;
|
||||
@@ -421,11 +421,11 @@ public class JavaSafeDeleteProcessor extends SafeDeleteProcessorDelegateBase {
|
||||
result.addAll(calleesSafeToDelete);
|
||||
}
|
||||
else {
|
||||
final PsiMethod method = calleesSafeToDelete.get(0).getCallerMethod();
|
||||
final PsiMember member = calleesSafeToDelete.get(0).getCallerMember();
|
||||
final ArrayList<UsageInfo> list = new ArrayList<>();
|
||||
JavaCallerChooser chooser = new SafeDeleteJavaCalleeChooser(method, project, list) {
|
||||
AbstractJavaMemberCallerChooser chooser = new SafeDeleteJavaCalleeChooser(member, project, list) {
|
||||
@Override
|
||||
protected ArrayList<SafeDeleteMethodCalleeUsageInfo> getTopLevelItems() {
|
||||
protected ArrayList<SafeDeleteMemberCalleeUsageInfo> getTopLevelItems() {
|
||||
return calleesSafeToDelete;
|
||||
}
|
||||
};
|
||||
@@ -438,12 +438,14 @@ public class JavaSafeDeleteProcessor extends SafeDeleteProcessorDelegateBase {
|
||||
for (UsageInfo info : list) {
|
||||
methodsToDelete.add(info.getElement());
|
||||
}
|
||||
methodsToDelete.add(method);
|
||||
methodsToDelete.add(member);
|
||||
final Condition<PsiElement> insideDeletedCondition = getUsageInsideDeletedFilter(methodsToDelete.toArray(new PsiElement[methodsToDelete.size()]));
|
||||
for (UsageInfo info : list) {
|
||||
SafeDeleteProcessor.addNonCodeUsages(info.getElement(), result, insideDeletedCondition,
|
||||
JavaRefactoringSettings.getInstance().RENAME_SEARCH_FOR_TEXT_FOR_METHOD,
|
||||
JavaRefactoringSettings.getInstance().RENAME_SEARCH_IN_COMMENTS_FOR_METHOD );
|
||||
PsiElement psi = info.getElement();
|
||||
JavaRefactoringSettings refactoringSettings = JavaRefactoringSettings.getInstance();
|
||||
SafeDeleteProcessor.addNonCodeUsages(psi, result, insideDeletedCondition,
|
||||
psi instanceof PsiMethod ? refactoringSettings.RENAME_SEARCH_FOR_TEXT_FOR_METHOD : refactoringSettings.RENAME_SEARCH_FOR_TEXT_FOR_FIELD,
|
||||
psi instanceof PsiMethod ? refactoringSettings.RENAME_SEARCH_IN_COMMENTS_FOR_METHOD : refactoringSettings.RENAME_SEARCH_IN_COMMENTS_FOR_FIELD );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -684,12 +686,7 @@ public class JavaSafeDeleteProcessor extends SafeDeleteProcessorDelegateBase {
|
||||
}
|
||||
}
|
||||
|
||||
final List<PsiMethod> calleesSafeToDelete = SafeDeleteJavaCalleeChooser.computeCalleesSafeToDelete(psiMethod);
|
||||
if (calleesSafeToDelete != null) {
|
||||
for (PsiMethod method : calleesSafeToDelete) {
|
||||
usages.add(new SafeDeleteMethodCalleeUsageInfo(method, psiMethod));
|
||||
}
|
||||
}
|
||||
appendCallees(psiMethod, usages);
|
||||
|
||||
return usage -> {
|
||||
if(usage instanceof PsiFile) return false;
|
||||
@@ -697,6 +694,15 @@ public class JavaSafeDeleteProcessor extends SafeDeleteProcessorDelegateBase {
|
||||
};
|
||||
}
|
||||
|
||||
private static void appendCallees(@NotNull PsiMember method, @NotNull List<UsageInfo> usages) {
|
||||
final List<PsiMember> calleesSafeToDelete = SafeDeleteJavaCalleeChooser.computeCalleesSafeToDelete(method);
|
||||
if (calleesSafeToDelete != null) {
|
||||
for (PsiMember callee : calleesSafeToDelete) {
|
||||
usages.add(new SafeDeleteMemberCalleeUsageInfo(callee, method));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void findFunctionalExpressions(final List<UsageInfo> usages, PsiMethod... methods) {
|
||||
for (PsiMethod method : methods) {
|
||||
final PsiClass containingClass = method.getContainingClass();
|
||||
@@ -943,6 +949,8 @@ public class JavaSafeDeleteProcessor extends SafeDeleteProcessorDelegateBase {
|
||||
usages.add(createParameterCallHierarchyUsageInfo(setterPrototype, setterParameter, (PsiMethod)scope, parameter));
|
||||
}
|
||||
}
|
||||
|
||||
appendCallees(psiField, usages);
|
||||
|
||||
return isInsideDeleted;
|
||||
}
|
||||
|
||||
+79
-49
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* Copyright 2000-2017 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.
|
||||
@@ -20,67 +20,86 @@ import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.searches.ReferencesSearch;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.refactoring.changeSignature.MethodNodeBase;
|
||||
import com.intellij.refactoring.changeSignature.inCallers.JavaCallerChooser;
|
||||
import com.intellij.refactoring.changeSignature.inCallers.JavaMethodNode;
|
||||
import com.intellij.refactoring.safeDelete.usageInfo.SafeDeleteMethodCalleeUsageInfo;
|
||||
import com.intellij.refactoring.changeSignature.MemberNodeBase;
|
||||
import com.intellij.refactoring.changeSignature.inCallers.AbstractJavaMemberCallerChooser;
|
||||
import com.intellij.refactoring.changeSignature.inCallers.JavaMemberNode;
|
||||
import com.intellij.refactoring.safeDelete.usageInfo.SafeDeleteMemberCalleeUsageInfo;
|
||||
import com.intellij.refactoring.safeDelete.usageInfo.SafeDeleteReferenceJavaDeleteUsageInfo;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
import com.intellij.util.CommonProcessors;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
abstract class SafeDeleteJavaCalleeChooser extends JavaCallerChooser {
|
||||
abstract class SafeDeleteJavaCalleeChooser extends AbstractJavaMemberCallerChooser<PsiMember> {
|
||||
private final Project myProject;
|
||||
|
||||
public SafeDeleteJavaCalleeChooser(final PsiMethod method, Project project, final ArrayList<UsageInfo> result) {
|
||||
super(method, project, "Select Methods To Cascade Safe Delete", null, methods -> result.addAll(ContainerUtil.map(methods, m -> {
|
||||
public SafeDeleteJavaCalleeChooser(PsiMember member,
|
||||
Project project,
|
||||
ArrayList<UsageInfo> result) {
|
||||
super(member, project, "Select Members To Cascade Safe Delete", null, members -> result.addAll(ContainerUtil.map(members, m -> {
|
||||
return new SafeDeleteReferenceJavaDeleteUsageInfo(m, m, true);
|
||||
})));
|
||||
myProject = project;
|
||||
}
|
||||
|
||||
protected abstract ArrayList<SafeDeleteMemberCalleeUsageInfo> getTopLevelItems();
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected String getMemberTypePresentableText() {
|
||||
return "member";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PsiMember[] findDeepestSuperMethods(PsiMember method) {
|
||||
return method instanceof PsiMethod ? ((PsiMethod)method).findDeepestSuperMethods() : PsiMember.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
static List<PsiMethod> computeCalleesSafeToDelete(final PsiMethod psiMethod) {
|
||||
final PsiCodeBlock body = psiMethod.getBody();
|
||||
static List<PsiMember> computeCalleesSafeToDelete(final PsiMember psiMember) {
|
||||
final PsiElement body;
|
||||
if (psiMember instanceof PsiMethod) {
|
||||
body = ((PsiMethod)psiMember).getBody();
|
||||
} else {
|
||||
assert psiMember instanceof PsiField;
|
||||
body = ((PsiField)psiMember).getInitializer();
|
||||
}
|
||||
if (body != null) {
|
||||
final PsiClass containingClass = psiMethod.getContainingClass();
|
||||
final PsiClass containingClass = psiMember.getContainingClass();
|
||||
if (containingClass != null) {
|
||||
final Set<PsiMethod> methodsToCheck = new HashSet<>();
|
||||
final Set<PsiMember> membersToCheck = new HashSet<>();
|
||||
body.accept(new JavaRecursiveElementWalkingVisitor() {
|
||||
@Override
|
||||
public void visitMethodCallExpression(PsiMethodCallExpression expression) {
|
||||
super.visitMethodCallExpression(expression);
|
||||
ContainerUtil.addAllNotNull(methodsToCheck, expression.resolveMethod());
|
||||
public void visitReferenceExpression(PsiReferenceExpression expression) {
|
||||
super.visitReferenceExpression(expression);
|
||||
PsiElement resolved = expression.resolve();
|
||||
if (resolved instanceof PsiMethod || resolved instanceof PsiField) {
|
||||
ContainerUtil.addAllNotNull(membersToCheck, (PsiMember) resolved);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return ContainerUtil.filter(methodsToCheck, m -> containingClass.equals(m.getContainingClass()) &&
|
||||
!psiMethod.equals(m) &&
|
||||
m.findDeepestSuperMethods().length == 0 &&
|
||||
ReferencesSearch.search(m).forEach(new CommonProcessors.CollectProcessor<PsiReference>() {
|
||||
@Override
|
||||
public boolean process(PsiReference reference) {
|
||||
final PsiElement element = reference.getElement();
|
||||
return PsiTreeUtil.isAncestor(psiMethod, element, true) ||
|
||||
PsiTreeUtil.isAncestor(m, element, true);
|
||||
}
|
||||
}));
|
||||
return membersToCheck
|
||||
.stream()
|
||||
.filter(m -> containingClass.equals(m.getContainingClass()) && !psiMember.equals(m))
|
||||
.filter(m -> !(m instanceof PsiMethod) || ((PsiMethod)m).findDeepestSuperMethods().length == 0)
|
||||
.filter(m -> usedOnlyIn(m, psiMember))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected abstract ArrayList<SafeDeleteMethodCalleeUsageInfo> getTopLevelItems();
|
||||
|
||||
@Override
|
||||
protected JavaMethodNode createTreeNode(PsiMethod nodeMethod,
|
||||
com.intellij.util.containers.HashSet<PsiMethod> callees,
|
||||
protected JavaMemberNode<PsiMember> createTreeNode(PsiMember nodeMethod,
|
||||
com.intellij.util.containers.HashSet<PsiMember> callees,
|
||||
Runnable cancelCallback) {
|
||||
final SafeDeleteJavaMethodNode node = new SafeDeleteJavaMethodNode(nodeMethod, callees, cancelCallback, nodeMethod != null ? nodeMethod.getProject() : myProject);
|
||||
if (getTopMethod().equals(nodeMethod)) {
|
||||
final SafeDeleteJavaMemberNode node = new SafeDeleteJavaMemberNode(nodeMethod, callees, cancelCallback, nodeMethod != null ? nodeMethod.getProject() : myProject);
|
||||
if (getTopMember().equals(nodeMethod)) {
|
||||
node.setEnabled(false);
|
||||
node.setChecked(true);
|
||||
}
|
||||
@@ -88,39 +107,38 @@ abstract class SafeDeleteJavaCalleeChooser extends JavaCallerChooser {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MethodNodeBase<PsiMethod> getCalleeNode(MethodNodeBase<PsiMethod> node) {
|
||||
protected MemberNodeBase<PsiMember> getCalleeNode(MemberNodeBase<PsiMember> node) {
|
||||
return node;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MethodNodeBase<PsiMethod> getCallerNode(MethodNodeBase<PsiMethod> node) {
|
||||
return (MethodNodeBase<PsiMethod>)node.getParent();
|
||||
protected MemberNodeBase<PsiMember> getCallerNode(MemberNodeBase<PsiMember> node) {
|
||||
return (MemberNodeBase<PsiMember>)node.getParent();
|
||||
}
|
||||
|
||||
private class SafeDeleteJavaMethodNode extends JavaMethodNode {
|
||||
private class SafeDeleteJavaMemberNode extends JavaMemberNode<PsiMember> {
|
||||
|
||||
public SafeDeleteJavaMethodNode(PsiMethod currentMethod,
|
||||
HashSet<PsiMethod> callees,
|
||||
public SafeDeleteJavaMemberNode(PsiMember currentMember,
|
||||
HashSet<PsiMember> callees,
|
||||
Runnable cancelCallback,
|
||||
Project project) {
|
||||
super(currentMethod, callees, project, cancelCallback);
|
||||
|
||||
super(currentMember, callees, project, cancelCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MethodNodeBase<PsiMethod> createNode(PsiMethod caller, HashSet<PsiMethod> callees) {
|
||||
return new SafeDeleteJavaMethodNode(caller, callees, myCancelCallback, myProject);
|
||||
protected MemberNodeBase<PsiMember> createNode(PsiMember caller, HashSet<PsiMember> callees) {
|
||||
return new SafeDeleteJavaMemberNode(caller, callees, myCancelCallback, myProject);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<PsiMethod> computeCallers() {
|
||||
if (getTopMethod().equals(getMethod())) {
|
||||
return ContainerUtil.map(getTopLevelItems(), info -> info.getCalledMethod());
|
||||
protected List<PsiMember> computeCallers() {
|
||||
if (getTopMember().equals(getMember())) {
|
||||
return ContainerUtil.map(getTopLevelItems(), info -> info.getCalledMember());
|
||||
}
|
||||
|
||||
final List<PsiMethod> callees = computeCalleesSafeToDelete(getMethod());
|
||||
final List<PsiMember> callees = computeCalleesSafeToDelete(getMember());
|
||||
if (callees != null) {
|
||||
callees.remove(getTopMethod());
|
||||
callees.remove(getTopMember());
|
||||
return callees;
|
||||
}
|
||||
else {
|
||||
@@ -129,8 +147,20 @@ abstract class SafeDeleteJavaCalleeChooser extends JavaCallerChooser {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Condition<PsiMethod> getFilter() {
|
||||
return method -> !myMethod.equals(method);
|
||||
protected Condition<PsiMember> getFilter() {
|
||||
return member -> !getMember().equals(member);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean usedOnlyIn(@NotNull PsiMember explored, @NotNull PsiMember place) {
|
||||
return ReferencesSearch.search(explored).forEach(
|
||||
new CommonProcessors.CollectProcessor<PsiReference>() {
|
||||
@Override
|
||||
public boolean process(PsiReference reference) {
|
||||
final PsiElement element = reference.getElement();
|
||||
return PsiTreeUtil.isAncestor(place, element, true) ||
|
||||
PsiTreeUtil.isAncestor(explored, element, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
+13
-13
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
* Copyright 2000-2017 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.
|
||||
@@ -27,13 +27,13 @@ import com.intellij.psi.search.searches.OverridingMethodsSearch;
|
||||
import com.intellij.psi.search.searches.ReferencesSearch;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.refactoring.changeSignature.MethodNodeBase;
|
||||
import com.intellij.refactoring.changeSignature.MemberNodeBase;
|
||||
import com.intellij.refactoring.changeSignature.inCallers.JavaCallerChooser;
|
||||
import com.intellij.refactoring.changeSignature.inCallers.JavaMethodNode;
|
||||
import com.intellij.refactoring.safeDelete.usageInfo.SafeDeleteParameterCallHierarchyUsageInfo;
|
||||
import com.intellij.refactoring.safeDelete.usageInfo.SafeDeleteReferenceJavaDeleteUsageInfo;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.EmptyConsumer;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
|
||||
@@ -48,7 +48,7 @@ abstract class SafeDeleteJavaCallerChooser extends JavaCallerChooser {
|
||||
private final ArrayList<UsageInfo> myResult;
|
||||
|
||||
public SafeDeleteJavaCallerChooser(PsiMethod method, Project project, ArrayList<UsageInfo> result) {
|
||||
super(method, project, "Select Methods To Propagate Parameter Deletion", null, Consumer.EMPTY_CONSUMER);
|
||||
super(method, project, "Select Methods To Propagate Parameter Deletion", null, EmptyConsumer.getInstance());
|
||||
myMethod = method;
|
||||
myProject = project;
|
||||
myResult = result;
|
||||
@@ -59,11 +59,11 @@ abstract class SafeDeleteJavaCallerChooser extends JavaCallerChooser {
|
||||
|
||||
@Override
|
||||
protected JavaMethodNode createTreeNode(PsiMethod nodeMethod,
|
||||
com.intellij.util.containers.HashSet<PsiMethod> called,
|
||||
Runnable cancelCallback) {
|
||||
com.intellij.util.containers.HashSet<PsiMethod> called,
|
||||
Runnable cancelCallback) {
|
||||
final SafeDeleteJavaMethodNode node = new SafeDeleteJavaMethodNode(nodeMethod, called, cancelCallback, getParameterIdx(),
|
||||
nodeMethod != null ? nodeMethod.getProject() : myProject);
|
||||
if (getTopMethod().equals(nodeMethod)) {
|
||||
if (getTopMember().equals(nodeMethod)) {
|
||||
node.setEnabled(false);
|
||||
node.setChecked(true);
|
||||
}
|
||||
@@ -74,10 +74,10 @@ abstract class SafeDeleteJavaCallerChooser extends JavaCallerChooser {
|
||||
protected void doOKAction() {
|
||||
final List<UsageInfo> foreignMethodUsages = new ArrayList<>();
|
||||
final Runnable runnable = () -> {
|
||||
final Set<MethodNodeBase<PsiMethod>> nodes = getSelectedNodes();
|
||||
for (MethodNodeBase<PsiMethod> node : nodes) {
|
||||
final Set<MemberNodeBase<PsiMethod>> nodes = getSelectedNodes();
|
||||
for (MemberNodeBase<PsiMethod> node : nodes) {
|
||||
final SafeDeleteJavaMethodNode methodNode = (SafeDeleteJavaMethodNode)node;
|
||||
final PsiMethod nodeMethod = methodNode.getMethod();
|
||||
final PsiMethod nodeMethod = methodNode.getMember();
|
||||
if (nodeMethod.equals(myMethod)) continue;
|
||||
final PsiParameter parameter = nodeMethod.getParameterList().getParameters()[methodNode.myParameterIdx];
|
||||
foreignMethodUsages.add(new SafeDeleteParameterCallHierarchyUsageInfo(nodeMethod, parameter, nodeMethod, parameter));
|
||||
@@ -232,18 +232,18 @@ abstract class SafeDeleteJavaCallerChooser extends JavaCallerChooser {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MethodNodeBase<PsiMethod> createNode(PsiMethod caller, HashSet<PsiMethod> called) {
|
||||
protected MemberNodeBase<PsiMethod> createNode(PsiMethod caller, HashSet<PsiMethod> called) {
|
||||
return new SafeDeleteJavaMethodNode(caller, called, myCancelCallback, getCallerParameterIndex(myMethod, myParameterIdx, caller), myProject);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<PsiMethod> computeCallers() {
|
||||
if (getTopMethod().equals(getMethod())) {
|
||||
if (getTopMember().equals(getMember())) {
|
||||
final ArrayList<SafeDeleteParameterCallHierarchyUsageInfo> items = getTopLevelItems();
|
||||
return ContainerUtil.map(items, info -> info.getCallerMethod());
|
||||
}
|
||||
final List<PsiMethod> methods = super.computeCallers();
|
||||
methods.remove(getTopMethod());
|
||||
methods.remove(getTopMember());
|
||||
return methods;
|
||||
}
|
||||
|
||||
|
||||
+14
-15
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* Copyright 2000-2017 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.
|
||||
@@ -15,33 +15,32 @@
|
||||
*/
|
||||
package com.intellij.refactoring.safeDelete.usageInfo;
|
||||
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.PsiParameter;
|
||||
import com.intellij.psi.PsiMember;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
|
||||
public class SafeDeleteMethodCalleeUsageInfo extends SafeDeleteUsageInfo implements SafeDeleteCustomUsageInfo {
|
||||
public class SafeDeleteMemberCalleeUsageInfo extends SafeDeleteUsageInfo implements SafeDeleteCustomUsageInfo {
|
||||
|
||||
private final PsiMethod myCalledMethod;
|
||||
private final PsiMethod myCallerMethod;
|
||||
private final PsiMember myCalledMember;
|
||||
private final PsiMember myCallerMember;
|
||||
|
||||
public SafeDeleteMethodCalleeUsageInfo(PsiMethod calledMethod, PsiMethod callerMethod) {
|
||||
super(calledMethod, calledMethod);
|
||||
myCalledMethod = calledMethod;
|
||||
myCallerMethod = callerMethod;
|
||||
public SafeDeleteMemberCalleeUsageInfo(PsiMember calledMember, PsiMember callerMember) {
|
||||
super(calledMember, calledMember);
|
||||
myCalledMember = calledMember;
|
||||
myCallerMember = callerMember;
|
||||
}
|
||||
|
||||
public void performRefactoring() throws IncorrectOperationException {
|
||||
final PsiMethod callee = myCalledMethod;
|
||||
final PsiMember callee = myCalledMember;
|
||||
if (callee != null && callee.isValid()) {
|
||||
callee.delete();
|
||||
}
|
||||
}
|
||||
|
||||
public PsiMethod getCalledMethod() {
|
||||
return myCalledMethod;
|
||||
public PsiMember getCalledMember() {
|
||||
return myCalledMember;
|
||||
}
|
||||
|
||||
public PsiMethod getCallerMethod() {
|
||||
return myCallerMethod;
|
||||
public PsiMember getCallerMember() {
|
||||
return myCallerMember;
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
class Foo {
|
||||
static final String HEL<caret>LO = createHelloText();
|
||||
|
||||
static String createHelloText() {
|
||||
return "hello";
|
||||
}
|
||||
}
|
||||
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
class Foo {
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
class Foo {
|
||||
static final String WORLD = "world";
|
||||
|
||||
static void sayHelloWo<caret>rld() {
|
||||
hello();
|
||||
System.out.println(WORLD);
|
||||
}
|
||||
|
||||
static void hello() {
|
||||
System.out.println("hello");
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
class Foo {
|
||||
|
||||
}
|
||||
@@ -370,6 +370,14 @@ public class SafeDeleteTest extends MultiFileTestCase {
|
||||
});
|
||||
}
|
||||
|
||||
public void testDeepDeleteFieldAndInitializerMethod() throws Exception {
|
||||
doSingleFileTest();
|
||||
}
|
||||
|
||||
public void testDeleteMethodCascadeWithField() throws Exception {
|
||||
doSingleFileTest();
|
||||
}
|
||||
|
||||
private void doTest(@NonNls final String qClassName) {
|
||||
doTest((rootDir, rootAfter) -> this.performAction(qClassName));
|
||||
}
|
||||
|
||||
+27
-28
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2010 JetBrains s.r.o.
|
||||
* Copyright 2000-2017 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.
|
||||
@@ -40,7 +40,6 @@ import com.intellij.ui.*;
|
||||
import com.intellij.ui.treeStructure.Tree;
|
||||
import com.intellij.util.Alarm;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.Query;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.HashSet;
|
||||
@@ -58,7 +57,7 @@ import java.util.*;
|
||||
public abstract class CallerChooserBase<M extends PsiElement> extends DialogWrapper {
|
||||
private final M myMethod;
|
||||
private final Alarm myAlarm = new Alarm();
|
||||
private MethodNodeBase<M> myRoot;
|
||||
private MemberNodeBase<M> myRoot;
|
||||
protected final Project myProject;
|
||||
private Tree myTree;
|
||||
private final Consumer<Set<M>> myCallback;
|
||||
@@ -68,7 +67,7 @@ public abstract class CallerChooserBase<M extends PsiElement> extends DialogWrap
|
||||
private final boolean myInitDone;
|
||||
private final String myFileName;
|
||||
|
||||
protected abstract MethodNodeBase<M> createTreeNode(M method, HashSet<M> called, Runnable cancelCallback);
|
||||
protected abstract MemberNodeBase<M> createTreeNode(M method, HashSet<M> called, Runnable cancelCallback);
|
||||
|
||||
protected abstract M[] findDeepestSuperMethods(M method);
|
||||
|
||||
@@ -105,14 +104,14 @@ public abstract class CallerChooserBase<M extends PsiElement> extends DialogWrap
|
||||
}
|
||||
else {
|
||||
final CheckedTreeNode root = (CheckedTreeNode)myTree.getModel().getRoot();
|
||||
myRoot = (MethodNodeBase)root.getFirstChild();
|
||||
myRoot = (MemberNodeBase)root.getFirstChild();
|
||||
}
|
||||
myTreeSelectionListener = new TreeSelectionListener() {
|
||||
@Override
|
||||
public void valueChanged(TreeSelectionEvent e) {
|
||||
final TreePath path = e.getPath();
|
||||
if (path != null) {
|
||||
final MethodNodeBase<M> node = (MethodNodeBase)path.getLastPathComponent();
|
||||
final MemberNodeBase<M> node = (MemberNodeBase)path.getLastPathComponent();
|
||||
myAlarm.cancelAllRequests();
|
||||
myAlarm.addRequest(() -> updateEditorTexts(node), 300);
|
||||
}
|
||||
@@ -129,7 +128,7 @@ public abstract class CallerChooserBase<M extends PsiElement> extends DialogWrap
|
||||
myTree.getSelectionModel().addSelectionPath(selectionPath);
|
||||
}
|
||||
|
||||
final MethodNodeBase<M> node = (MethodNodeBase)selectionPath.getLastPathComponent();
|
||||
final MemberNodeBase<M> node = (MemberNodeBase)selectionPath.getLastPathComponent();
|
||||
updateEditorTexts(node);
|
||||
|
||||
splitter.setSecondComponent(callSitesViewer);
|
||||
@@ -137,12 +136,12 @@ public abstract class CallerChooserBase<M extends PsiElement> extends DialogWrap
|
||||
return result;
|
||||
}
|
||||
|
||||
private void updateEditorTexts(final MethodNodeBase<M> node) {
|
||||
final MethodNodeBase<M> parentNode = getCalleeNode(node);
|
||||
final MethodNodeBase<M> callerNode = getCallerNode(node);
|
||||
final String callerText = node != myRoot ? getText(callerNode.getMethod()) : getEmptyCallerText();
|
||||
private void updateEditorTexts(final MemberNodeBase<M> node) {
|
||||
final MemberNodeBase<M> parentNode = getCalleeNode(node);
|
||||
final MemberNodeBase<M> callerNode = getCallerNode(node);
|
||||
final String callerText = node != myRoot ? getText(callerNode.getMember()) : getEmptyCallerText();
|
||||
final Document callerDocument = myCallerEditor.getDocument();
|
||||
final String calleeText = node != myRoot ? getText(parentNode.getMethod()) : getEmptyCalleeText();
|
||||
final String calleeText = node != myRoot ? getText(parentNode.getMember()) : getEmptyCalleeText();
|
||||
final Document calleeDocument = myCalleeEditor.getDocument();
|
||||
|
||||
ApplicationManager.getApplication().runWriteAction(() -> {
|
||||
@@ -150,7 +149,7 @@ public abstract class CallerChooserBase<M extends PsiElement> extends DialogWrap
|
||||
calleeDocument.setText(calleeText);
|
||||
});
|
||||
|
||||
final M caller = callerNode.getMethod();
|
||||
final M caller = callerNode.getMember();
|
||||
final PsiElement callee = parentNode != null ? parentNode.getElementToSearch() : null;
|
||||
if (caller != null && caller.isPhysical() && callee != null) {
|
||||
HighlightManager highlighter = HighlightManager.getInstance(myProject);
|
||||
@@ -164,11 +163,11 @@ public abstract class CallerChooserBase<M extends PsiElement> extends DialogWrap
|
||||
}
|
||||
}
|
||||
|
||||
protected MethodNodeBase<M> getCalleeNode(MethodNodeBase<M> node) {
|
||||
return (MethodNodeBase<M>)node.getParent();
|
||||
protected MemberNodeBase<M> getCalleeNode(MemberNodeBase<M> node) {
|
||||
return (MemberNodeBase<M>)node.getParent();
|
||||
}
|
||||
|
||||
protected MethodNodeBase<M> getCallerNode(MethodNodeBase<M> node) {
|
||||
protected MemberNodeBase<M> getCallerNode(MemberNodeBase<M> node) {
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -250,8 +249,8 @@ public abstract class CallerChooserBase<M extends PsiElement> extends DialogWrap
|
||||
boolean leaf,
|
||||
int row,
|
||||
boolean hasFocus) {
|
||||
if (value instanceof MethodNodeBase) {
|
||||
((MethodNodeBase)value).customizeRenderer(getTextRenderer());
|
||||
if (value instanceof MemberNodeBase) {
|
||||
((MemberNodeBase)value).customizeRenderer(getTextRenderer());
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -262,19 +261,19 @@ public abstract class CallerChooserBase<M extends PsiElement> extends DialogWrap
|
||||
return tree;
|
||||
}
|
||||
|
||||
protected M getTopMethod() {
|
||||
protected M getTopMember() {
|
||||
return myMethod;
|
||||
}
|
||||
|
||||
private void getSelectedMethods(Set<M> methods) {
|
||||
MethodNodeBase<M> node = myRoot;
|
||||
MemberNodeBase<M> node = myRoot;
|
||||
getSelectedMethodsInner(node, methods);
|
||||
methods.remove(node.getMethod());
|
||||
methods.remove(node.getMember());
|
||||
}
|
||||
|
||||
private void getSelectedMethodsInner(final MethodNodeBase<M> node, final Set<M> allMethods) {
|
||||
private void getSelectedMethodsInner(final MemberNodeBase<M> node, final Set<M> allMethods) {
|
||||
if (node.isChecked()) {
|
||||
M method = node.getMethod();
|
||||
M method = node.getMember();
|
||||
final M[] superMethods = method == myMethod ? null : findDeepestSuperMethods(method);
|
||||
if (superMethods == null || superMethods.length == 0) {
|
||||
allMethods.add(method);
|
||||
@@ -285,23 +284,23 @@ public abstract class CallerChooserBase<M extends PsiElement> extends DialogWrap
|
||||
|
||||
final Enumeration children = node.children();
|
||||
while (children.hasMoreElements()) {
|
||||
getSelectedMethodsInner((MethodNodeBase)children.nextElement(), allMethods);
|
||||
getSelectedMethodsInner((MemberNodeBase)children.nextElement(), allMethods);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected Set<MethodNodeBase<M>> getSelectedNodes() {
|
||||
final Set<MethodNodeBase<M>> nodes = new LinkedHashSet<>();
|
||||
protected Set<MemberNodeBase<M>> getSelectedNodes() {
|
||||
final Set<MemberNodeBase<M>> nodes = new LinkedHashSet<>();
|
||||
collectSelectedNodes(myRoot, nodes);
|
||||
return nodes;
|
||||
}
|
||||
|
||||
private void collectSelectedNodes(final MethodNodeBase<M> node, final Set<MethodNodeBase<M>> nodes) {
|
||||
private void collectSelectedNodes(final MemberNodeBase<M> node, final Set<MemberNodeBase<M>> nodes) {
|
||||
if (node.isChecked()) {
|
||||
nodes.add(node);
|
||||
final Enumeration children = node.children();
|
||||
while (children.hasMoreElements()) {
|
||||
collectSelectedNodes((MethodNodeBase)children.nextElement(), nodes);
|
||||
collectSelectedNodes((MemberNodeBase)children.nextElement(), nodes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright 2000-2017 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.application.ApplicationManager;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.*;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.refactoring.RefactoringBundle;
|
||||
import com.intellij.ui.CheckedTreeNode;
|
||||
import com.intellij.ui.ColoredTreeCellRenderer;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.tree.TreeNode;
|
||||
import java.util.*;
|
||||
|
||||
public abstract class MemberNodeBase<M extends PsiElement> extends CheckedTreeNode {
|
||||
protected final M myMethod;
|
||||
protected final Set<M> myCalled;
|
||||
protected final Project myProject;
|
||||
protected final Runnable myCancelCallback;
|
||||
private boolean myOldChecked;
|
||||
|
||||
protected abstract MemberNodeBase<M> createNode(M caller, HashSet<M> called);
|
||||
|
||||
protected abstract List<M> computeCallers();
|
||||
|
||||
protected abstract void customizeRendererText(ColoredTreeCellRenderer renderer);
|
||||
|
||||
protected Condition<M> getFilter() {
|
||||
return Conditions.alwaysTrue();
|
||||
}
|
||||
|
||||
protected MemberNodeBase(final M method, Set<M> called, Project project, Runnable cancelCallback) {
|
||||
super(method);
|
||||
myMethod = method;
|
||||
myCalled = called;
|
||||
myProject = project;
|
||||
myCancelCallback = cancelCallback;
|
||||
isChecked = false;
|
||||
}
|
||||
|
||||
//IMPORTANT: do not build children in children()
|
||||
private void buildChildren() {
|
||||
if (children == null) {
|
||||
final List<M> callers = findCallers();
|
||||
children = new Vector(callers.size());
|
||||
for (M caller : callers) {
|
||||
final HashSet<M> called = new HashSet<>(myCalled);
|
||||
called.add(getMember());
|
||||
final MemberNodeBase<M> child = createNode(caller, called);
|
||||
children.add(child);
|
||||
child.parent = this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TreeNode getChildAt(int index) {
|
||||
buildChildren();
|
||||
return super.getChildAt(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getChildCount() {
|
||||
buildChildren();
|
||||
return super.getChildCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLeaf() {
|
||||
if (children == null) {
|
||||
return false;
|
||||
}
|
||||
return super.isLeaf();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIndex(TreeNode aChild) {
|
||||
buildChildren();
|
||||
return super.getIndex(aChild);
|
||||
}
|
||||
|
||||
private List<M> findCallers() {
|
||||
if (getMember() == null) return Collections.emptyList();
|
||||
final Ref<List<M>> callers = new Ref<>();
|
||||
if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(() -> ApplicationManager.getApplication().runReadAction(() -> callers.set(ContainerUtil.filter(computeCallers(), getFilter()))), RefactoringBundle.message("caller.chooser.looking.for.callers"), true, myProject)) {
|
||||
myCancelCallback.run();
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return callers.get();
|
||||
}
|
||||
|
||||
public void customizeRenderer(ColoredTreeCellRenderer renderer) {
|
||||
if (getMember() == null) return;
|
||||
final int flags = Iconable.ICON_FLAG_VISIBILITY | Iconable.ICON_FLAG_READ_STATUS;
|
||||
renderer.setIcon(ApplicationManager.getApplication().runReadAction(new Computable<Icon>() {
|
||||
@Override
|
||||
public Icon compute() {
|
||||
return getMember().getIcon(flags);
|
||||
}
|
||||
}));
|
||||
|
||||
customizeRendererText(renderer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnabled(final boolean enabled) {
|
||||
super.setEnabled(enabled);
|
||||
if (!enabled) {
|
||||
myOldChecked = isChecked();
|
||||
setChecked(false);
|
||||
}
|
||||
else {
|
||||
setChecked(myOldChecked);
|
||||
}
|
||||
}
|
||||
|
||||
public M getMember() {
|
||||
return myMethod;
|
||||
}
|
||||
|
||||
public PsiElement getElementToSearch() {
|
||||
return getMember();
|
||||
}
|
||||
|
||||
}
|
||||
+13
-120
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* Copyright 2000-2017 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.
|
||||
@@ -15,131 +15,24 @@
|
||||
*/
|
||||
package com.intellij.refactoring.changeSignature;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.Iconable;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.refactoring.RefactoringBundle;
|
||||
import com.intellij.ui.CheckedTreeNode;
|
||||
import com.intellij.ui.ColoredTreeCellRenderer;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.tree.TreeNode;
|
||||
import java.util.*;
|
||||
import java.util.Set;
|
||||
|
||||
public abstract class MethodNodeBase<M extends PsiElement> extends CheckedTreeNode {
|
||||
protected final M myMethod;
|
||||
protected final Set<M> myCalled;
|
||||
protected final Project myProject;
|
||||
protected final Runnable myCancelCallback;
|
||||
private boolean myOldChecked;
|
||||
|
||||
protected abstract MethodNodeBase<M> createNode(M caller, HashSet<M> called);
|
||||
|
||||
protected abstract List<M> computeCallers();
|
||||
|
||||
protected abstract void customizeRendererText(ColoredTreeCellRenderer renderer);
|
||||
|
||||
protected Condition<M> getFilter() {
|
||||
return Condition.TRUE;
|
||||
}
|
||||
|
||||
protected MethodNodeBase(final M method, Set<M> called, Project project, Runnable cancelCallback) {
|
||||
super(method);
|
||||
myMethod = method;
|
||||
myCalled = called;
|
||||
myProject = project;
|
||||
myCancelCallback = cancelCallback;
|
||||
isChecked = false;
|
||||
}
|
||||
|
||||
//IMPORTANT: do not build children in children()
|
||||
private void buildChildren() {
|
||||
if (children == null) {
|
||||
final List<M> callers = findCallers();
|
||||
children = new Vector(callers.size());
|
||||
for (M caller : callers) {
|
||||
final HashSet<M> called = new HashSet<>(myCalled);
|
||||
called.add(myMethod);
|
||||
final MethodNodeBase<M> child = createNode(caller, called);
|
||||
children.add(child);
|
||||
child.parent = this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TreeNode getChildAt(int index) {
|
||||
buildChildren();
|
||||
return super.getChildAt(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getChildCount() {
|
||||
buildChildren();
|
||||
return super.getChildCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLeaf() {
|
||||
if (children == null) {
|
||||
return false;
|
||||
}
|
||||
return super.isLeaf();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIndex(TreeNode aChild) {
|
||||
buildChildren();
|
||||
return super.getIndex(aChild);
|
||||
}
|
||||
|
||||
private List<M> findCallers() {
|
||||
if (myMethod == null) return Collections.emptyList();
|
||||
final Ref<List<M>> callers = new Ref<>();
|
||||
if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(() -> ApplicationManager.getApplication().runReadAction(() -> callers.set(ContainerUtil.filter(computeCallers(), getFilter()))), RefactoringBundle.message("caller.chooser.looking.for.callers"), true, myProject)) {
|
||||
myCancelCallback.run();
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return callers.get();
|
||||
}
|
||||
|
||||
public void customizeRenderer(ColoredTreeCellRenderer renderer) {
|
||||
if (myMethod == null) return;
|
||||
final int flags = Iconable.ICON_FLAG_VISIBILITY | Iconable.ICON_FLAG_READ_STATUS;
|
||||
renderer.setIcon(ApplicationManager.getApplication().runReadAction(new Computable<Icon>() {
|
||||
@Override
|
||||
public Icon compute() {
|
||||
return myMethod.getIcon(flags);
|
||||
}
|
||||
}));
|
||||
|
||||
customizeRendererText(renderer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnabled(final boolean enabled) {
|
||||
super.setEnabled(enabled);
|
||||
if (!enabled) {
|
||||
myOldChecked = isChecked();
|
||||
setChecked(false);
|
||||
}
|
||||
else {
|
||||
setChecked(myOldChecked);
|
||||
}
|
||||
/**
|
||||
* @deprecated to be removed in IDEA 2019.1
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract class MethodNodeBase<M extends PsiElement> extends MemberNodeBase<M> {
|
||||
protected MethodNodeBase(M method,
|
||||
Set<M> called,
|
||||
Project project,
|
||||
Runnable cancelCallback) {
|
||||
super(method, called, project, cancelCallback);
|
||||
}
|
||||
|
||||
public M getMethod() {
|
||||
return myMethod;
|
||||
return getMember();
|
||||
}
|
||||
|
||||
public PsiElement getElementToSearch() {
|
||||
return getMethod();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user