diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/inCallers/AbstractJavaMemberCallerChooser.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/inCallers/AbstractJavaMemberCallerChooser.java new file mode 100644 index 000000000000..c9dd214185cf --- /dev/null +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/inCallers/AbstractJavaMemberCallerChooser.java @@ -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 extends CallerChooserBase { + + public AbstractJavaMemberCallerChooser(M member, Project project, String title, Tree previousTree, Consumer> 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"; + } +} diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/inCallers/JavaCallerChooser.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/inCallers/JavaCallerChooser.java index 6468988ed7bb..3a5459bdf56c 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/inCallers/JavaCallerChooser.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/inCallers/JavaCallerChooser.java @@ -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 { +public class JavaCallerChooser extends AbstractJavaMemberCallerChooser { + public JavaCallerChooser(PsiMethod method, + Project project, + String title, + Tree previousTree, + Consumer> callback) { + super(method, project, title, previousTree, callback); + } - public JavaCallerChooser(PsiMethod method, Project project, String title, Tree previousTree, Consumer> 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 called, Runnable cancelCallback) { + protected MemberNodeBase createTreeNode(PsiMethod method, HashSet called, Runnable cancelCallback) { return new JavaMethodNode(method, called, myProject, cancelCallback); } @@ -40,14 +49,4 @@ public class JavaCallerChooser extends CallerChooserBase { 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"; - } } diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/inCallers/JavaMemberNode.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/inCallers/JavaMemberNode.java new file mode 100644 index 000000000000..16a157f3bf9c --- /dev/null +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/inCallers/JavaMemberNode.java @@ -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 extends MemberNodeBase { + protected JavaMemberNode(final M member, Set 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 + ); + } + } +} diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/inCallers/JavaMethodNode.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/inCallers/JavaMethodNode.java index 324779aa365b..78d97091436f 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/inCallers/JavaMethodNode.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/inCallers/JavaMethodNode.java @@ -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 { - - protected JavaMethodNode(final PsiMethod method, Set called, Project project, Runnable cancelCallback) { +public class JavaMethodNode extends JavaMemberNode { + protected JavaMethodNode(PsiMethod method, + Set called, + Project project, + Runnable cancelCallback) { super(method, called, project, cancelCallback); } @Override - protected MethodNodeBase createNode(PsiMethod caller, HashSet called) { + protected MemberNodeBase createNode(PsiMethod caller, HashSet called) { return new JavaMethodNode(caller, called, myProject, myCancelCallback); } @Override protected List 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 result = new ArrayList<>(); for (PsiReference ref : refs) { @@ -57,7 +50,7 @@ public class JavaMethodNode extends MethodNodeBase { !(((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 { } 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)); - } - } } diff --git a/java/java-impl/src/com/intellij/refactoring/makeStatic/MakeStaticJavaCallerChooser.java b/java/java-impl/src/com/intellij/refactoring/makeStatic/MakeStaticJavaCallerChooser.java index 0ff4714084d8..5815a136859b 100644 --- a/java/java-impl/src/com/intellij/refactoring/makeStatic/MakeStaticJavaCallerChooser.java +++ b/java/java-impl/src/com/intellij/refactoring/makeStatic/MakeStaticJavaCallerChooser.java @@ -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 computeCallers() { - if (getTopMethod().equals(getMethod())) { + if (getTopMember().equals(getMember())) { final ArrayList items = getTopLevelItems(); return ContainerUtil.map(items, info -> (PsiMethod)info.getElement()); } @@ -104,7 +103,7 @@ abstract class MakeStaticJavaCallerChooser extends JavaCallerChooser { @Override - protected MethodNodeBase createNode(PsiMethod caller, HashSet called) { + protected MemberNodeBase createNode(PsiMethod caller, HashSet called) { return new MakeStaticJavaMethodNode(caller, called, myCancelCallback, myProject); } diff --git a/java/java-impl/src/com/intellij/refactoring/safeDelete/JavaSafeDeleteProcessor.java b/java/java-impl/src/com/intellij/refactoring/safeDelete/JavaSafeDeleteProcessor.java index 2eebd59bdd72..4e501efbd4cd 100644 --- a/java/java-impl/src/com/intellij/refactoring/safeDelete/JavaSafeDeleteProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/safeDelete/JavaSafeDeleteProcessor.java @@ -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 result = new ArrayList<>(); final ArrayList overridingMethods = new ArrayList<>(); final ArrayList delegatingParams = new ArrayList<>(); - final ArrayList calleesSafeToDelete = new ArrayList<>(); + final ArrayList 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 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 list = new ArrayList<>(); - JavaCallerChooser chooser = new SafeDeleteJavaCalleeChooser(method, project, list) { + AbstractJavaMemberCallerChooser chooser = new SafeDeleteJavaCalleeChooser(member, project, list) { @Override - protected ArrayList getTopLevelItems() { + protected ArrayList 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 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 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 usages) { + final List calleesSafeToDelete = SafeDeleteJavaCalleeChooser.computeCalleesSafeToDelete(method); + if (calleesSafeToDelete != null) { + for (PsiMember callee : calleesSafeToDelete) { + usages.add(new SafeDeleteMemberCalleeUsageInfo(callee, method)); + } + } + } + private static void findFunctionalExpressions(final List 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; } diff --git a/java/java-impl/src/com/intellij/refactoring/safeDelete/SafeDeleteJavaCalleeChooser.java b/java/java-impl/src/com/intellij/refactoring/safeDelete/SafeDeleteJavaCalleeChooser.java index 60349a3cdd55..fb5b4a293688 100644 --- a/java/java-impl/src/com/intellij/refactoring/safeDelete/SafeDeleteJavaCalleeChooser.java +++ b/java/java-impl/src/com/intellij/refactoring/safeDelete/SafeDeleteJavaCalleeChooser.java @@ -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 { private final Project myProject; - public SafeDeleteJavaCalleeChooser(final PsiMethod method, Project project, final ArrayList 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 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 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 computeCalleesSafeToDelete(final PsiMethod psiMethod) { - final PsiCodeBlock body = psiMethod.getBody(); + static List 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 methodsToCheck = new HashSet<>(); + final Set 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() { - @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 getTopLevelItems(); - @Override - protected JavaMethodNode createTreeNode(PsiMethod nodeMethod, - com.intellij.util.containers.HashSet callees, + protected JavaMemberNode createTreeNode(PsiMember nodeMethod, + com.intellij.util.containers.HashSet 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 getCalleeNode(MethodNodeBase node) { + protected MemberNodeBase getCalleeNode(MemberNodeBase node) { return node; } @Override - protected MethodNodeBase getCallerNode(MethodNodeBase node) { - return (MethodNodeBase)node.getParent(); + protected MemberNodeBase getCallerNode(MemberNodeBase node) { + return (MemberNodeBase)node.getParent(); } - private class SafeDeleteJavaMethodNode extends JavaMethodNode { + private class SafeDeleteJavaMemberNode extends JavaMemberNode { - public SafeDeleteJavaMethodNode(PsiMethod currentMethod, - HashSet callees, + public SafeDeleteJavaMemberNode(PsiMember currentMember, + HashSet callees, Runnable cancelCallback, Project project) { - super(currentMethod, callees, project, cancelCallback); - + super(currentMember, callees, project, cancelCallback); } @Override - protected MethodNodeBase createNode(PsiMethod caller, HashSet callees) { - return new SafeDeleteJavaMethodNode(caller, callees, myCancelCallback, myProject); + protected MemberNodeBase createNode(PsiMember caller, HashSet callees) { + return new SafeDeleteJavaMemberNode(caller, callees, myCancelCallback, myProject); } @Override - protected List computeCallers() { - if (getTopMethod().equals(getMethod())) { - return ContainerUtil.map(getTopLevelItems(), info -> info.getCalledMethod()); + protected List computeCallers() { + if (getTopMember().equals(getMember())) { + return ContainerUtil.map(getTopLevelItems(), info -> info.getCalledMember()); } - final List callees = computeCalleesSafeToDelete(getMethod()); + final List 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 getFilter() { - return method -> !myMethod.equals(method); + protected Condition getFilter() { + return member -> !getMember().equals(member); } } + + private static boolean usedOnlyIn(@NotNull PsiMember explored, @NotNull PsiMember place) { + return ReferencesSearch.search(explored).forEach( + new CommonProcessors.CollectProcessor() { + @Override + public boolean process(PsiReference reference) { + final PsiElement element = reference.getElement(); + return PsiTreeUtil.isAncestor(place, element, true) || + PsiTreeUtil.isAncestor(explored, element, true); + } + }); + } } \ No newline at end of file diff --git a/java/java-impl/src/com/intellij/refactoring/safeDelete/SafeDeleteJavaCallerChooser.java b/java/java-impl/src/com/intellij/refactoring/safeDelete/SafeDeleteJavaCallerChooser.java index 6217d83d8920..a81a58798e4e 100644 --- a/java/java-impl/src/com/intellij/refactoring/safeDelete/SafeDeleteJavaCallerChooser.java +++ b/java/java-impl/src/com/intellij/refactoring/safeDelete/SafeDeleteJavaCallerChooser.java @@ -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 myResult; public SafeDeleteJavaCallerChooser(PsiMethod method, Project project, ArrayList 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 called, - Runnable cancelCallback) { + com.intellij.util.containers.HashSet 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 foreignMethodUsages = new ArrayList<>(); final Runnable runnable = () -> { - final Set> nodes = getSelectedNodes(); - for (MethodNodeBase node : nodes) { + final Set> nodes = getSelectedNodes(); + for (MemberNodeBase 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 createNode(PsiMethod caller, HashSet called) { + protected MemberNodeBase createNode(PsiMethod caller, HashSet called) { return new SafeDeleteJavaMethodNode(caller, called, myCancelCallback, getCallerParameterIndex(myMethod, myParameterIdx, caller), myProject); } @Override protected List computeCallers() { - if (getTopMethod().equals(getMethod())) { + if (getTopMember().equals(getMember())) { final ArrayList items = getTopLevelItems(); return ContainerUtil.map(items, info -> info.getCallerMethod()); } final List methods = super.computeCallers(); - methods.remove(getTopMethod()); + methods.remove(getTopMember()); return methods; } diff --git a/java/java-impl/src/com/intellij/refactoring/safeDelete/usageInfo/SafeDeleteMethodCalleeUsageInfo.java b/java/java-impl/src/com/intellij/refactoring/safeDelete/usageInfo/SafeDeleteMemberCalleeUsageInfo.java similarity index 58% rename from java/java-impl/src/com/intellij/refactoring/safeDelete/usageInfo/SafeDeleteMethodCalleeUsageInfo.java rename to java/java-impl/src/com/intellij/refactoring/safeDelete/usageInfo/SafeDeleteMemberCalleeUsageInfo.java index d7a49f732894..84c605162bf9 100644 --- a/java/java-impl/src/com/intellij/refactoring/safeDelete/usageInfo/SafeDeleteMethodCalleeUsageInfo.java +++ b/java/java-impl/src/com/intellij/refactoring/safeDelete/usageInfo/SafeDeleteMemberCalleeUsageInfo.java @@ -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; } } diff --git a/java/java-tests/testData/refactoring/safeDelete/DeepDeleteFieldAndInitializerMethod.java b/java/java-tests/testData/refactoring/safeDelete/DeepDeleteFieldAndInitializerMethod.java new file mode 100644 index 000000000000..6306e68641bb --- /dev/null +++ b/java/java-tests/testData/refactoring/safeDelete/DeepDeleteFieldAndInitializerMethod.java @@ -0,0 +1,8 @@ +class Foo { + static final String HELLO = createHelloText(); + + static String createHelloText() { + return "hello"; + } +} + diff --git a/java/java-tests/testData/refactoring/safeDelete/DeepDeleteFieldAndInitializerMethod_after.java b/java/java-tests/testData/refactoring/safeDelete/DeepDeleteFieldAndInitializerMethod_after.java new file mode 100644 index 000000000000..95cfdc471655 --- /dev/null +++ b/java/java-tests/testData/refactoring/safeDelete/DeepDeleteFieldAndInitializerMethod_after.java @@ -0,0 +1,4 @@ +class Foo { + +} + diff --git a/java/java-tests/testData/refactoring/safeDelete/DeleteMethodCascadeWithField.java b/java/java-tests/testData/refactoring/safeDelete/DeleteMethodCascadeWithField.java new file mode 100644 index 000000000000..bedc466a9927 --- /dev/null +++ b/java/java-tests/testData/refactoring/safeDelete/DeleteMethodCascadeWithField.java @@ -0,0 +1,12 @@ +class Foo { + static final String WORLD = "world"; + + static void sayHelloWorld() { + hello(); + System.out.println(WORLD); + } + + static void hello() { + System.out.println("hello"); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/safeDelete/DeleteMethodCascadeWithField_after.java b/java/java-tests/testData/refactoring/safeDelete/DeleteMethodCascadeWithField_after.java new file mode 100644 index 000000000000..576000ea446f --- /dev/null +++ b/java/java-tests/testData/refactoring/safeDelete/DeleteMethodCascadeWithField_after.java @@ -0,0 +1,3 @@ +class Foo { + +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/refactoring/SafeDeleteTest.java b/java/java-tests/testSrc/com/intellij/java/refactoring/SafeDeleteTest.java index 7db53e0186f8..787666248934 100644 --- a/java/java-tests/testSrc/com/intellij/java/refactoring/SafeDeleteTest.java +++ b/java/java-tests/testSrc/com/intellij/java/refactoring/SafeDeleteTest.java @@ -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)); } diff --git a/platform/lang-impl/src/com/intellij/refactoring/changeSignature/CallerChooserBase.java b/platform/lang-impl/src/com/intellij/refactoring/changeSignature/CallerChooserBase.java index 6d73e2487156..6f6a0071df6e 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/changeSignature/CallerChooserBase.java +++ b/platform/lang-impl/src/com/intellij/refactoring/changeSignature/CallerChooserBase.java @@ -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 extends DialogWrapper { private final M myMethod; private final Alarm myAlarm = new Alarm(); - private MethodNodeBase myRoot; + private MemberNodeBase myRoot; protected final Project myProject; private Tree myTree; private final Consumer> myCallback; @@ -68,7 +67,7 @@ public abstract class CallerChooserBase extends DialogWrap private final boolean myInitDone; private final String myFileName; - protected abstract MethodNodeBase createTreeNode(M method, HashSet called, Runnable cancelCallback); + protected abstract MemberNodeBase createTreeNode(M method, HashSet called, Runnable cancelCallback); protected abstract M[] findDeepestSuperMethods(M method); @@ -105,14 +104,14 @@ public abstract class CallerChooserBase 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 node = (MethodNodeBase)path.getLastPathComponent(); + final MemberNodeBase node = (MemberNodeBase)path.getLastPathComponent(); myAlarm.cancelAllRequests(); myAlarm.addRequest(() -> updateEditorTexts(node), 300); } @@ -129,7 +128,7 @@ public abstract class CallerChooserBase extends DialogWrap myTree.getSelectionModel().addSelectionPath(selectionPath); } - final MethodNodeBase node = (MethodNodeBase)selectionPath.getLastPathComponent(); + final MemberNodeBase node = (MemberNodeBase)selectionPath.getLastPathComponent(); updateEditorTexts(node); splitter.setSecondComponent(callSitesViewer); @@ -137,12 +136,12 @@ public abstract class CallerChooserBase extends DialogWrap return result; } - private void updateEditorTexts(final MethodNodeBase node) { - final MethodNodeBase parentNode = getCalleeNode(node); - final MethodNodeBase callerNode = getCallerNode(node); - final String callerText = node != myRoot ? getText(callerNode.getMethod()) : getEmptyCallerText(); + private void updateEditorTexts(final MemberNodeBase node) { + final MemberNodeBase parentNode = getCalleeNode(node); + final MemberNodeBase 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 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 extends DialogWrap } } - protected MethodNodeBase getCalleeNode(MethodNodeBase node) { - return (MethodNodeBase)node.getParent(); + protected MemberNodeBase getCalleeNode(MemberNodeBase node) { + return (MemberNodeBase)node.getParent(); } - protected MethodNodeBase getCallerNode(MethodNodeBase node) { + protected MemberNodeBase getCallerNode(MemberNodeBase node) { return node; } @@ -250,8 +249,8 @@ public abstract class CallerChooserBase 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 extends DialogWrap return tree; } - protected M getTopMethod() { + protected M getTopMember() { return myMethod; } private void getSelectedMethods(Set methods) { - MethodNodeBase node = myRoot; + MemberNodeBase node = myRoot; getSelectedMethodsInner(node, methods); - methods.remove(node.getMethod()); + methods.remove(node.getMember()); } - private void getSelectedMethodsInner(final MethodNodeBase node, final Set allMethods) { + private void getSelectedMethodsInner(final MemberNodeBase node, final Set 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 extends DialogWrap final Enumeration children = node.children(); while (children.hasMoreElements()) { - getSelectedMethodsInner((MethodNodeBase)children.nextElement(), allMethods); + getSelectedMethodsInner((MemberNodeBase)children.nextElement(), allMethods); } } } - protected Set> getSelectedNodes() { - final Set> nodes = new LinkedHashSet<>(); + protected Set> getSelectedNodes() { + final Set> nodes = new LinkedHashSet<>(); collectSelectedNodes(myRoot, nodes); return nodes; } - private void collectSelectedNodes(final MethodNodeBase node, final Set> nodes) { + private void collectSelectedNodes(final MemberNodeBase node, final Set> 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); } } } diff --git a/platform/lang-impl/src/com/intellij/refactoring/changeSignature/MemberNodeBase.java b/platform/lang-impl/src/com/intellij/refactoring/changeSignature/MemberNodeBase.java new file mode 100644 index 000000000000..b69178be3460 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/refactoring/changeSignature/MemberNodeBase.java @@ -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 extends CheckedTreeNode { + protected final M myMethod; + protected final Set myCalled; + protected final Project myProject; + protected final Runnable myCancelCallback; + private boolean myOldChecked; + + protected abstract MemberNodeBase createNode(M caller, HashSet called); + + protected abstract List computeCallers(); + + protected abstract void customizeRendererText(ColoredTreeCellRenderer renderer); + + protected Condition getFilter() { + return Conditions.alwaysTrue(); + } + + protected MemberNodeBase(final M method, Set 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 callers = findCallers(); + children = new Vector(callers.size()); + for (M caller : callers) { + final HashSet called = new HashSet<>(myCalled); + called.add(getMember()); + final MemberNodeBase 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 findCallers() { + if (getMember() == null) return Collections.emptyList(); + final Ref> 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() { + @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(); + } + +} diff --git a/platform/lang-impl/src/com/intellij/refactoring/changeSignature/MethodNodeBase.java b/platform/lang-impl/src/com/intellij/refactoring/changeSignature/MethodNodeBase.java index c1c676019334..2ad9d9574c9a 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/changeSignature/MethodNodeBase.java +++ b/platform/lang-impl/src/com/intellij/refactoring/changeSignature/MethodNodeBase.java @@ -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 extends CheckedTreeNode { - protected final M myMethod; - protected final Set myCalled; - protected final Project myProject; - protected final Runnable myCancelCallback; - private boolean myOldChecked; - - protected abstract MethodNodeBase createNode(M caller, HashSet called); - - protected abstract List computeCallers(); - - protected abstract void customizeRendererText(ColoredTreeCellRenderer renderer); - - protected Condition getFilter() { - return Condition.TRUE; - } - - protected MethodNodeBase(final M method, Set 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 callers = findCallers(); - children = new Vector(callers.size()); - for (M caller : callers) { - final HashSet called = new HashSet<>(myCalled); - called.add(myMethod); - final MethodNodeBase 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 findCallers() { - if (myMethod == null) return Collections.emptyList(); - final Ref> 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() { - @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 extends MemberNodeBase { + protected MethodNodeBase(M method, + Set called, + Project project, + Runnable cancelCallback) { + super(method, called, project, cancelCallback); } public M getMethod() { - return myMethod; + return getMember(); } - - public PsiElement getElementToSearch() { - return getMethod(); - } - }