From 13eac43cc2b190f692c8b38ea301b2e91e5016c2 Mon Sep 17 00:00:00 2001 From: UNV Date: Fri, 25 Apr 2025 20:19:34 +0300 Subject: [PATCH 1/2] Reformatting hierarchy. --- .../impl/ide/hierarchy/JavaHierarchyUtil.java | 34 +- .../hierarchy/call/CallHierarchyBrowser.java | 110 ++-- .../call/CallHierarchyNodeDescriptor.java | 357 +++++++------ .../call/CalleeMethodsTreeStructure.java | 150 +++--- .../call/CallerMethodsTreeStructure.java | 188 +++---- .../call/JavaCallHierarchyProvider.java | 44 +- .../method/ImplementMethodAction.java | 20 +- .../method/JavaMethodHierarchyProvider.java | 125 ++--- .../method/MethodHierarchyBrowser.java | 104 ++-- .../method/MethodHierarchyNodeDescriptor.java | 289 +++++------ .../method/MethodHierarchyTreeStructure.java | 477 ++++++++---------- .../hierarchy/method/MethodHierarchyUtil.java | 34 +- .../method/OverrideImplementMethodAction.java | 309 ++++++------ .../method/OverrideMethodAction.java | 20 +- .../type/JavaTypeHierarchyProvider.java | 120 ++--- .../type/SubtypesHierarchyTreeStructure.java | 87 ++-- .../SupertypesHierarchyTreeStructure.java | 72 ++- .../hierarchy/type/TypeHierarchyBrowser.java | 222 ++++---- .../type/TypeHierarchyNodeDescriptor.java | 102 ++-- .../type/TypeHierarchyTreeStructure.java | 91 ++-- 20 files changed, 1435 insertions(+), 1520 deletions(-) diff --git a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/JavaHierarchyUtil.java b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/JavaHierarchyUtil.java index fc1614823c..403a9d3d30 100644 --- a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/JavaHierarchyUtil.java +++ b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/JavaHierarchyUtil.java @@ -31,24 +31,26 @@ * @author yole */ public class JavaHierarchyUtil { - private JavaHierarchyUtil() { - } + private JavaHierarchyUtil() { + } - @Nullable - public static String getPackageName(final PsiClass psiClass) { - final PsiFile file = psiClass.getContainingFile(); - if (file instanceof PsiClassOwner) { - return ((PsiClassOwner) file).getPackageName(); - } else { - return null; + @Nullable + public static String getPackageName(final PsiClass psiClass) { + final PsiFile file = psiClass.getContainingFile(); + if (file instanceof PsiClassOwner) { + return ((PsiClassOwner)file).getPackageName(); + } + else { + return null; + } } - } - public static Comparator getComparator(Project project) { - if (HierarchyBrowserManager.getInstance(project).getState().SORT_ALPHABETICALLY) { - return AlphaComparator.INSTANCE; - } else { - return SourceComparator.INSTANCE; + public static Comparator getComparator(Project project) { + if (HierarchyBrowserManager.getInstance(project).getState().SORT_ALPHABETICALLY) { + return AlphaComparator.INSTANCE; + } + else { + return SourceComparator.INSTANCE; + } } - } } diff --git a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/call/CallHierarchyBrowser.java b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/call/CallHierarchyBrowser.java index 1207516e1b..735e1da681 100644 --- a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/call/CallHierarchyBrowser.java +++ b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/call/CallHierarchyBrowser.java @@ -36,71 +36,71 @@ import java.util.Map; public class CallHierarchyBrowser extends CallHierarchyBrowserBase { - private static final Logger LOG = Logger.getInstance(CallHierarchyBrowser.class); + private static final Logger LOG = Logger.getInstance(CallHierarchyBrowser.class); - public CallHierarchyBrowser(@Nonnull Project project, @Nonnull PsiMethod method) { - super(project, method); - } - - @Override - protected void createTrees(@Nonnull final Map type2TreeMap) { - ActionGroup group = (ActionGroup)ActionManager.getInstance().getAction(IdeActions.GROUP_CALL_HIERARCHY_POPUP); - final JTree tree1 = createTree(false); - PopupHandler.installPopupHandler(tree1, group, ActionPlaces.CALL_HIERARCHY_VIEW_POPUP, ActionManager.getInstance()); - final BaseOnThisMethodAction baseOnThisMethodAction = new BaseOnThisMethodAction(); - baseOnThisMethodAction - .registerCustomShortcutSet(ActionManager.getInstance().getAction(IdeActions.ACTION_CALL_HIERARCHY).getShortcutSet(), tree1); - type2TreeMap.put(CALLEE_TYPE, tree1); + public CallHierarchyBrowser(@Nonnull Project project, @Nonnull PsiMethod method) { + super(project, method); + } - final JTree tree2 = createTree(false); - PopupHandler.installPopupHandler(tree2, group, ActionPlaces.CALL_HIERARCHY_VIEW_POPUP, ActionManager.getInstance()); - baseOnThisMethodAction - .registerCustomShortcutSet(ActionManager.getInstance().getAction(IdeActions.ACTION_CALL_HIERARCHY).getShortcutSet(), tree2); - type2TreeMap.put(CALLER_TYPE, tree2); - } + @Override + protected void createTrees(@Nonnull final Map type2TreeMap) { + ActionGroup group = (ActionGroup)ActionManager.getInstance().getAction(IdeActions.GROUP_CALL_HIERARCHY_POPUP); + final JTree tree1 = createTree(false); + PopupHandler.installPopupHandler(tree1, group, ActionPlaces.CALL_HIERARCHY_VIEW_POPUP, ActionManager.getInstance()); + final BaseOnThisMethodAction baseOnThisMethodAction = new BaseOnThisMethodAction(); + baseOnThisMethodAction + .registerCustomShortcutSet(ActionManager.getInstance().getAction(IdeActions.ACTION_CALL_HIERARCHY).getShortcutSet(), tree1); + type2TreeMap.put(CALLEE_TYPE, tree1); - @Override - protected PsiElement getElementFromDescriptor(@Nonnull HierarchyNodeDescriptor descriptor) { - if (descriptor instanceof CallHierarchyNodeDescriptor) { - CallHierarchyNodeDescriptor nodeDescriptor = (CallHierarchyNodeDescriptor)descriptor; - return nodeDescriptor.getEnclosingElement(); + final JTree tree2 = createTree(false); + PopupHandler.installPopupHandler(tree2, group, ActionPlaces.CALL_HIERARCHY_VIEW_POPUP, ActionManager.getInstance()); + baseOnThisMethodAction + .registerCustomShortcutSet(ActionManager.getInstance().getAction(IdeActions.ACTION_CALL_HIERARCHY).getShortcutSet(), tree2); + type2TreeMap.put(CALLER_TYPE, tree2); } - return null; - } - @Override - protected PsiElement getOpenFileElementFromDescriptor(@Nonnull HierarchyNodeDescriptor descriptor) { - if (descriptor instanceof CallHierarchyNodeDescriptor) { - CallHierarchyNodeDescriptor nodeDescriptor = (CallHierarchyNodeDescriptor)descriptor; - return nodeDescriptor.getTargetElement(); + @Override + protected PsiElement getElementFromDescriptor(@Nonnull HierarchyNodeDescriptor descriptor) { + if (descriptor instanceof CallHierarchyNodeDescriptor) { + CallHierarchyNodeDescriptor nodeDescriptor = (CallHierarchyNodeDescriptor)descriptor; + return nodeDescriptor.getEnclosingElement(); + } + return null; } - return null; - } - @Override - protected boolean isApplicableElement(@Nonnull final PsiElement element) { - return element instanceof PsiMethod; - } - - @Override - protected HierarchyTreeStructure createHierarchyTreeStructure(@Nonnull final String typeName, @Nonnull final PsiElement psiElement) { - if (CALLER_TYPE.equals(typeName)) { - return new CallerMethodsTreeStructure(myProject, (PsiMethod)psiElement, getCurrentScopeType()); + @Override + protected PsiElement getOpenFileElementFromDescriptor(@Nonnull HierarchyNodeDescriptor descriptor) { + if (descriptor instanceof CallHierarchyNodeDescriptor) { + CallHierarchyNodeDescriptor nodeDescriptor = (CallHierarchyNodeDescriptor)descriptor; + return nodeDescriptor.getTargetElement(); + } + return null; } - else if (CALLEE_TYPE.equals(typeName)) { - return new CalleeMethodsTreeStructure(myProject, (PsiMethod)psiElement, getCurrentScopeType()); + + @Override + protected boolean isApplicableElement(@Nonnull final PsiElement element) { + return element instanceof PsiMethod; } - else { - LOG.error("unexpected type: " + typeName); - return null; + + @Override + protected HierarchyTreeStructure createHierarchyTreeStructure(@Nonnull final String typeName, @Nonnull final PsiElement psiElement) { + if (CALLER_TYPE.equals(typeName)) { + return new CallerMethodsTreeStructure(myProject, (PsiMethod)psiElement, getCurrentScopeType()); + } + else if (CALLEE_TYPE.equals(typeName)) { + return new CalleeMethodsTreeStructure(myProject, (PsiMethod)psiElement, getCurrentScopeType()); + } + else { + LOG.error("unexpected type: " + typeName); + return null; + } } - } - @Override - protected Comparator getComparator() { - return JavaHierarchyUtil.getComparator(myProject); - } + @Override + protected Comparator getComparator() { + return JavaHierarchyUtil.getComparator(myProject); + } - public static final class BaseOnThisMethodAction extends CallHierarchyBrowserBase.BaseOnThisMethodAction { - } + public static final class BaseOnThisMethodAction extends CallHierarchyBrowserBase.BaseOnThisMethodAction { + } } diff --git a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/call/CallHierarchyNodeDescriptor.java b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/call/CallHierarchyNodeDescriptor.java index e0e5eecb72..2745470baf 100644 --- a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/call/CallHierarchyNodeDescriptor.java +++ b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/call/CallHierarchyNodeDescriptor.java @@ -59,203 +59,226 @@ import java.util.List; public final class CallHierarchyNodeDescriptor extends HierarchyNodeDescriptor implements Navigatable { - private int myUsageCount = 1; - private final List myReferences = new ArrayList(); - private final boolean myNavigateToReference; + private int myUsageCount = 1; + private final List myReferences = new ArrayList(); + private final boolean myNavigateToReference; - public CallHierarchyNodeDescriptor(@Nonnull Project project, final HierarchyNodeDescriptor parentDescriptor, @Nonnull PsiElement element, final boolean isBase, final boolean navigateToReference) { - super(project, parentDescriptor, element, isBase); - myNavigateToReference = navigateToReference; - } - - /** - * @return PsiMethod or PsiClass or JspFile - */ - public final PsiMember getEnclosingElement() { - PsiElement element = getPsiElement(); - return element == null ? null : getEnclosingElement(element); - } - - public static PsiMember getEnclosingElement(final PsiElement element) { - return PsiTreeUtil.getNonStrictParentOfType(element, PsiMethod.class, PsiClass.class); - } + public CallHierarchyNodeDescriptor( + @Nonnull Project project, + final HierarchyNodeDescriptor parentDescriptor, + @Nonnull PsiElement element, + final boolean isBase, + final boolean navigateToReference + ) { + super(project, parentDescriptor, element, isBase); + myNavigateToReference = navigateToReference; + } - public final void incrementUsageCount() { - myUsageCount++; - } + /** + * @return PsiMethod or PsiClass or JspFile + */ + public final PsiMember getEnclosingElement() { + PsiElement element = getPsiElement(); + return element == null ? null : getEnclosingElement(element); + } - /** - * Element for OpenFileDescriptor - */ - public final PsiElement getTargetElement() { - return getPsiElement(); - } + public static PsiMember getEnclosingElement(final PsiElement element) { + return PsiTreeUtil.getNonStrictParentOfType(element, PsiMethod.class, PsiClass.class); + } - @Override - public final boolean isValid() { - return getEnclosingElement() != null; - } + public final void incrementUsageCount() { + myUsageCount++; + } - @Override - @RequiredUIAccess - public final boolean update() { - final CompositeAppearance oldText = myHighlightedText; - final Icon oldIcon = TargetAWT.to(getIcon()); + /** + * Element for OpenFileDescriptor + */ + public final PsiElement getTargetElement() { + return getPsiElement(); + } - int flags = Iconable.ICON_FLAG_VISIBILITY; - if (isMarkReadOnly()) { - flags |= Iconable.ICON_FLAG_READ_STATUS; + @Override + public final boolean isValid() { + return getEnclosingElement() != null; } - boolean changes = super.update(); + @Override + @RequiredUIAccess + public final boolean update() { + final CompositeAppearance oldText = myHighlightedText; + final Icon oldIcon = TargetAWT.to(getIcon()); - final PsiElement enclosingElement = getEnclosingElement(); + int flags = Iconable.ICON_FLAG_VISIBILITY; + if (isMarkReadOnly()) { + flags |= Iconable.ICON_FLAG_READ_STATUS; + } - if (enclosingElement == null) { - final String invalidPrefix = IdeLocalize.nodeHierarchyInvalid().get(); - if (!myHighlightedText.getText().startsWith(invalidPrefix)) { - myHighlightedText.getBeginning().addText(invalidPrefix, HierarchyNodeDescriptor.getInvalidPrefixAttributes()); - } - return true; - } + boolean changes = super.update(); - Image newIcon = IconDescriptorUpdaters.getIcon(enclosingElement, flags); - if (changes && myIsBase) { - newIcon = ImageEffects.appendRight(AllIcons.Hierarchy.Base, newIcon); - } - setIcon(newIcon); + final PsiElement enclosingElement = getEnclosingElement(); - myHighlightedText = new CompositeAppearance(); - TextAttributes mainTextAttributes = null; - if (myColor != null) { - mainTextAttributes = new TextAttributes(myColor, null, null, null, Font.PLAIN); - } - if (enclosingElement instanceof PsiMethod) { - if (enclosingElement instanceof SyntheticElement) { - PsiFile file = enclosingElement.getContainingFile(); - myHighlightedText.getEnding().addText( - file != null ? file.getName() : IdeLocalize.nodeCallHierarchyUnknownJsp().get(), - mainTextAttributes - ); - } else { - final PsiMethod method = (PsiMethod) enclosingElement; - final StringBuilder buffer = new StringBuilder(128); - final PsiClass containingClass = method.getContainingClass(); - if (containingClass != null) { - buffer.append(ClassPresentationUtil.getNameForClass(containingClass, false)); - buffer.append('.'); + if (enclosingElement == null) { + final String invalidPrefix = IdeLocalize.nodeHierarchyInvalid().get(); + if (!myHighlightedText.getText().startsWith(invalidPrefix)) { + myHighlightedText.getBeginning().addText(invalidPrefix, HierarchyNodeDescriptor.getInvalidPrefixAttributes()); + } + return true; } - final String methodText = PsiFormatUtil.formatMethod(method, PsiSubstitutor.EMPTY, PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_PARAMETERS, PsiFormatUtilBase.SHOW_TYPE); - buffer.append(methodText); - myHighlightedText.getEnding().addText(buffer.toString(), mainTextAttributes); - } - } else { - myHighlightedText.getEnding().addText(ClassPresentationUtil.getNameForClass((PsiClass) enclosingElement, false), mainTextAttributes); - } - - if (myUsageCount > 1) { - myHighlightedText.getEnding().addText( - IdeLocalize.nodeCallHierarchyNUsages(myUsageCount).get(), - HierarchyNodeDescriptor.getUsageCountPrefixAttributes() - ); - } + Image newIcon = IconDescriptorUpdaters.getIcon(enclosingElement, flags); + if (changes && myIsBase) { + newIcon = ImageEffects.appendRight(AllIcons.Hierarchy.Base, newIcon); + } + setIcon(newIcon); - final PsiClass containingClass = enclosingElement instanceof PsiMethod method ? method.getContainingClass() : (PsiClass) enclosingElement; - if (containingClass != null) { - final String packageName = JavaHierarchyUtil.getPackageName(containingClass); - myHighlightedText.getEnding().addText(" (" + packageName + ")", HierarchyNodeDescriptor.getPackageNameAttributes()); - } + myHighlightedText = new CompositeAppearance(); + TextAttributes mainTextAttributes = null; + if (myColor != null) { + mainTextAttributes = new TextAttributes(myColor, null, null, null, Font.PLAIN); + } + if (enclosingElement instanceof PsiMethod) { + if (enclosingElement instanceof SyntheticElement) { + PsiFile file = enclosingElement.getContainingFile(); + myHighlightedText.getEnding().addText( + file != null ? file.getName() : IdeLocalize.nodeCallHierarchyUnknownJsp().get(), + mainTextAttributes + ); + } + else { + final PsiMethod method = (PsiMethod)enclosingElement; + final StringBuilder buffer = new StringBuilder(128); + final PsiClass containingClass = method.getContainingClass(); + if (containingClass != null) { + buffer.append(ClassPresentationUtil.getNameForClass(containingClass, false)); + buffer.append('.'); + } + final String methodText = PsiFormatUtil.formatMethod( + method, + PsiSubstitutor.EMPTY, + PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_PARAMETERS, + PsiFormatUtilBase.SHOW_TYPE + ); + buffer.append(methodText); - myName = myHighlightedText.getText(); + myHighlightedText.getEnding().addText(buffer.toString(), mainTextAttributes); + } + } + else { + myHighlightedText.getEnding() + .addText(ClassPresentationUtil.getNameForClass((PsiClass)enclosingElement, false), mainTextAttributes); + } - if (!Comparing.equal(myHighlightedText, oldText) || !Comparing.equal(getIcon(), oldIcon)) { - changes = true; - } - return changes; - } + if (myUsageCount > 1) { + myHighlightedText.getEnding().addText( + IdeLocalize.nodeCallHierarchyNUsages(myUsageCount).get(), + HierarchyNodeDescriptor.getUsageCountPrefixAttributes() + ); + } - public void addReference(final PsiReference reference) { - myReferences.add(reference); - } + final PsiClass containingClass = + enclosingElement instanceof PsiMethod method ? method.getContainingClass() : (PsiClass)enclosingElement; + if (containingClass != null) { + final String packageName = JavaHierarchyUtil.getPackageName(containingClass); + myHighlightedText.getEnding().addText(" (" + packageName + ")", HierarchyNodeDescriptor.getPackageNameAttributes()); + } - public boolean hasReference(PsiReference reference) { - return myReferences.contains(reference); - } + myName = myHighlightedText.getText(); - @Override - @RequiredReadAction - public void navigate(boolean requestFocus) { - if (!myNavigateToReference) { - PsiElement element = getPsiElement(); - if (element instanceof Navigatable navigatable && navigatable.canNavigate()) { - navigatable.navigate(requestFocus); - } - return; + if (!Comparing.equal(myHighlightedText, oldText) || !Comparing.equal(getIcon(), oldIcon)) { + changes = true; + } + return changes; } - final PsiReference firstReference = myReferences.get(0); - final PsiElement element = firstReference.getElement(); - if (element == null) { - return; + public void addReference(final PsiReference reference) { + myReferences.add(reference); } - final PsiElement callElement = element.getParent(); - if (callElement instanceof Navigatable navigatable && navigatable.canNavigate()) { - navigatable.navigate(requestFocus); - } else { - final PsiFile psiFile = callElement.getContainingFile(); - if (psiFile == null || psiFile.getVirtualFile() == null) { - return; - } - FileEditorManager.getInstance(getProject()).openFile(psiFile.getVirtualFile(), requestFocus); + + public boolean hasReference(PsiReference reference) { + return myReferences.contains(reference); } - Editor editor = PsiUtilBase.findEditor(callElement); + @Override + @RequiredReadAction + public void navigate(boolean requestFocus) { + if (!myNavigateToReference) { + PsiElement element = getPsiElement(); + if (element instanceof Navigatable navigatable && navigatable.canNavigate()) { + navigatable.navigate(requestFocus); + } + return; + } + + final PsiReference firstReference = myReferences.get(0); + final PsiElement element = firstReference.getElement(); + if (element == null) { + return; + } + final PsiElement callElement = element.getParent(); + if (callElement instanceof Navigatable navigatable && navigatable.canNavigate()) { + navigatable.navigate(requestFocus); + } + else { + final PsiFile psiFile = callElement.getContainingFile(); + if (psiFile == null || psiFile.getVirtualFile() == null) { + return; + } + FileEditorManager.getInstance(getProject()).openFile(psiFile.getVirtualFile(), requestFocus); + } + + Editor editor = PsiUtilBase.findEditor(callElement); - if (editor != null) { + if (editor != null) { - HighlightManager highlightManager = HighlightManager.getInstance(getProject()); - EditorColorsManager colorManager = EditorColorsManager.getInstance(); - TextAttributes attributes = colorManager.getGlobalScheme().getAttributes(EditorColors.SEARCH_RESULT_ATTRIBUTES); - ArrayList highlighters = new ArrayList<>(); - for (PsiReference psiReference : myReferences) { - final PsiElement eachElement = psiReference.getElement(); - if (eachElement != null) { - final PsiElement eachMethodCall = eachElement.getParent(); - if (eachMethodCall != null) { - final TextRange textRange = eachMethodCall.getTextRange(); - highlightManager.addRangeHighlight(editor, textRange.getStartOffset(), textRange.getEndOffset(), attributes, false, highlighters); - } + HighlightManager highlightManager = HighlightManager.getInstance(getProject()); + EditorColorsManager colorManager = EditorColorsManager.getInstance(); + TextAttributes attributes = colorManager.getGlobalScheme().getAttributes(EditorColors.SEARCH_RESULT_ATTRIBUTES); + ArrayList highlighters = new ArrayList<>(); + for (PsiReference psiReference : myReferences) { + final PsiElement eachElement = psiReference.getElement(); + if (eachElement != null) { + final PsiElement eachMethodCall = eachElement.getParent(); + if (eachMethodCall != null) { + final TextRange textRange = eachMethodCall.getTextRange(); + highlightManager.addRangeHighlight( + editor, + textRange.getStartOffset(), + textRange.getEndOffset(), + attributes, + false, + highlighters + ); + } + } + } } - } } - } - @Override - public boolean canNavigate() { - if (!myNavigateToReference) { - PsiElement element = getPsiElement(); - return element instanceof Navigatable navigatable && navigatable.canNavigate(); - } - if (myReferences.isEmpty()) { - return false; - } - final PsiReference firstReference = myReferences.get(0); - final PsiElement callElement = firstReference.getElement().getParent(); - if (callElement == null || !callElement.isValid()) { - return false; - } - if (!(callElement instanceof Navigatable navigatable && navigatable.canNavigate())) { - final PsiFile psiFile = callElement.getContainingFile(); - if (psiFile == null) { - return false; - } + @Override + public boolean canNavigate() { + if (!myNavigateToReference) { + PsiElement element = getPsiElement(); + return element instanceof Navigatable navigatable && navigatable.canNavigate(); + } + if (myReferences.isEmpty()) { + return false; + } + final PsiReference firstReference = myReferences.get(0); + final PsiElement callElement = firstReference.getElement().getParent(); + if (callElement == null || !callElement.isValid()) { + return false; + } + if (!(callElement instanceof Navigatable navigatable && navigatable.canNavigate())) { + final PsiFile psiFile = callElement.getContainingFile(); + if (psiFile == null) { + return false; + } + } + return true; } - return true; - } - @Override - public boolean canNavigateToSource() { - return canNavigate(); - } + @Override + public boolean canNavigateToSource() { + return canNavigate(); + } } diff --git a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/call/CalleeMethodsTreeStructure.java b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/call/CalleeMethodsTreeStructure.java index 8265c3832f..675347094a 100644 --- a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/call/CalleeMethodsTreeStructure.java +++ b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/call/CalleeMethodsTreeStructure.java @@ -27,92 +27,96 @@ import java.util.HashMap; public final class CalleeMethodsTreeStructure extends HierarchyTreeStructure { - private final String myScopeType; - - /** - * Should be called in read action - */ - public CalleeMethodsTreeStructure(final Project project, final PsiMethod method, final String scopeType) { - super(project, new CallHierarchyNodeDescriptor(project, null, method, true, false)); - myScopeType = scopeType; - } - - protected final Object[] buildChildren(final HierarchyNodeDescriptor descriptor) { - final PsiMember enclosingElement = ((CallHierarchyNodeDescriptor)descriptor).getEnclosingElement(); - if (!(enclosingElement instanceof PsiMethod)) { - return ArrayUtil.EMPTY_OBJECT_ARRAY; + private final String myScopeType; + + /** + * Should be called in read action + */ + public CalleeMethodsTreeStructure(final Project project, final PsiMethod method, final String scopeType) { + super(project, new CallHierarchyNodeDescriptor(project, null, method, true, false)); + myScopeType = scopeType; } - final PsiMethod method = (PsiMethod)enclosingElement; - final ArrayList methods = new ArrayList(); + protected final Object[] buildChildren(final HierarchyNodeDescriptor descriptor) { + final PsiMember enclosingElement = ((CallHierarchyNodeDescriptor)descriptor).getEnclosingElement(); + if (!(enclosingElement instanceof PsiMethod)) { + return ArrayUtil.EMPTY_OBJECT_ARRAY; + } + final PsiMethod method = (PsiMethod)enclosingElement; - final PsiCodeBlock body = method.getBody(); - if (body != null) { - visitor(body, methods); - } + final ArrayList methods = new ArrayList(); - final PsiMethod baseMethod = (PsiMethod)((CallHierarchyNodeDescriptor)getBaseDescriptor()).getTargetElement(); - final PsiClass baseClass = baseMethod.getContainingClass(); + final PsiCodeBlock body = method.getBody(); + if (body != null) { + visitor(body, methods); + } - final HashMap methodToDescriptorMap = new HashMap(); + final PsiMethod baseMethod = (PsiMethod)((CallHierarchyNodeDescriptor)getBaseDescriptor()).getTargetElement(); + final PsiClass baseClass = baseMethod.getContainingClass(); - final ArrayList result = new ArrayList(); + final HashMap methodToDescriptorMap = new HashMap(); - for (final PsiMethod calledMethod : methods) { - if (!isInScope(baseClass, calledMethod, myScopeType)) continue; + final ArrayList result = new ArrayList(); - CallHierarchyNodeDescriptor d = methodToDescriptorMap.get(calledMethod); - if (d == null) { - d = new CallHierarchyNodeDescriptor(myProject, descriptor, calledMethod, false, false); - methodToDescriptorMap.put(calledMethod, d); - result.add(d); - } - else { - d.incrementUsageCount(); - } - } + for (final PsiMethod calledMethod : methods) { + if (!isInScope(baseClass, calledMethod, myScopeType)) { + continue; + } - // also add overriding methods as children - final PsiMethod[] overridingMethods = OverridingMethodsSearch.search(method, true).toArray(PsiMethod.EMPTY_ARRAY); - for (final PsiMethod overridingMethod : overridingMethods) { - if (!isInScope(baseClass, overridingMethod, myScopeType)) continue; - final CallHierarchyNodeDescriptor node = new CallHierarchyNodeDescriptor(myProject, descriptor, overridingMethod, false, false); - if (!result.contains(node)) result.add(node); - } - -/* - // show method implementations in EJB Class - final PsiMethod[] ejbImplementations = EjbUtil.findEjbImplementations(method, null); - for (int i = 0; i < ejbImplementations.length; i++) { - PsiMethod ejbImplementation = ejbImplementations[i]; - result.add(new CallHierarchyNodeDescriptor(myProject, descriptor, ejbImplementation, false)); - } -*/ - return ArrayUtil.toObjectArray(result); - } + CallHierarchyNodeDescriptor d = methodToDescriptorMap.get(calledMethod); + if (d == null) { + d = new CallHierarchyNodeDescriptor(myProject, descriptor, calledMethod, false, false); + methodToDescriptorMap.put(calledMethod, d); + result.add(d); + } + else { + d.incrementUsageCount(); + } + } + // also add overriding methods as children + final PsiMethod[] overridingMethods = OverridingMethodsSearch.search(method, true).toArray(PsiMethod.EMPTY_ARRAY); + for (final PsiMethod overridingMethod : overridingMethods) { + if (!isInScope(baseClass, overridingMethod, myScopeType)) { + continue; + } + final CallHierarchyNodeDescriptor node = new CallHierarchyNodeDescriptor(myProject, descriptor, overridingMethod, false, false); + if (!result.contains(node)) { + result.add(node); + } + } + /* + // show method implementations in EJB Class + final PsiMethod[] ejbImplementations = EjbUtil.findEjbImplementations(method, null); + for (int i = 0; i < ejbImplementations.length; i++) { + PsiMethod ejbImplementation = ejbImplementations[i]; + result.add(new CallHierarchyNodeDescriptor(myProject, descriptor, ejbImplementation, false)); + } + */ + return ArrayUtil.toObjectArray(result); + } - private static void visitor(final PsiElement element, final ArrayList methods) { - final PsiElement[] children = element.getChildren(); - for (final PsiElement child : children) { - visitor(child, methods); - if (child instanceof PsiMethodCallExpression) { - final PsiMethodCallExpression callExpression = (PsiMethodCallExpression)child; - final PsiReferenceExpression methodExpression = callExpression.getMethodExpression(); - final PsiMethod method = (PsiMethod)methodExpression.resolve(); - if (method != null) { - methods.add(method); - } - } - else if (child instanceof PsiNewExpression) { - final PsiNewExpression newExpression = (PsiNewExpression)child; - final PsiMethod method = newExpression.resolveConstructor(); - if (method != null) { - methods.add(method); + private static void visitor(final PsiElement element, final ArrayList methods) { + final PsiElement[] children = element.getChildren(); + for (final PsiElement child : children) { + visitor(child, methods); + if (child instanceof PsiMethodCallExpression) { + final PsiMethodCallExpression callExpression = (PsiMethodCallExpression)child; + final PsiReferenceExpression methodExpression = callExpression.getMethodExpression(); + final PsiMethod method = (PsiMethod)methodExpression.resolve(); + if (method != null) { + methods.add(method); + } + } + else if (child instanceof PsiNewExpression) { + final PsiNewExpression newExpression = (PsiNewExpression)child; + final PsiMethod method = newExpression.resolveConstructor(); + if (method != null) { + methods.add(method); + } + } } - } } - } } diff --git a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/call/CallerMethodsTreeStructure.java b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/call/CallerMethodsTreeStructure.java index e86dd15f4b..46e25c560f 100644 --- a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/call/CallerMethodsTreeStructure.java +++ b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/call/CallerMethodsTreeStructure.java @@ -34,108 +34,108 @@ import java.util.Set; public final class CallerMethodsTreeStructure extends HierarchyTreeStructure { - private final String myScopeType; + private final String myScopeType; - /** - * Should be called in read action - */ - public CallerMethodsTreeStructure(final Project project, final PsiMethod method, final String scopeType) { - super(project, new CallHierarchyNodeDescriptor(project, null, method, true, false)); - myScopeType = scopeType; - } - - @Override - protected final Object[] buildChildren(final HierarchyNodeDescriptor descriptor) { - final PsiMember enclosingElement = ((CallHierarchyNodeDescriptor)descriptor).getEnclosingElement(); - HierarchyNodeDescriptor nodeDescriptor = getBaseDescriptor(); - if (!(enclosingElement instanceof PsiMethod) || nodeDescriptor == null) { - return ArrayUtil.EMPTY_OBJECT_ARRAY; + /** + * Should be called in read action + */ + public CallerMethodsTreeStructure(final Project project, final PsiMethod method, final String scopeType) { + super(project, new CallHierarchyNodeDescriptor(project, null, method, true, false)); + myScopeType = scopeType; } - final PsiMethod method = (PsiMethod)enclosingElement; - final PsiMethod baseMethod = (PsiMethod)((CallHierarchyNodeDescriptor)nodeDescriptor).getTargetElement(); - final SearchScope searchScope = getSearchScope(myScopeType, baseMethod.getContainingClass()); - final PsiClass originalClass = method.getContainingClass(); - assert originalClass != null; - final PsiClassType originalType = JavaPsiFacade.getElementFactory(myProject).createType(originalClass); - final Set methodsToFind = new HashSet(); - methodsToFind.add(method); - ContainerUtil.addAll(methodsToFind, method.findDeepestSuperMethods()); + @Override + protected final Object[] buildChildren(final HierarchyNodeDescriptor descriptor) { + final PsiMember enclosingElement = ((CallHierarchyNodeDescriptor)descriptor).getEnclosingElement(); + HierarchyNodeDescriptor nodeDescriptor = getBaseDescriptor(); + if (!(enclosingElement instanceof PsiMethod) || nodeDescriptor == null) { + return ArrayUtil.EMPTY_OBJECT_ARRAY; + } + final PsiMethod method = (PsiMethod)enclosingElement; + final PsiMethod baseMethod = (PsiMethod)((CallHierarchyNodeDescriptor)nodeDescriptor).getTargetElement(); + final SearchScope searchScope = getSearchScope(myScopeType, baseMethod.getContainingClass()); - final Map methodToDescriptorMap = new HashMap(); - for (final PsiMethod methodToFind : methodsToFind) { - MethodReferencesSearch.search(methodToFind, searchScope, true).forEach(new Processor() { - @Override - public boolean process(final PsiReference reference) { - if (reference instanceof PsiReferenceExpression) { - final PsiExpression qualifier = ((PsiReferenceExpression)reference).getQualifierExpression(); - if (qualifier instanceof PsiSuperExpression) { // filter super.foo() call inside foo() and similar cases (bug 8411) - final PsiClass superClass = PsiUtil.resolveClassInType(qualifier.getType()); - if (originalClass.isInheritor(superClass, true)) { - return true; - } - } - if (qualifier != null && !methodToFind.hasModifierProperty(PsiModifier.STATIC)) { - final PsiType qualifierType = qualifier.getType(); - if (qualifierType instanceof PsiClassType && - !TypeConversionUtil.isAssignable(qualifierType, originalType) && - methodToFind != method) { - final PsiClass psiClass = ((PsiClassType)qualifierType).resolve(); - if (psiClass != null) { - final PsiMethod callee = psiClass.findMethodBySignature(methodToFind, true); - if (callee != null && !methodsToFind.contains(callee)) { - // skip sibling methods - return true; - } - } - } - } - } - else { - if (!(reference instanceof PsiElement)) { - return true; - } + final PsiClass originalClass = method.getContainingClass(); + assert originalClass != null; + final PsiClassType originalType = JavaPsiFacade.getElementFactory(myProject).createType(originalClass); + final Set methodsToFind = new HashSet(); + methodsToFind.add(method); + ContainerUtil.addAll(methodsToFind, method.findDeepestSuperMethods()); + + final Map methodToDescriptorMap = new HashMap(); + for (final PsiMethod methodToFind : methodsToFind) { + MethodReferencesSearch.search(methodToFind, searchScope, true).forEach(new Processor() { + @Override + public boolean process(final PsiReference reference) { + if (reference instanceof PsiReferenceExpression) { + final PsiExpression qualifier = ((PsiReferenceExpression)reference).getQualifierExpression(); + if (qualifier instanceof PsiSuperExpression) { // filter super.foo() call inside foo() and similar cases (bug 8411) + final PsiClass superClass = PsiUtil.resolveClassInType(qualifier.getType()); + if (originalClass.isInheritor(superClass, true)) { + return true; + } + } + if (qualifier != null && !methodToFind.hasModifierProperty(PsiModifier.STATIC)) { + final PsiType qualifierType = qualifier.getType(); + if (qualifierType instanceof PsiClassType && + !TypeConversionUtil.isAssignable(qualifierType, originalType) && + methodToFind != method) { + final PsiClass psiClass = ((PsiClassType)qualifierType).resolve(); + if (psiClass != null) { + final PsiMethod callee = psiClass.findMethodBySignature(methodToFind, true); + if (callee != null && !methodsToFind.contains(callee)) { + // skip sibling methods + return true; + } + } + } + } + } + else { + if (!(reference instanceof PsiElement)) { + return true; + } - final PsiElement parent = ((PsiElement)reference).getParent(); - if (parent instanceof PsiNewExpression) { - if (((PsiNewExpression)parent).getClassReference() != reference) { - return true; - } - } - else if (parent instanceof PsiAnonymousClass) { - if (((PsiAnonymousClass)parent).getBaseClassReference() != reference) { - return true; - } - } - else { - return true; - } - } + final PsiElement parent = ((PsiElement)reference).getParent(); + if (parent instanceof PsiNewExpression) { + if (((PsiNewExpression)parent).getClassReference() != reference) { + return true; + } + } + else if (parent instanceof PsiAnonymousClass) { + if (((PsiAnonymousClass)parent).getBaseClassReference() != reference) { + return true; + } + } + else { + return true; + } + } - final PsiElement element = reference.getElement(); - final PsiMember key = CallHierarchyNodeDescriptor.getEnclosingElement(element); + final PsiElement element = reference.getElement(); + final PsiMember key = CallHierarchyNodeDescriptor.getEnclosingElement(element); - synchronized (methodToDescriptorMap) { - CallHierarchyNodeDescriptor d = methodToDescriptorMap.get(key); - if (d == null) { - d = new CallHierarchyNodeDescriptor(myProject, descriptor, element, false, true); - methodToDescriptorMap.put(key, d); - } - else if (!d.hasReference(reference)) { - d.incrementUsageCount(); - } - d.addReference(reference); - } - return true; + synchronized (methodToDescriptorMap) { + CallHierarchyNodeDescriptor d = methodToDescriptorMap.get(key); + if (d == null) { + d = new CallHierarchyNodeDescriptor(myProject, descriptor, element, false, true); + methodToDescriptorMap.put(key, d); + } + else if (!d.hasReference(reference)) { + d.incrementUsageCount(); + } + d.addReference(reference); + } + return true; + } + }); } - }); - } - return methodToDescriptorMap.values().toArray(new Object[methodToDescriptorMap.size()]); - } + return methodToDescriptorMap.values().toArray(new Object[methodToDescriptorMap.size()]); + } - @Override - public boolean isAlwaysShowPlus() { - return true; - } + @Override + public boolean isAlwaysShowPlus() { + return true; + } } diff --git a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/call/JavaCallHierarchyProvider.java b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/call/JavaCallHierarchyProvider.java index db02a622bf..ae18053009 100644 --- a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/call/JavaCallHierarchyProvider.java +++ b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/call/JavaCallHierarchyProvider.java @@ -34,29 +34,31 @@ */ @ExtensionImpl public class JavaCallHierarchyProvider implements CallHierarchyProvider { - @Override - public PsiElement getTarget(@Nonnull final DataContext dataContext) { - final Project project = dataContext.getData(Project.KEY); - if (project == null) return null; + @Override + public PsiElement getTarget(@Nonnull final DataContext dataContext) { + final Project project = dataContext.getData(Project.KEY); + if (project == null) { + return null; + } - final PsiElement element = dataContext.getData(PsiElement.KEY); - return PsiTreeUtil.getParentOfType(element, PsiMethod.class, false); - } + final PsiElement element = dataContext.getData(PsiElement.KEY); + return PsiTreeUtil.getParentOfType(element, PsiMethod.class, false); + } - @Override - @Nonnull - public HierarchyBrowser createHierarchyBrowser(final PsiElement target) { - return new CallHierarchyBrowser(target.getProject(), (PsiMethod) target); - } + @Override + @Nonnull + public HierarchyBrowser createHierarchyBrowser(final PsiElement target) { + return new CallHierarchyBrowser(target.getProject(), (PsiMethod)target); + } - @Override - public void browserActivated(@Nonnull final HierarchyBrowser hierarchyBrowser) { - ((CallHierarchyBrowser) hierarchyBrowser).changeView(CallHierarchyBrowserBase.CALLER_TYPE); - } + @Override + public void browserActivated(@Nonnull final HierarchyBrowser hierarchyBrowser) { + ((CallHierarchyBrowser)hierarchyBrowser).changeView(CallHierarchyBrowserBase.CALLER_TYPE); + } - @Nonnull - @Override - public Language getLanguage() { - return JavaLanguage.INSTANCE; - } + @Nonnull + @Override + public Language getLanguage() { + return JavaLanguage.INSTANCE; + } } diff --git a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/ImplementMethodAction.java b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/ImplementMethodAction.java index 157b749d74..fcd731a647 100644 --- a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/ImplementMethodAction.java +++ b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/ImplementMethodAction.java @@ -19,15 +19,15 @@ import consulo.ui.ex.action.Presentation; public final class ImplementMethodAction extends OverrideImplementMethodAction { - protected final void update(final Presentation presentation, final int toImplement, final int toOverride) { - if (toImplement > 0) { - presentation.setEnabled(true); - presentation.setVisible(true); - presentation.setTextValue(toImplement == 1 ? IdeLocalize.actionImplementMethod() : IdeLocalize.actionImplementMethods()); + protected final void update(final Presentation presentation, final int toImplement, final int toOverride) { + if (toImplement > 0) { + presentation.setEnabled(true); + presentation.setVisible(true); + presentation.setTextValue(toImplement == 1 ? IdeLocalize.actionImplementMethod() : IdeLocalize.actionImplementMethods()); + } + else { + presentation.setEnabled(false); + presentation.setVisible(false); + } } - else { - presentation.setEnabled(false); - presentation.setVisible(false); - } - } } diff --git a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/JavaMethodHierarchyProvider.java b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/JavaMethodHierarchyProvider.java index b9076cd24e..65b4d12da0 100644 --- a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/JavaMethodHierarchyProvider.java +++ b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/JavaMethodHierarchyProvider.java @@ -43,75 +43,76 @@ */ @ExtensionImpl public class JavaMethodHierarchyProvider implements MethodHierarchyProvider { - @RequiredReadAction - public PsiElement getTarget(@Nonnull final DataContext dataContext) { - final PsiMethod method = getMethodImpl(dataContext); - if (method != null && method.getContainingClass() != null && !method.hasModifierProperty(PsiModifier.PRIVATE) - && !method.hasModifierProperty(PsiModifier.STATIC)) { - return method; - } else { - return null; - } - } - - @RequiredReadAction - @Nullable - private static PsiMethod getMethodImpl(final DataContext dataContext) { - final Project project = dataContext.getData(Project.KEY); - if (project == null) { - return null; - } - - PsiElement element = dataContext.getData(PsiElement.KEY); - final PsiMethod method = PsiTreeUtil.getParentOfType(element, PsiMethod.class, false); - - if (method != null) { - return method; + @RequiredReadAction + public PsiElement getTarget(@Nonnull final DataContext dataContext) { + final PsiMethod method = getMethodImpl(dataContext); + if (method != null && method.getContainingClass() != null && !method.hasModifierProperty(PsiModifier.PRIVATE) + && !method.hasModifierProperty(PsiModifier.STATIC)) { + return method; + } + else { + return null; + } } - final Editor editor = dataContext.getData(Editor.KEY); - if (editor == null) { - return null; + @RequiredReadAction + @Nullable + private static PsiMethod getMethodImpl(final DataContext dataContext) { + final Project project = dataContext.getData(Project.KEY); + if (project == null) { + return null; + } + + PsiElement element = dataContext.getData(PsiElement.KEY); + final PsiMethod method = PsiTreeUtil.getParentOfType(element, PsiMethod.class, false); + + if (method != null) { + return method; + } + + final Editor editor = dataContext.getData(Editor.KEY); + if (editor == null) { + return null; + } + + final PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); + if (psiFile == null) { + return null; + } + + PsiDocumentManager.getInstance(project).commitAllDocuments(); + + final int offset = editor.getCaretModel().getOffset(); + if (offset < 1) { + return null; + } + + element = psiFile.findElementAt(offset); + if (!(element instanceof PsiWhiteSpace)) { + return null; + } + + element = psiFile.findElementAt(offset - 1); + if (!(element instanceof PsiJavaToken javaToken && javaToken.getTokenType() == JavaTokenType.SEMICOLON)) { + return null; + } + + return PsiTreeUtil.getParentOfType(element, PsiMethod.class, false); } - final PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); - if (psiFile == null) { - return null; + @Nonnull + public HierarchyBrowser createHierarchyBrowser(final PsiElement target) { + return new MethodHierarchyBrowser(target.getProject(), (PsiMethod)target); } - PsiDocumentManager.getInstance(project).commitAllDocuments(); - - final int offset = editor.getCaretModel().getOffset(); - if (offset < 1) { - return null; + @RequiredReadAction + public void browserActivated(@Nonnull final HierarchyBrowser hierarchyBrowser) { + ((MethodHierarchyBrowser)hierarchyBrowser).changeView(MethodHierarchyBrowserBase.METHOD_TYPE); } - element = psiFile.findElementAt(offset); - if (!(element instanceof PsiWhiteSpace)) { - return null; + @Nonnull + @Override + public Language getLanguage() { + return JavaLanguage.INSTANCE; } - - element = psiFile.findElementAt(offset - 1); - if (!(element instanceof PsiJavaToken javaToken && javaToken.getTokenType() == JavaTokenType.SEMICOLON)) { - return null; - } - - return PsiTreeUtil.getParentOfType(element, PsiMethod.class, false); - } - - @Nonnull - public HierarchyBrowser createHierarchyBrowser(final PsiElement target) { - return new MethodHierarchyBrowser(target.getProject(), (PsiMethod) target); - } - - @RequiredReadAction - public void browserActivated(@Nonnull final HierarchyBrowser hierarchyBrowser) { - ((MethodHierarchyBrowser) hierarchyBrowser).changeView(MethodHierarchyBrowserBase.METHOD_TYPE); - } - - @Nonnull - @Override - public Language getLanguage() { - return JavaLanguage.INSTANCE; - } } diff --git a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/MethodHierarchyBrowser.java b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/MethodHierarchyBrowser.java index da1d1dd131..7ceab713d5 100644 --- a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/MethodHierarchyBrowser.java +++ b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/MethodHierarchyBrowser.java @@ -38,61 +38,61 @@ import java.util.Map; public class MethodHierarchyBrowser extends MethodHierarchyBrowserBase { - private static final Logger LOG = Logger.getInstance(MethodHierarchyBrowser.class); - - public MethodHierarchyBrowser(final Project project, final PsiMethod method) { - super(project, method); - } - - protected void createTrees(@Nonnull Map trees) { - final JTree tree = createTree(false); - ActionGroup group = (ActionGroup)ActionManager.getInstance().getAction(IdeActions.GROUP_METHOD_HIERARCHY_POPUP); - PopupHandler.installPopupHandler(tree, group, ActionPlaces.METHOD_HIERARCHY_VIEW_POPUP, ActionManager.getInstance()); - - final BaseOnThisMethodAction baseOnThisMethodAction = new BaseOnThisMethodAction(); - baseOnThisMethodAction - .registerCustomShortcutSet(ActionManager.getInstance().getAction(IdeActions.ACTION_METHOD_HIERARCHY).getShortcutSet(), tree); - - trees.put(METHOD_TYPE, tree); - } - - protected JPanel createLegendPanel() { - return createStandardLegendPanel( - IdeLocalize.hierarchyLegendMethodIsDefinedInClass().get(), - IdeLocalize.hierarchyLegendMethodDefinedInSuperclass().get(), - IdeLocalize.hierarchyLegendMethodShouldBeDefined().get() - ); - } - - - protected PsiElement getElementFromDescriptor(@Nonnull final HierarchyNodeDescriptor descriptor) { - return descriptor instanceof MethodHierarchyNodeDescriptor methodHierarchyNodeDescriptor - ? methodHierarchyNodeDescriptor.getTargetElement() : null; - } - - protected boolean isApplicableElement(@Nonnull final PsiElement psiElement) { - return psiElement instanceof PsiMethod; - } - - protected HierarchyTreeStructure createHierarchyTreeStructure(@Nonnull final String typeName, @Nonnull final PsiElement psiElement) { - if (!METHOD_TYPE.equals(typeName)) { - LOG.error("unexpected type: " + typeName); - return null; + private static final Logger LOG = Logger.getInstance(MethodHierarchyBrowser.class); + + public MethodHierarchyBrowser(final Project project, final PsiMethod method) { + super(project, method); } - return new MethodHierarchyTreeStructure(myProject, (PsiMethod)psiElement); - } - protected Comparator getComparator() { - return JavaHierarchyUtil.getComparator(myProject); - } + protected void createTrees(@Nonnull Map trees) { + final JTree tree = createTree(false); + ActionGroup group = (ActionGroup)ActionManager.getInstance().getAction(IdeActions.GROUP_METHOD_HIERARCHY_POPUP); + PopupHandler.installPopupHandler(tree, group, ActionPlaces.METHOD_HIERARCHY_VIEW_POPUP, ActionManager.getInstance()); + + final BaseOnThisMethodAction baseOnThisMethodAction = new BaseOnThisMethodAction(); + baseOnThisMethodAction + .registerCustomShortcutSet(ActionManager.getInstance().getAction(IdeActions.ACTION_METHOD_HIERARCHY).getShortcutSet(), tree); - public PsiMethod getBaseMethod() { - final HierarchyTreeBuilder builder = myBuilders.get(myCurrentViewType); - final MethodHierarchyTreeStructure treeStructure = (MethodHierarchyTreeStructure)builder.getTreeStructure(); - return treeStructure.getBaseMethod(); - } + trees.put(METHOD_TYPE, tree); + } + + protected JPanel createLegendPanel() { + return createStandardLegendPanel( + IdeLocalize.hierarchyLegendMethodIsDefinedInClass().get(), + IdeLocalize.hierarchyLegendMethodDefinedInSuperclass().get(), + IdeLocalize.hierarchyLegendMethodShouldBeDefined().get() + ); + } - public static final class BaseOnThisMethodAction extends MethodHierarchyBrowserBase.BaseOnThisMethodAction { - } + + protected PsiElement getElementFromDescriptor(@Nonnull final HierarchyNodeDescriptor descriptor) { + return descriptor instanceof MethodHierarchyNodeDescriptor methodHierarchyNodeDescriptor + ? methodHierarchyNodeDescriptor.getTargetElement() : null; + } + + protected boolean isApplicableElement(@Nonnull final PsiElement psiElement) { + return psiElement instanceof PsiMethod; + } + + protected HierarchyTreeStructure createHierarchyTreeStructure(@Nonnull final String typeName, @Nonnull final PsiElement psiElement) { + if (!METHOD_TYPE.equals(typeName)) { + LOG.error("unexpected type: " + typeName); + return null; + } + return new MethodHierarchyTreeStructure(myProject, (PsiMethod)psiElement); + } + + protected Comparator getComparator() { + return JavaHierarchyUtil.getComparator(myProject); + } + + public PsiMethod getBaseMethod() { + final HierarchyTreeBuilder builder = myBuilders.get(myCurrentViewType); + final MethodHierarchyTreeStructure treeStructure = (MethodHierarchyTreeStructure)builder.getTreeStructure(); + return treeStructure.getBaseMethod(); + } + + public static final class BaseOnThisMethodAction extends MethodHierarchyBrowserBase.BaseOnThisMethodAction { + } } diff --git a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/MethodHierarchyNodeDescriptor.java b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/MethodHierarchyNodeDescriptor.java index 2acc7a54a5..3aa4165dc8 100644 --- a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/MethodHierarchyNodeDescriptor.java +++ b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/MethodHierarchyNodeDescriptor.java @@ -37,159 +37,138 @@ import java.awt.*; -public final class MethodHierarchyNodeDescriptor extends HierarchyNodeDescriptor -{ - private Image myRawIcon; - private Image myStateIcon; - private MethodHierarchyTreeStructure myTreeStructure; - - public MethodHierarchyNodeDescriptor( - final Project project, - final HierarchyNodeDescriptor parentDescriptor, - final PsiElement aClass, - final boolean isBase, - final MethodHierarchyTreeStructure treeStructure - ) { - super(project, parentDescriptor, aClass, isBase); - myTreeStructure = treeStructure; - } - - public final void setTreeStructure(final MethodHierarchyTreeStructure treeStructure) - { - myTreeStructure = treeStructure; - } - - PsiMethod getMethod(final PsiClass aClass, final boolean checkBases) - { - return MethodHierarchyUtil.findBaseMethodInClass(myTreeStructure.getBaseMethod(), aClass, checkBases); - } - - public final PsiElement getPsiClass() - { - return getPsiElement(); - } - - /** - * Element for OpenFileDescriptor - */ - public final PsiElement getTargetElement() - { - final PsiElement element = getPsiClass(); - if (!(element instanceof PsiClass)) - { - return element; - } - final PsiClass aClass = (PsiClass) getPsiClass(); - if (!aClass.isValid()) - { - return null; - } - final PsiMethod method = getMethod(aClass, false); - if (method != null) - { - return method; - } - return aClass; - } - - @Override - @RequiredUIAccess - public final boolean update() - { - int flags = Iconable.ICON_FLAG_VISIBILITY; - if (isMarkReadOnly()) - { - flags |= Iconable.ICON_FLAG_READ_STATUS; - } - - boolean changes = super.update(); - - final PsiElement aClass = getPsiClass(); - - if (aClass == null) - { - final String invalidPrefix = IdeLocalize.nodeHierarchyInvalid().get(); - if (!myHighlightedText.getText().startsWith(invalidPrefix)) - { - myHighlightedText.getBeginning().addText(invalidPrefix, HierarchyNodeDescriptor.getInvalidPrefixAttributes()); - } - return true; - } - - final Image newRawIcon = IconDescriptorUpdaters.getIcon(aClass, flags); - final Image newStateIcon = aClass instanceof PsiClass psiClass ? calculateState(psiClass) : AllIcons.Hierarchy.MethodDefined; - - if (changes || newRawIcon != myRawIcon || newStateIcon != myStateIcon) - { - changes = true; - - myRawIcon = newRawIcon; - myStateIcon = newStateIcon; - - Image newIcon = myRawIcon; - - if (myIsBase) - { - newIcon = ImageEffects.appendRight(AllIcons.Hierarchy.Base, newIcon); - } - - if (myStateIcon != null) - { - newIcon = ImageEffects.appendRight(myStateIcon, newIcon); - } - - setIcon(newIcon); - } - - final CompositeAppearance oldText = myHighlightedText; - - myHighlightedText = new CompositeAppearance(); - TextAttributes classNameAttributes = null; - if (myColor != null) - { - classNameAttributes = new TextAttributes(myColor, null, null, null, Font.PLAIN); - } - if (aClass instanceof PsiClass psiClass) - { - myHighlightedText.getEnding().addText(ClassPresentationUtil.getNameForClass(psiClass, false), classNameAttributes); - myHighlightedText.getEnding().addText( - " (" + JavaHierarchyUtil.getPackageName(psiClass) + ")", - HierarchyNodeDescriptor.getPackageNameAttributes() - ); - } - else if (aClass instanceof PsiFunctionalExpression functionalExpression) - { - myHighlightedText.getEnding().addText(ClassPresentationUtil.getFunctionalExpressionPresentation(functionalExpression, false)); - } - myName = myHighlightedText.getText(); - - if (!Comparing.equal(myHighlightedText, oldText)) - { - changes = true; - } - return changes; - } - - private Image calculateState(final PsiClass psiClass) - { - final PsiMethod method = getMethod(psiClass, false); - if (method != null) - { - return method.hasModifierProperty(PsiModifier.ABSTRACT) ? null : AllIcons.Hierarchy.MethodDefined; - } - - if (myTreeStructure.isSuperClassForBaseClass(psiClass)) - { - return AllIcons.Hierarchy.MethodNotDefined; - } - - final boolean isAbstractClass = psiClass.hasModifierProperty(PsiModifier.ABSTRACT); - - // was it implemented is in superclasses? - final PsiMethod baseClassMethod = getMethod(psiClass, true); - - final boolean hasBaseImplementation = baseClassMethod != null && !baseClassMethod.hasModifierProperty(PsiModifier.ABSTRACT); - - return hasBaseImplementation || isAbstractClass ? AllIcons.Hierarchy.MethodNotDefined : AllIcons.Hierarchy.ShouldDefineMethod; - } +public final class MethodHierarchyNodeDescriptor extends HierarchyNodeDescriptor { + private Image myRawIcon; + private Image myStateIcon; + private MethodHierarchyTreeStructure myTreeStructure; + + public MethodHierarchyNodeDescriptor( + final Project project, + final HierarchyNodeDescriptor parentDescriptor, + final PsiElement aClass, + final boolean isBase, + final MethodHierarchyTreeStructure treeStructure + ) { + super(project, parentDescriptor, aClass, isBase); + myTreeStructure = treeStructure; + } + + public final void setTreeStructure(final MethodHierarchyTreeStructure treeStructure) { + myTreeStructure = treeStructure; + } + + PsiMethod getMethod(final PsiClass aClass, final boolean checkBases) { + return MethodHierarchyUtil.findBaseMethodInClass(myTreeStructure.getBaseMethod(), aClass, checkBases); + } + + public final PsiElement getPsiClass() { + return getPsiElement(); + } + + /** + * Element for OpenFileDescriptor + */ + public final PsiElement getTargetElement() { + final PsiElement element = getPsiClass(); + if (!(element instanceof PsiClass)) { + return element; + } + final PsiClass aClass = (PsiClass)getPsiClass(); + if (!aClass.isValid()) { + return null; + } + final PsiMethod method = getMethod(aClass, false); + if (method != null) { + return method; + } + return aClass; + } + + @Override + @RequiredUIAccess + public final boolean update() { + int flags = Iconable.ICON_FLAG_VISIBILITY; + if (isMarkReadOnly()) { + flags |= Iconable.ICON_FLAG_READ_STATUS; + } + + boolean changes = super.update(); + + final PsiElement aClass = getPsiClass(); + + if (aClass == null) { + final String invalidPrefix = IdeLocalize.nodeHierarchyInvalid().get(); + if (!myHighlightedText.getText().startsWith(invalidPrefix)) { + myHighlightedText.getBeginning().addText(invalidPrefix, HierarchyNodeDescriptor.getInvalidPrefixAttributes()); + } + return true; + } + + final Image newRawIcon = IconDescriptorUpdaters.getIcon(aClass, flags); + final Image newStateIcon = aClass instanceof PsiClass psiClass ? calculateState(psiClass) : AllIcons.Hierarchy.MethodDefined; + + if (changes || newRawIcon != myRawIcon || newStateIcon != myStateIcon) { + changes = true; + + myRawIcon = newRawIcon; + myStateIcon = newStateIcon; + + Image newIcon = myRawIcon; + + if (myIsBase) { + newIcon = ImageEffects.appendRight(AllIcons.Hierarchy.Base, newIcon); + } + + if (myStateIcon != null) { + newIcon = ImageEffects.appendRight(myStateIcon, newIcon); + } + + setIcon(newIcon); + } + + final CompositeAppearance oldText = myHighlightedText; + + myHighlightedText = new CompositeAppearance(); + TextAttributes classNameAttributes = null; + if (myColor != null) { + classNameAttributes = new TextAttributes(myColor, null, null, null, Font.PLAIN); + } + if (aClass instanceof PsiClass psiClass) { + myHighlightedText.getEnding().addText(ClassPresentationUtil.getNameForClass(psiClass, false), classNameAttributes); + myHighlightedText.getEnding().addText( + " (" + JavaHierarchyUtil.getPackageName(psiClass) + ")", + HierarchyNodeDescriptor.getPackageNameAttributes() + ); + } + else if (aClass instanceof PsiFunctionalExpression functionalExpression) { + myHighlightedText.getEnding() + .addText(ClassPresentationUtil.getFunctionalExpressionPresentation(functionalExpression, false)); + } + myName = myHighlightedText.getText(); + + if (!Comparing.equal(myHighlightedText, oldText)) { + changes = true; + } + return changes; + } + + private Image calculateState(final PsiClass psiClass) { + final PsiMethod method = getMethod(psiClass, false); + if (method != null) { + return method.hasModifierProperty(PsiModifier.ABSTRACT) ? null : AllIcons.Hierarchy.MethodDefined; + } + + if (myTreeStructure.isSuperClassForBaseClass(psiClass)) { + return AllIcons.Hierarchy.MethodNotDefined; + } + + final boolean isAbstractClass = psiClass.hasModifierProperty(PsiModifier.ABSTRACT); + + // was it implemented is in superclasses? + final PsiMethod baseClassMethod = getMethod(psiClass, true); + + final boolean hasBaseImplementation = baseClassMethod != null && !baseClassMethod.hasModifierProperty(PsiModifier.ABSTRACT); + + return hasBaseImplementation || isAbstractClass ? AllIcons.Hierarchy.MethodNotDefined : AllIcons.Hierarchy.ShouldDefineMethod; + } } diff --git a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/MethodHierarchyTreeStructure.java b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/MethodHierarchyTreeStructure.java index bbd0ecca1b..10a04749c6 100644 --- a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/MethodHierarchyTreeStructure.java +++ b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/MethodHierarchyTreeStructure.java @@ -34,263 +34,222 @@ import consulo.java.language.module.util.JavaClassNames; import jakarta.annotation.Nullable; -public final class MethodHierarchyTreeStructure extends HierarchyTreeStructure -{ - private final SmartPsiElementPointer myMethod; - - /** - * Should be called in read action - */ - public MethodHierarchyTreeStructure(final Project project, final PsiMethod method) - { - super(project, null); - myBaseDescriptor = buildHierarchyElement(project, method); - ((MethodHierarchyNodeDescriptor) myBaseDescriptor).setTreeStructure(this); - myMethod = SmartPointerManager.getInstance(myProject).createSmartPsiElementPointer(method); - setBaseElement(myBaseDescriptor); //to set myRoot - } - - private HierarchyNodeDescriptor buildHierarchyElement(final Project project, final PsiMethod method) - { - final PsiClass suitableBaseClass = findSuitableBaseClass(method); - - HierarchyNodeDescriptor descriptor = null; - final ArrayList superClasses = createSuperClasses(suitableBaseClass); - - if(!suitableBaseClass.equals(method.getContainingClass())) - { - superClasses.add(0, suitableBaseClass); - } - - // remove from the top of the branch the classes that contain no 'method' - for(int i = superClasses.size() - 1; i >= 0; i--) - { - final PsiClass psiClass = superClasses.get(i); - - if(MethodHierarchyUtil.findBaseMethodInClass(method, psiClass, false) == null) - { - superClasses.remove(i); - } - else - { - break; - } - } - - for(int i = superClasses.size() - 1; i >= 0; i--) - { - final PsiClass superClass = superClasses.get(i); - final HierarchyNodeDescriptor newDescriptor = new MethodHierarchyNodeDescriptor(project, descriptor, superClass, false, this); - if(descriptor != null) - { - descriptor.setCachedChildren(new HierarchyNodeDescriptor[]{newDescriptor}); - } - descriptor = newDescriptor; - } - final HierarchyNodeDescriptor newDescriptor = new MethodHierarchyNodeDescriptor(project, descriptor, method.getContainingClass(), true, this); - if(descriptor != null) - { - descriptor.setCachedChildren(new HierarchyNodeDescriptor[]{newDescriptor}); - } - return newDescriptor; - } - - private static ArrayList createSuperClasses(PsiClass aClass) - { - if(!aClass.isValid()) - { - return new ArrayList(); - } - - final ArrayList superClasses = new ArrayList(); - while(!isJavaLangObject(aClass)) - { - final PsiClass aClass1 = aClass; - final PsiClass[] superTypes = aClass1.getSupers(); - PsiClass superType = null; - // find class first - for(final PsiClass type : superTypes) - { - if(!type.isInterface() && !isJavaLangObject(type)) - { - superType = type; - break; - } - } - // if we haven't found a class, try to find an interface - if(superType == null) - { - for(final PsiClass type : superTypes) - { - if(!isJavaLangObject(type)) - { - superType = type; - break; - } - } - } - if(superType == null) - { - break; - } - if(superClasses.contains(superType)) - { - break; - } - superClasses.add(superType); - aClass = superType; - } - - return superClasses; - } - - private static boolean isJavaLangObject(final PsiClass aClass) - { - return JavaClassNames.JAVA_LANG_OBJECT.equals(aClass.getQualifiedName()); - } - - private static PsiClass findSuitableBaseClass(final PsiMethod method) - { - final PsiClass containingClass = method.getContainingClass(); - - if(containingClass instanceof PsiAnonymousClass) - { - return containingClass; - } - - final PsiClass superClass = containingClass.getSuperClass(); - if(superClass == null) - { - return containingClass; - } - - if(MethodHierarchyUtil.findBaseMethodInClass(method, superClass, true) == null) - { - for(final PsiClass anInterface : containingClass.getInterfaces()) - { - if(MethodHierarchyUtil.findBaseMethodInClass(method, anInterface, true) != null) - { - return anInterface; - } - } - } - - return containingClass; - } - - @Nullable - public final PsiMethod getBaseMethod() - { - final PsiElement element = myMethod.getElement(); - return element instanceof PsiMethod ? (PsiMethod) element : null; - } - - - @Nonnull - @Override - protected final Object[] buildChildren(@Nonnull final HierarchyNodeDescriptor descriptor) - { - final PsiElement psiElement = ((MethodHierarchyNodeDescriptor) descriptor).getPsiClass(); - if(!(psiElement instanceof PsiClass)) - { - return ArrayUtil.EMPTY_OBJECT_ARRAY; - } - final PsiClass psiClass = (PsiClass) psiElement; - final Collection subclasses = getSubclasses(psiClass); - - final List descriptors = new ArrayList(subclasses.size()); - for(final PsiClass aClass : subclasses) - { - if(HierarchyBrowserManager.getInstance(myProject).getState().HIDE_CLASSES_WHERE_METHOD_NOT_IMPLEMENTED) - { - if(shouldHideClass(aClass)) - { - continue; - } - } - - final MethodHierarchyNodeDescriptor d = new MethodHierarchyNodeDescriptor(myProject, descriptor, aClass, false, this); - descriptors.add(d); - } - - final PsiMethod existingMethod = ((MethodHierarchyNodeDescriptor) descriptor).getMethod(psiClass, false); - if(existingMethod != null) - { - FunctionalExpressionSearch.search(existingMethod).forEach(new Processor() - { - @Override - public boolean process(PsiFunctionalExpression expression) - { - descriptors.add(new MethodHierarchyNodeDescriptor(myProject, descriptor, expression, false, MethodHierarchyTreeStructure.this)); - return true; - } - }); - } - - return descriptors.toArray(new HierarchyNodeDescriptor[descriptors.size()]); - } - - private static Collection getSubclasses(final PsiClass psiClass) - { - if(psiClass instanceof PsiAnonymousClass || psiClass.hasModifierProperty(PsiModifier.FINAL)) - { - return Collections.emptyList(); - } - - return ClassInheritorsSearch.search(psiClass, false).findAll(); - } - - private boolean shouldHideClass(final PsiClass psiClass) - { - if(getMethod(psiClass, false) != null || isSuperClassForBaseClass(psiClass)) - { - return false; - } - - if(hasBaseClassMethod(psiClass) || isAbstract(psiClass)) - { - for(final PsiClass subclass : getSubclasses(psiClass)) - { - if(!shouldHideClass(subclass)) - { - return false; - } - } - return true; - } - - return false; - } - - private boolean isAbstract(final PsiModifierListOwner owner) - { - return owner.hasModifierProperty(PsiModifier.ABSTRACT); - } - - private boolean hasBaseClassMethod(final PsiClass psiClass) - { - final PsiMethod baseClassMethod = getMethod(psiClass, true); - return baseClassMethod != null && !isAbstract(baseClassMethod); - } - - private PsiMethod getMethod(final PsiClass aClass, final boolean checkBases) - { - return MethodHierarchyUtil.findBaseMethodInClass(getBaseMethod(), aClass, checkBases); - } - - boolean isSuperClassForBaseClass(final PsiClass aClass) - { - final PsiMethod baseMethod = getBaseMethod(); - if(baseMethod == null) - { - return false; - } - final PsiClass baseClass = baseMethod.getContainingClass(); - if(baseClass == null) - { - return false; - } - // NB: parameters here are at CORRECT places!!! - return baseClass.isInheritor(aClass, true); - } +public final class MethodHierarchyTreeStructure extends HierarchyTreeStructure { + private final SmartPsiElementPointer myMethod; + + /** + * Should be called in read action + */ + public MethodHierarchyTreeStructure(final Project project, final PsiMethod method) { + super(project, null); + myBaseDescriptor = buildHierarchyElement(project, method); + ((MethodHierarchyNodeDescriptor)myBaseDescriptor).setTreeStructure(this); + myMethod = SmartPointerManager.getInstance(myProject).createSmartPsiElementPointer(method); + setBaseElement(myBaseDescriptor); //to set myRoot + } + + private HierarchyNodeDescriptor buildHierarchyElement(final Project project, final PsiMethod method) { + final PsiClass suitableBaseClass = findSuitableBaseClass(method); + + HierarchyNodeDescriptor descriptor = null; + final ArrayList superClasses = createSuperClasses(suitableBaseClass); + + if (!suitableBaseClass.equals(method.getContainingClass())) { + superClasses.add(0, suitableBaseClass); + } + + // remove from the top of the branch the classes that contain no 'method' + for (int i = superClasses.size() - 1; i >= 0; i--) { + final PsiClass psiClass = superClasses.get(i); + + if (MethodHierarchyUtil.findBaseMethodInClass(method, psiClass, false) == null) { + superClasses.remove(i); + } + else { + break; + } + } + + for (int i = superClasses.size() - 1; i >= 0; i--) { + final PsiClass superClass = superClasses.get(i); + final HierarchyNodeDescriptor newDescriptor = + new MethodHierarchyNodeDescriptor(project, descriptor, superClass, false, this); + if (descriptor != null) { + descriptor.setCachedChildren(new HierarchyNodeDescriptor[]{newDescriptor}); + } + descriptor = newDescriptor; + } + final HierarchyNodeDescriptor newDescriptor = + new MethodHierarchyNodeDescriptor(project, descriptor, method.getContainingClass(), true, this); + if (descriptor != null) { + descriptor.setCachedChildren(new HierarchyNodeDescriptor[]{newDescriptor}); + } + return newDescriptor; + } + + private static ArrayList createSuperClasses(PsiClass aClass) { + if (!aClass.isValid()) { + return new ArrayList(); + } + + final ArrayList superClasses = new ArrayList(); + while (!isJavaLangObject(aClass)) { + final PsiClass aClass1 = aClass; + final PsiClass[] superTypes = aClass1.getSupers(); + PsiClass superType = null; + // find class first + for (final PsiClass type : superTypes) { + if (!type.isInterface() && !isJavaLangObject(type)) { + superType = type; + break; + } + } + // if we haven't found a class, try to find an interface + if (superType == null) { + for (final PsiClass type : superTypes) { + if (!isJavaLangObject(type)) { + superType = type; + break; + } + } + } + if (superType == null) { + break; + } + if (superClasses.contains(superType)) { + break; + } + superClasses.add(superType); + aClass = superType; + } + + return superClasses; + } + + private static boolean isJavaLangObject(final PsiClass aClass) { + return JavaClassNames.JAVA_LANG_OBJECT.equals(aClass.getQualifiedName()); + } + + private static PsiClass findSuitableBaseClass(final PsiMethod method) { + final PsiClass containingClass = method.getContainingClass(); + + if (containingClass instanceof PsiAnonymousClass) { + return containingClass; + } + + final PsiClass superClass = containingClass.getSuperClass(); + if (superClass == null) { + return containingClass; + } + + if (MethodHierarchyUtil.findBaseMethodInClass(method, superClass, true) == null) { + for (final PsiClass anInterface : containingClass.getInterfaces()) { + if (MethodHierarchyUtil.findBaseMethodInClass(method, anInterface, true) != null) { + return anInterface; + } + } + } + + return containingClass; + } + + @Nullable + public final PsiMethod getBaseMethod() { + final PsiElement element = myMethod.getElement(); + return element instanceof PsiMethod ? (PsiMethod)element : null; + } + + + @Nonnull + @Override + protected final Object[] buildChildren(@Nonnull final HierarchyNodeDescriptor descriptor) { + final PsiElement psiElement = ((MethodHierarchyNodeDescriptor)descriptor).getPsiClass(); + if (!(psiElement instanceof PsiClass)) { + return ArrayUtil.EMPTY_OBJECT_ARRAY; + } + final PsiClass psiClass = (PsiClass)psiElement; + final Collection subclasses = getSubclasses(psiClass); + + final List descriptors = new ArrayList(subclasses.size()); + for (final PsiClass aClass : subclasses) { + if (HierarchyBrowserManager.getInstance(myProject).getState().HIDE_CLASSES_WHERE_METHOD_NOT_IMPLEMENTED) { + if (shouldHideClass(aClass)) { + continue; + } + } + + final MethodHierarchyNodeDescriptor d = new MethodHierarchyNodeDescriptor(myProject, descriptor, aClass, false, this); + descriptors.add(d); + } + + final PsiMethod existingMethod = ((MethodHierarchyNodeDescriptor)descriptor).getMethod(psiClass, false); + if (existingMethod != null) { + FunctionalExpressionSearch.search(existingMethod).forEach(new Processor() { + @Override + public boolean process(PsiFunctionalExpression expression) { + descriptors.add(new MethodHierarchyNodeDescriptor( + myProject, + descriptor, + expression, + false, + MethodHierarchyTreeStructure.this + )); + return true; + } + }); + } + + return descriptors.toArray(new HierarchyNodeDescriptor[descriptors.size()]); + } + + private static Collection getSubclasses(final PsiClass psiClass) { + if (psiClass instanceof PsiAnonymousClass || psiClass.hasModifierProperty(PsiModifier.FINAL)) { + return Collections.emptyList(); + } + + return ClassInheritorsSearch.search(psiClass, false).findAll(); + } + + private boolean shouldHideClass(final PsiClass psiClass) { + if (getMethod(psiClass, false) != null || isSuperClassForBaseClass(psiClass)) { + return false; + } + + if (hasBaseClassMethod(psiClass) || isAbstract(psiClass)) { + for (final PsiClass subclass : getSubclasses(psiClass)) { + if (!shouldHideClass(subclass)) { + return false; + } + } + return true; + } + + return false; + } + + private boolean isAbstract(final PsiModifierListOwner owner) { + return owner.hasModifierProperty(PsiModifier.ABSTRACT); + } + + private boolean hasBaseClassMethod(final PsiClass psiClass) { + final PsiMethod baseClassMethod = getMethod(psiClass, true); + return baseClassMethod != null && !isAbstract(baseClassMethod); + } + + private PsiMethod getMethod(final PsiClass aClass, final boolean checkBases) { + return MethodHierarchyUtil.findBaseMethodInClass(getBaseMethod(), aClass, checkBases); + } + + boolean isSuperClassForBaseClass(final PsiClass aClass) { + final PsiMethod baseMethod = getBaseMethod(); + if (baseMethod == null) { + return false; + } + final PsiClass baseClass = baseMethod.getContainingClass(); + if (baseClass == null) { + return false; + } + // NB: parameters here are at CORRECT places!!! + return baseClass.isInheritor(aClass, true); + } } diff --git a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/MethodHierarchyUtil.java b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/MethodHierarchyUtil.java index 74692c3abc..8416fdf5ea 100644 --- a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/MethodHierarchyUtil.java +++ b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/MethodHierarchyUtil.java @@ -21,21 +21,25 @@ import com.intellij.java.language.psi.util.MethodSignatureUtil; final class MethodHierarchyUtil { - public static PsiMethod findBaseMethodInClass(final PsiMethod baseMethod, final PsiClass aClass, final boolean checkBases) { - if (baseMethod == null) return null; // base method is invalid - if (cannotBeOverridding(baseMethod)) return null; - /*if (!checkBases) return MethodSignatureUtil.findMethodBySignature(aClass, signature, false);*/ - return MethodSignatureUtil.findMethodBySuperMethod(aClass, baseMethod, checkBases); - /*final MethodSignatureBackedByPsiMethod signature = SuperMethodsSearch.search(baseMethod, aClass, checkBases, false).findFirst(); - return signature == null ? null : signature.getMethod();*/ - } + public static PsiMethod findBaseMethodInClass(final PsiMethod baseMethod, final PsiClass aClass, final boolean checkBases) { + if (baseMethod == null) { + return null; // base method is invalid + } + if (cannotBeOverridding(baseMethod)) { + return null; + } + /*if (!checkBases) return MethodSignatureUtil.findMethodBySignature(aClass, signature, false);*/ + return MethodSignatureUtil.findMethodBySuperMethod(aClass, baseMethod, checkBases); + /*final MethodSignatureBackedByPsiMethod signature = SuperMethodsSearch.search(baseMethod, aClass, checkBases, false).findFirst(); + return signature == null ? null : signature.getMethod();*/ + } - private static boolean cannotBeOverridding(final PsiMethod method) { - final PsiClass parentClass = method.getContainingClass(); - return parentClass == null - || method.isConstructor() - || method.hasModifierProperty(PsiModifier.STATIC) - || method.hasModifierProperty(PsiModifier.PRIVATE); - } + private static boolean cannotBeOverridding(final PsiMethod method) { + final PsiClass parentClass = method.getContainingClass(); + return parentClass == null + || method.isConstructor() + || method.hasModifierProperty(PsiModifier.STATIC) + || method.hasModifierProperty(PsiModifier.PRIVATE); + } } diff --git a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/OverrideImplementMethodAction.java b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/OverrideImplementMethodAction.java index 8660ccb8c1..a2efaa6e70 100644 --- a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/OverrideImplementMethodAction.java +++ b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/OverrideImplementMethodAction.java @@ -46,184 +46,157 @@ import java.util.Collection; import java.util.List; -abstract class OverrideImplementMethodAction extends AnAction -{ - private static final Logger LOG = Logger.getInstance(OverrideImplementMethodAction.class); +abstract class OverrideImplementMethodAction extends AnAction { + private static final Logger LOG = Logger.getInstance(OverrideImplementMethodAction.class); - @RequiredUIAccess - @Override - public final void actionPerformed(@Nonnull final AnActionEvent event) - { - final DataContext dataContext = event.getDataContext(); - final MethodHierarchyBrowser methodHierarchyBrowser = (MethodHierarchyBrowser) dataContext.getData(MethodHierarchyBrowserBase.DATA_KEY); - if (methodHierarchyBrowser == null) - { - return; - } - final Project project = dataContext.getData(Project.KEY); - if (project == null) - { - return; - } + @RequiredUIAccess + @Override + public final void actionPerformed(@Nonnull final AnActionEvent event) { + final DataContext dataContext = event.getDataContext(); + final MethodHierarchyBrowser methodHierarchyBrowser = + (MethodHierarchyBrowser)dataContext.getData(MethodHierarchyBrowserBase.DATA_KEY); + if (methodHierarchyBrowser == null) { + return; + } + final Project project = dataContext.getData(Project.KEY); + if (project == null) { + return; + } - final String commandName = event.getPresentation().getText(); - Application.get().runWriteAction(() -> CommandProcessor.getInstance().executeCommand( - project, - new Runnable() - { - @Override - @RequiredUIAccess - public void run() - { - try - { - final HierarchyNodeDescriptor[] selectedDescriptors = methodHierarchyBrowser.getSelectedDescriptors(); - if (selectedDescriptors.length > 0) - { - final List files = new ArrayList<>(selectedDescriptors.length); - for (HierarchyNodeDescriptor selectedDescriptor : selectedDescriptors) - { - final PsiFile containingFile = ((MethodHierarchyNodeDescriptor) selectedDescriptor).getPsiClass().getContainingFile(); - if (containingFile != null) - { - final VirtualFile vFile = containingFile.getVirtualFile(); - if (vFile != null) - { - files.add(vFile); - } - } - } - final ReadonlyStatusHandler.OperationStatus status = - ReadonlyStatusHandler.getInstance(project).ensureFilesWritable(VfsUtil.toVirtualFileArray(files)); - if (!status.hasReadonlyFiles()) - { - for (HierarchyNodeDescriptor selectedDescriptor : selectedDescriptors) - { - final PsiElement aClass = ((MethodHierarchyNodeDescriptor) selectedDescriptor).getPsiClass(); - if (aClass instanceof PsiClass psiClass) - { - OverrideImplementUtil.overrideOrImplement(psiClass, methodHierarchyBrowser.getBaseMethod()); - } - } - ToolWindowManager.getInstance(project).activateEditorComponent(); - } - else - { - Application.get().invokeLater(() -> Messages.showErrorDialog(project, status.getReadonlyFilesMessage(), commandName)); - } - } - } - catch (IncorrectOperationException e) - { - LOG.error(e); - } - } - }, - commandName, - null - )); - } + final String commandName = event.getPresentation().getText(); + Application.get().runWriteAction(() -> CommandProcessor.getInstance().executeCommand( + project, + new Runnable() { + @Override + @RequiredUIAccess + public void run() { + try { + final HierarchyNodeDescriptor[] selectedDescriptors = methodHierarchyBrowser.getSelectedDescriptors(); + if (selectedDescriptors.length > 0) { + final List files = new ArrayList<>(selectedDescriptors.length); + for (HierarchyNodeDescriptor selectedDescriptor : selectedDescriptors) { + final PsiFile containingFile = + ((MethodHierarchyNodeDescriptor)selectedDescriptor).getPsiClass().getContainingFile(); + if (containingFile != null) { + final VirtualFile vFile = containingFile.getVirtualFile(); + if (vFile != null) { + files.add(vFile); + } + } + } + final ReadonlyStatusHandler.OperationStatus status = + ReadonlyStatusHandler.getInstance(project).ensureFilesWritable(VfsUtil.toVirtualFileArray(files)); + if (!status.hasReadonlyFiles()) { + for (HierarchyNodeDescriptor selectedDescriptor : selectedDescriptors) { + final PsiElement aClass = ((MethodHierarchyNodeDescriptor)selectedDescriptor).getPsiClass(); + if (aClass instanceof PsiClass psiClass) { + OverrideImplementUtil.overrideOrImplement(psiClass, methodHierarchyBrowser.getBaseMethod()); + } + } + ToolWindowManager.getInstance(project).activateEditorComponent(); + } + else { + Application.get() + .invokeLater(() -> Messages.showErrorDialog(project, status.getReadonlyFilesMessage(), commandName)); + } + } + } + catch (IncorrectOperationException e) { + LOG.error(e); + } + } + }, + commandName, + null + )); + } - @RequiredUIAccess - @Override - public final void update(@Nonnull final AnActionEvent e) - { - final Presentation presentation = e.getPresentation(); - final DataContext dataContext = e.getDataContext(); + @RequiredUIAccess + @Override + public final void update(@Nonnull final AnActionEvent e) { + final Presentation presentation = e.getPresentation(); + final DataContext dataContext = e.getDataContext(); - final MethodHierarchyBrowser methodHierarchyBrowser = (MethodHierarchyBrowser) dataContext.getData(MethodHierarchyBrowserBase.DATA_KEY); - if (methodHierarchyBrowser == null) - { - presentation.setEnabled(false); - presentation.setVisible(false); - return; - } - final Project project = dataContext.getData(Project.KEY); - if (project == null) - { - presentation.setEnabled(false); - presentation.setVisible(false); - return; - } + final MethodHierarchyBrowser methodHierarchyBrowser = + (MethodHierarchyBrowser)dataContext.getData(MethodHierarchyBrowserBase.DATA_KEY); + if (methodHierarchyBrowser == null) { + presentation.setEnabled(false); + presentation.setVisible(false); + return; + } + final Project project = dataContext.getData(Project.KEY); + if (project == null) { + presentation.setEnabled(false); + presentation.setVisible(false); + return; + } - final HierarchyNodeDescriptor[] selectedDescriptors = methodHierarchyBrowser.getSelectedDescriptors(); - int toImplement = 0; - int toOverride = 0; + final HierarchyNodeDescriptor[] selectedDescriptors = methodHierarchyBrowser.getSelectedDescriptors(); + int toImplement = 0; + int toOverride = 0; - for (final HierarchyNodeDescriptor descriptor : selectedDescriptors) - { - if (canImplementOverride((MethodHierarchyNodeDescriptor) descriptor, methodHierarchyBrowser, true)) - { - if (toOverride > 0) - { - // no mixed actions allowed - presentation.setEnabled(false); - presentation.setVisible(false); - return; - } - toImplement++; - } - else if (canImplementOverride((MethodHierarchyNodeDescriptor) descriptor, methodHierarchyBrowser, false)) - { - if (toImplement > 0) - { - // no mixed actions allowed - presentation.setEnabled(false); - presentation.setVisible(false); - return; - } - toOverride++; - } - else - { - // no action is applicable to this node - presentation.setEnabled(false); - presentation.setVisible(false); - return; - } - } + for (final HierarchyNodeDescriptor descriptor : selectedDescriptors) { + if (canImplementOverride((MethodHierarchyNodeDescriptor)descriptor, methodHierarchyBrowser, true)) { + if (toOverride > 0) { + // no mixed actions allowed + presentation.setEnabled(false); + presentation.setVisible(false); + return; + } + toImplement++; + } + else if (canImplementOverride((MethodHierarchyNodeDescriptor)descriptor, methodHierarchyBrowser, false)) { + if (toImplement > 0) { + // no mixed actions allowed + presentation.setEnabled(false); + presentation.setVisible(false); + return; + } + toOverride++; + } + else { + // no action is applicable to this node + presentation.setEnabled(false); + presentation.setVisible(false); + return; + } + } - presentation.setVisible(true); + presentation.setVisible(true); - update(presentation, toImplement, toOverride); - } + update(presentation, toImplement, toOverride); + } - protected abstract void update(Presentation presentation, int toImplement, int toOverride); + protected abstract void update(Presentation presentation, int toImplement, int toOverride); - private static boolean canImplementOverride( - final MethodHierarchyNodeDescriptor descriptor, - final MethodHierarchyBrowser methodHierarchyBrowser, - final boolean toImplement - ) - { - final PsiElement psiElement = descriptor.getPsiClass(); - if (!(psiElement instanceof PsiClass)) - { - return false; - } - final PsiClass psiClass = (PsiClass) psiElement; - if (psiClass instanceof PsiSyntheticClass) - { - return false; - } - final PsiMethod baseMethod = methodHierarchyBrowser.getBaseMethod(); - if (baseMethod == null) - { - return false; - } - final MethodSignature signature = baseMethod.getSignature(PsiSubstitutor.EMPTY); + private static boolean canImplementOverride( + final MethodHierarchyNodeDescriptor descriptor, + final MethodHierarchyBrowser methodHierarchyBrowser, + final boolean toImplement + ) { + final PsiElement psiElement = descriptor.getPsiClass(); + if (!(psiElement instanceof PsiClass)) { + return false; + } + final PsiClass psiClass = (PsiClass)psiElement; + if (psiClass instanceof PsiSyntheticClass) { + return false; + } + final PsiMethod baseMethod = methodHierarchyBrowser.getBaseMethod(); + if (baseMethod == null) { + return false; + } + final MethodSignature signature = baseMethod.getSignature(PsiSubstitutor.EMPTY); - Collection allOriginalSignatures = toImplement - ? OverrideImplementUtil.getMethodSignaturesToImplement(psiClass) - : OverrideImplementUtil.getMethodSignaturesToOverride(psiClass); - for (final MethodSignature originalSignature : allOriginalSignatures) - { - if (originalSignature.equals(signature)) - { - return true; - } - } + Collection allOriginalSignatures = toImplement + ? OverrideImplementUtil.getMethodSignaturesToImplement(psiClass) + : OverrideImplementUtil.getMethodSignaturesToOverride(psiClass); + for (final MethodSignature originalSignature : allOriginalSignatures) { + if (originalSignature.equals(signature)) { + return true; + } + } - return false; - } + return false; + } } diff --git a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/OverrideMethodAction.java b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/OverrideMethodAction.java index 5fb3c4766e..9a6badfab6 100644 --- a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/OverrideMethodAction.java +++ b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/OverrideMethodAction.java @@ -19,15 +19,15 @@ import consulo.ui.ex.action.Presentation; public final class OverrideMethodAction extends OverrideImplementMethodAction { - protected final void update(final Presentation presentation, final int toImplement, final int toOverride) { - if (toOverride > 0) { - presentation.setEnabled(true); - presentation.setVisible(true); - presentation.setTextValue(toOverride == 1 ? IdeLocalize.actionOverrideMethod() : IdeLocalize.actionOverrideMethods()); + protected final void update(final Presentation presentation, final int toImplement, final int toOverride) { + if (toOverride > 0) { + presentation.setEnabled(true); + presentation.setVisible(true); + presentation.setTextValue(toOverride == 1 ? IdeLocalize.actionOverrideMethod() : IdeLocalize.actionOverrideMethods()); + } + else { + presentation.setEnabled(false); + presentation.setVisible(false); + } } - else { - presentation.setEnabled(false); - presentation.setVisible(false); - } - } } diff --git a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/type/JavaTypeHierarchyProvider.java b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/type/JavaTypeHierarchyProvider.java index 3faa399939..417afbcced 100644 --- a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/type/JavaTypeHierarchyProvider.java +++ b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/type/JavaTypeHierarchyProvider.java @@ -35,6 +35,7 @@ import consulo.ui.annotation.RequiredUIAccess; import jakarta.annotation.Nonnull; + import java.util.Set; /** @@ -42,73 +43,74 @@ */ @ExtensionImpl public class JavaTypeHierarchyProvider implements TypeHierarchyProvider { - @Override - @RequiredUIAccess - public PsiElement getTarget(@Nonnull final DataContext dataContext) { - final Project project = dataContext.getData(Project.KEY); - if (project == null) { - return null; - } + @Override + @RequiredUIAccess + public PsiElement getTarget(@Nonnull final DataContext dataContext) { + final Project project = dataContext.getData(Project.KEY); + if (project == null) { + return null; + } + + final Editor editor = dataContext.getData(Editor.KEY); + if (editor != null) { + final PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); + if (file == null) { + return null; + } - final Editor editor = dataContext.getData(Editor.KEY); - if (editor != null) { - final PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); - if (file == null) { - return null; - } + final PsiElement targetElement = TargetElementUtil.findTargetElement( + editor, + Set.of( + TargetElementUtilExtender.ELEMENT_NAME_ACCEPTED, + TargetElementUtilExtender.REFERENCED_ELEMENT_ACCEPTED, + TargetElementUtilExtender.LOOKUP_ITEM_ACCEPTED + ) + ); + if (targetElement instanceof PsiClass) { + return targetElement; + } - final PsiElement targetElement = TargetElementUtil.findTargetElement( - editor, - Set.of( - TargetElementUtilExtender.ELEMENT_NAME_ACCEPTED, - TargetElementUtilExtender.REFERENCED_ELEMENT_ACCEPTED, - TargetElementUtilExtender.LOOKUP_ITEM_ACCEPTED - ) - ); - if (targetElement instanceof PsiClass) { - return targetElement; - } + final int offset = editor.getCaretModel().getOffset(); + PsiElement element = file.findElementAt(offset); + while (element != null) { + if (element instanceof PsiFile) { + if (!(element instanceof PsiClassOwner)) { + return null; + } + final PsiClass[] classes = ((PsiClassOwner)element).getClasses(); + return classes.length == 1 ? classes[0] : null; + } + if (element instanceof PsiClass && !(element instanceof PsiAnonymousClass) && !(element instanceof PsiSyntheticClass)) { + return element; + } + element = element.getParent(); + } - final int offset = editor.getCaretModel().getOffset(); - PsiElement element = file.findElementAt(offset); - while (element != null) { - if (element instanceof PsiFile) { - if (!(element instanceof PsiClassOwner)) { return null; - } - final PsiClass[] classes = ((PsiClassOwner) element).getClasses(); - return classes.length == 1 ? classes[0] : null; } - if (element instanceof PsiClass && !(element instanceof PsiAnonymousClass) && !(element instanceof PsiSyntheticClass)) { - return element; + else { + final PsiElement element = dataContext.getData(PsiElement.KEY); + return element instanceof PsiClass psiClass ? psiClass : null; } - element = element.getParent(); - } - - return null; - } else { - final PsiElement element = dataContext.getData(PsiElement.KEY); - return element instanceof PsiClass psiClass ? psiClass : null; } - } - @Override - @Nonnull - public HierarchyBrowser createHierarchyBrowser(final PsiElement target) { - return new TypeHierarchyBrowser(target.getProject(), (PsiClass) target); - } + @Override + @Nonnull + public HierarchyBrowser createHierarchyBrowser(final PsiElement target) { + return new TypeHierarchyBrowser(target.getProject(), (PsiClass)target); + } - @Override - public void browserActivated(@Nonnull final HierarchyBrowser hierarchyBrowser) { - final TypeHierarchyBrowser browser = (TypeHierarchyBrowser) hierarchyBrowser; - final String typeName = browser.isInterface() - ? TypeHierarchyBrowserBase.SUBTYPES_HIERARCHY_TYPE : TypeHierarchyBrowserBase.TYPE_HIERARCHY_TYPE; - browser.changeView(typeName); - } + @Override + public void browserActivated(@Nonnull final HierarchyBrowser hierarchyBrowser) { + final TypeHierarchyBrowser browser = (TypeHierarchyBrowser)hierarchyBrowser; + final String typeName = browser.isInterface() + ? TypeHierarchyBrowserBase.SUBTYPES_HIERARCHY_TYPE : TypeHierarchyBrowserBase.TYPE_HIERARCHY_TYPE; + browser.changeView(typeName); + } - @Nonnull - @Override - public Language getLanguage() { - return JavaLanguage.INSTANCE; - } + @Nonnull + @Override + public Language getLanguage() { + return JavaLanguage.INSTANCE; + } } diff --git a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/type/SubtypesHierarchyTreeStructure.java b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/type/SubtypesHierarchyTreeStructure.java index 6a439878dd..d19ce3702d 100644 --- a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/type/SubtypesHierarchyTreeStructure.java +++ b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/type/SubtypesHierarchyTreeStructure.java @@ -32,55 +32,46 @@ import java.util.ArrayList; import java.util.List; -public class SubtypesHierarchyTreeStructure extends HierarchyTreeStructure -{ - private final String myCurrentScopeType; +public class SubtypesHierarchyTreeStructure extends HierarchyTreeStructure { + private final String myCurrentScopeType; - protected SubtypesHierarchyTreeStructure(final Project project, final HierarchyNodeDescriptor descriptor, String currentScopeType) - { - super(project, descriptor); - myCurrentScopeType = currentScopeType; - } + protected SubtypesHierarchyTreeStructure(final Project project, final HierarchyNodeDescriptor descriptor, String currentScopeType) { + super(project, descriptor); + myCurrentScopeType = currentScopeType; + } - public SubtypesHierarchyTreeStructure(Project project, PsiClass psiClass, String currentScopeType) - { - super(project, new TypeHierarchyNodeDescriptor(project, null, psiClass, true)); - myCurrentScopeType = currentScopeType; - } + public SubtypesHierarchyTreeStructure(Project project, PsiClass psiClass, String currentScopeType) { + super(project, new TypeHierarchyNodeDescriptor(project, null, psiClass, true)); + myCurrentScopeType = currentScopeType; + } - @Override - @Nonnull - protected final Object[] buildChildren(@Nonnull final HierarchyNodeDescriptor descriptor) - { - final Object element = ((TypeHierarchyNodeDescriptor) descriptor).getPsiClass(); - if (!(element instanceof PsiClass)) - { - return ArrayUtil.EMPTY_OBJECT_ARRAY; - } - final PsiClass psiClass = (PsiClass) element; - if (JavaClassNames.JAVA_LANG_OBJECT.equals(psiClass.getQualifiedName())) - { - return new Object[]{IdeLocalize.nodeHierarchyJavaLangObject().get()}; - } - if (psiClass instanceof PsiAnonymousClass) - { - return ArrayUtil.EMPTY_OBJECT_ARRAY; - } - if (psiClass.hasModifierProperty(PsiModifier.FINAL)) - { - return ArrayUtil.EMPTY_OBJECT_ARRAY; - } - final SearchScope searchScope = psiClass.getUseScope().intersectWith(getSearchScope(myCurrentScopeType, psiClass)); - final List classes = new ArrayList<>(ClassInheritorsSearch.search(psiClass, searchScope, false).findAll()); - final List descriptors = new ArrayList<>(classes.size()); - for (PsiClass aClass : classes) - { - descriptors.add(new TypeHierarchyNodeDescriptor(myProject, descriptor, aClass, false)); - } - FunctionalExpressionSearch.search(psiClass, searchScope).forEach(expression -> { - descriptors.add(new TypeHierarchyNodeDescriptor(myProject, descriptor, expression, false)); - return true; - }); - return descriptors.toArray(new HierarchyNodeDescriptor[descriptors.size()]); - } + @Override + @Nonnull + protected final Object[] buildChildren(@Nonnull final HierarchyNodeDescriptor descriptor) { + final Object element = ((TypeHierarchyNodeDescriptor)descriptor).getPsiClass(); + if (!(element instanceof PsiClass)) { + return ArrayUtil.EMPTY_OBJECT_ARRAY; + } + final PsiClass psiClass = (PsiClass)element; + if (JavaClassNames.JAVA_LANG_OBJECT.equals(psiClass.getQualifiedName())) { + return new Object[]{IdeLocalize.nodeHierarchyJavaLangObject().get()}; + } + if (psiClass instanceof PsiAnonymousClass) { + return ArrayUtil.EMPTY_OBJECT_ARRAY; + } + if (psiClass.hasModifierProperty(PsiModifier.FINAL)) { + return ArrayUtil.EMPTY_OBJECT_ARRAY; + } + final SearchScope searchScope = psiClass.getUseScope().intersectWith(getSearchScope(myCurrentScopeType, psiClass)); + final List classes = new ArrayList<>(ClassInheritorsSearch.search(psiClass, searchScope, false).findAll()); + final List descriptors = new ArrayList<>(classes.size()); + for (PsiClass aClass : classes) { + descriptors.add(new TypeHierarchyNodeDescriptor(myProject, descriptor, aClass, false)); + } + FunctionalExpressionSearch.search(psiClass, searchScope).forEach(expression -> { + descriptors.add(new TypeHierarchyNodeDescriptor(myProject, descriptor, expression, false)); + return true; + }); + return descriptors.toArray(new HierarchyNodeDescriptor[descriptors.size()]); + } } diff --git a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/type/SupertypesHierarchyTreeStructure.java b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/type/SupertypesHierarchyTreeStructure.java index bd27678fa6..393379312d 100644 --- a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/type/SupertypesHierarchyTreeStructure.java +++ b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/type/SupertypesHierarchyTreeStructure.java @@ -30,42 +30,40 @@ import com.intellij.java.language.psi.util.PsiUtil; import consulo.util.collection.ArrayUtil; -public final class SupertypesHierarchyTreeStructure extends HierarchyTreeStructure -{ +public final class SupertypesHierarchyTreeStructure extends HierarchyTreeStructure { + public SupertypesHierarchyTreeStructure(final Project project, final PsiClass aClass) { + super(project, new TypeHierarchyNodeDescriptor(project, null, aClass, true)); + } - public SupertypesHierarchyTreeStructure(final Project project, final PsiClass aClass) - { - super(project, new TypeHierarchyNodeDescriptor(project, null, aClass, true)); - } - - @Override - @Nonnull - protected final Object[] buildChildren(@Nonnull final HierarchyNodeDescriptor descriptor) - { - final Object element = ((TypeHierarchyNodeDescriptor) descriptor).getPsiClass(); - if(element instanceof PsiClass) - { - final PsiClass psiClass = (PsiClass) element; - final PsiClass[] supers = psiClass.getSupers(); - final List descriptors = new ArrayList(); - final PsiClass objectClass = JavaPsiFacade.getInstance(myProject).findClass(JavaClassNames.JAVA_LANG_OBJECT, psiClass.getResolveScope()); - for(PsiClass aSuper : supers) - { - if(!psiClass.isInterface() || !aSuper.equals(objectClass)) - { - descriptors.add(new TypeHierarchyNodeDescriptor(myProject, descriptor, aSuper, false)); - } - } - return descriptors.toArray(new HierarchyNodeDescriptor[descriptors.size()]); - } - else if(element instanceof PsiFunctionalExpression) - { - final PsiClass functionalInterfaceClass = PsiUtil.resolveClassInType(((PsiFunctionalExpression) element).getFunctionalInterfaceType()); - if(functionalInterfaceClass != null) - { - return new HierarchyNodeDescriptor[]{new TypeHierarchyNodeDescriptor(myProject, descriptor, functionalInterfaceClass, false)}; - } - } - return ArrayUtil.EMPTY_OBJECT_ARRAY; - } + @Override + @Nonnull + protected final Object[] buildChildren(@Nonnull final HierarchyNodeDescriptor descriptor) { + final Object element = ((TypeHierarchyNodeDescriptor)descriptor).getPsiClass(); + if (element instanceof PsiClass) { + final PsiClass psiClass = (PsiClass)element; + final PsiClass[] supers = psiClass.getSupers(); + final List descriptors = new ArrayList(); + final PsiClass objectClass = + JavaPsiFacade.getInstance(myProject).findClass(JavaClassNames.JAVA_LANG_OBJECT, psiClass.getResolveScope()); + for (PsiClass aSuper : supers) { + if (!psiClass.isInterface() || !aSuper.equals(objectClass)) { + descriptors.add(new TypeHierarchyNodeDescriptor(myProject, descriptor, aSuper, false)); + } + } + return descriptors.toArray(new HierarchyNodeDescriptor[descriptors.size()]); + } + else if (element instanceof PsiFunctionalExpression) { + final PsiClass functionalInterfaceClass = + PsiUtil.resolveClassInType(((PsiFunctionalExpression)element).getFunctionalInterfaceType()); + if (functionalInterfaceClass != null) { + return new HierarchyNodeDescriptor[]{new TypeHierarchyNodeDescriptor( + myProject, + descriptor, + functionalInterfaceClass, + false + )}; + } + } + return ArrayUtil.EMPTY_OBJECT_ARRAY; + } } diff --git a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/type/TypeHierarchyBrowser.java b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/type/TypeHierarchyBrowser.java index 72adee8b61..a80425c879 100644 --- a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/type/TypeHierarchyBrowser.java +++ b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/type/TypeHierarchyBrowser.java @@ -42,127 +42,103 @@ import com.intellij.java.language.impl.psi.presentation.java.ClassPresentationUtil; import jakarta.annotation.Nullable; -public class TypeHierarchyBrowser extends TypeHierarchyBrowserBase -{ - private static final Logger LOG = Logger.getInstance(TypeHierarchyBrowser.class); - - - public TypeHierarchyBrowser(final Project project, final PsiClass psiClass) - { - super(project, psiClass); - } - - @Override - protected boolean isInterface(PsiElement psiElement) - { - return psiElement instanceof PsiClass && ((PsiClass) psiElement).isInterface(); - } - - @Override - protected void createTrees(@Nonnull Map trees) - { - createTreeAndSetupCommonActions(trees, IdeActions.GROUP_TYPE_HIERARCHY_POPUP); - } - - @Override - protected void prependActions(DefaultActionGroup actionGroup) - { - super.prependActions(actionGroup); - actionGroup.add(new ChangeScopeAction() - { - @Override - protected boolean isEnabled() - { - return !Comparing.strEqual(myCurrentViewType, SUPERTYPES_HIERARCHY_TYPE); - } - }); - } - - @Override - protected String getContentDisplayName(@Nonnull String typeName, @Nonnull PsiElement element) - { - return MessageFormat.format(typeName, ClassPresentationUtil.getNameForClass((PsiClass) element, false)); - } - - @Override - protected PsiElement getElementFromDescriptor(@Nonnull HierarchyNodeDescriptor descriptor) - { - if(!(descriptor instanceof TypeHierarchyNodeDescriptor)) - { - return null; - } - return ((TypeHierarchyNodeDescriptor) descriptor).getPsiClass(); - } - - @Override - @Nullable - protected JPanel createLegendPanel() - { - return null; - } - - @Override - protected boolean isApplicableElement(@Nonnull final PsiElement element) - { - return element instanceof PsiClass; - } - - @Override - protected Comparator getComparator() - { - return JavaHierarchyUtil.getComparator(myProject); - } - - @Override - protected HierarchyTreeStructure createHierarchyTreeStructure(@Nonnull final String typeName, @Nonnull final PsiElement psiElement) - { - if(SUPERTYPES_HIERARCHY_TYPE.equals(typeName)) - { - return new SupertypesHierarchyTreeStructure(myProject, (PsiClass) psiElement); - } - else if(SUBTYPES_HIERARCHY_TYPE.equals(typeName)) - { - return new SubtypesHierarchyTreeStructure(myProject, (PsiClass) psiElement, getCurrentScopeType()); - } - else if(TYPE_HIERARCHY_TYPE.equals(typeName)) - { - return new TypeHierarchyTreeStructure(myProject, (PsiClass) psiElement, getCurrentScopeType()); - } - else - { - LOG.error("unexpected type: " + typeName); - return null; - } - } - - @Override - protected boolean canBeDeleted(final PsiElement psiElement) - { - return psiElement instanceof PsiClass && !(psiElement instanceof PsiAnonymousClass); - } - - @Override - protected String getQualifiedName(final PsiElement psiElement) - { - if(psiElement instanceof PsiClass) - { - return ((PsiClass) psiElement).getQualifiedName(); - } - return ""; - } - - public static class BaseOnThisTypeAction extends TypeHierarchyBrowserBase.BaseOnThisTypeAction - { - protected boolean isEnabled(@Nonnull final HierarchyBrowserBaseEx browser, @Nonnull final PsiElement psiElement) - { - return super.isEnabled(browser, psiElement) && !JavaClassNames.JAVA_LANG_OBJECT.equals(((PsiClass) psiElement).getQualifiedName()); - } - } - - @Nonnull - @Override - protected TypeHierarchyBrowserBase.BaseOnThisTypeAction createBaseOnThisAction() - { - return new BaseOnThisTypeAction(); - } +public class TypeHierarchyBrowser extends TypeHierarchyBrowserBase { + private static final Logger LOG = Logger.getInstance(TypeHierarchyBrowser.class); + + public TypeHierarchyBrowser(final Project project, final PsiClass psiClass) { + super(project, psiClass); + } + + @Override + protected boolean isInterface(PsiElement psiElement) { + return psiElement instanceof PsiClass && ((PsiClass)psiElement).isInterface(); + } + + @Override + protected void createTrees(@Nonnull Map trees) { + createTreeAndSetupCommonActions(trees, IdeActions.GROUP_TYPE_HIERARCHY_POPUP); + } + + @Override + protected void prependActions(DefaultActionGroup actionGroup) { + super.prependActions(actionGroup); + actionGroup.add(new ChangeScopeAction() { + @Override + protected boolean isEnabled() { + return !Comparing.strEqual(myCurrentViewType, SUPERTYPES_HIERARCHY_TYPE); + } + }); + } + + @Override + protected String getContentDisplayName(@Nonnull String typeName, @Nonnull PsiElement element) { + return MessageFormat.format(typeName, ClassPresentationUtil.getNameForClass((PsiClass)element, false)); + } + + @Override + protected PsiElement getElementFromDescriptor(@Nonnull HierarchyNodeDescriptor descriptor) { + if (!(descriptor instanceof TypeHierarchyNodeDescriptor)) { + return null; + } + return ((TypeHierarchyNodeDescriptor)descriptor).getPsiClass(); + } + + @Override + @Nullable + protected JPanel createLegendPanel() { + return null; + } + + @Override + protected boolean isApplicableElement(@Nonnull final PsiElement element) { + return element instanceof PsiClass; + } + + @Override + protected Comparator getComparator() { + return JavaHierarchyUtil.getComparator(myProject); + } + + @Override + protected HierarchyTreeStructure createHierarchyTreeStructure(@Nonnull final String typeName, @Nonnull final PsiElement psiElement) { + if (SUPERTYPES_HIERARCHY_TYPE.equals(typeName)) { + return new SupertypesHierarchyTreeStructure(myProject, (PsiClass)psiElement); + } + else if (SUBTYPES_HIERARCHY_TYPE.equals(typeName)) { + return new SubtypesHierarchyTreeStructure(myProject, (PsiClass)psiElement, getCurrentScopeType()); + } + else if (TYPE_HIERARCHY_TYPE.equals(typeName)) { + return new TypeHierarchyTreeStructure(myProject, (PsiClass)psiElement, getCurrentScopeType()); + } + else { + LOG.error("unexpected type: " + typeName); + return null; + } + } + + @Override + protected boolean canBeDeleted(final PsiElement psiElement) { + return psiElement instanceof PsiClass && !(psiElement instanceof PsiAnonymousClass); + } + + @Override + protected String getQualifiedName(final PsiElement psiElement) { + if (psiElement instanceof PsiClass) { + return ((PsiClass)psiElement).getQualifiedName(); + } + return ""; + } + + public static class BaseOnThisTypeAction extends TypeHierarchyBrowserBase.BaseOnThisTypeAction { + protected boolean isEnabled(@Nonnull final HierarchyBrowserBaseEx browser, @Nonnull final PsiElement psiElement) { + return super.isEnabled(browser, psiElement) + && !JavaClassNames.JAVA_LANG_OBJECT.equals(((PsiClass)psiElement).getQualifiedName()); + } + } + + @Nonnull + @Override + protected TypeHierarchyBrowserBase.BaseOnThisTypeAction createBaseOnThisAction() { + return new BaseOnThisTypeAction(); + } } diff --git a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/type/TypeHierarchyNodeDescriptor.java b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/type/TypeHierarchyNodeDescriptor.java index f72d0bab21..2ae355c244 100644 --- a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/type/TypeHierarchyNodeDescriptor.java +++ b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/type/TypeHierarchyNodeDescriptor.java @@ -32,67 +32,61 @@ import java.awt.*; -public final class TypeHierarchyNodeDescriptor extends HierarchyNodeDescriptor -{ - public TypeHierarchyNodeDescriptor(final Project project, final HierarchyNodeDescriptor parentDescriptor, final PsiElement classOrFunctionalExpression, final boolean isBase) - { - super(project, parentDescriptor, classOrFunctionalExpression, isBase); - } +public final class TypeHierarchyNodeDescriptor extends HierarchyNodeDescriptor { + public TypeHierarchyNodeDescriptor( + final Project project, + final HierarchyNodeDescriptor parentDescriptor, + final PsiElement classOrFunctionalExpression, + final boolean isBase + ) { + super(project, parentDescriptor, classOrFunctionalExpression, isBase); + } - public final PsiElement getPsiClass() - { - return getPsiElement(); - } + public final PsiElement getPsiClass() { + return getPsiElement(); + } - @RequiredUIAccess - public final boolean update() - { - boolean changes = super.update(); + @RequiredUIAccess + public final boolean update() { + boolean changes = super.update(); - if (getPsiElement() == null) - { - final String invalidPrefix = IdeLocalize.nodeHierarchyInvalid().get(); - if (!myHighlightedText.getText().startsWith(invalidPrefix)) - { - myHighlightedText.getBeginning().addText(invalidPrefix, HierarchyNodeDescriptor.getInvalidPrefixAttributes()); - } - return true; - } + if (getPsiElement() == null) { + final String invalidPrefix = IdeLocalize.nodeHierarchyInvalid().get(); + if (!myHighlightedText.getText().startsWith(invalidPrefix)) { + myHighlightedText.getBeginning().addText(invalidPrefix, HierarchyNodeDescriptor.getInvalidPrefixAttributes()); + } + return true; + } - if (changes && myIsBase) - { - setIcon(ImageEffects.appendRight(AllIcons.Hierarchy.Base, getIcon())); - } + if (changes && myIsBase) { + setIcon(ImageEffects.appendRight(AllIcons.Hierarchy.Base, getIcon())); + } - final PsiElement psiElement = getPsiClass(); + final PsiElement psiElement = getPsiClass(); - final CompositeAppearance oldText = myHighlightedText; + final CompositeAppearance oldText = myHighlightedText; - myHighlightedText = new CompositeAppearance(); + myHighlightedText = new CompositeAppearance(); - TextAttributes classNameAttributes = null; - if (myColor != null) - { - classNameAttributes = new TextAttributes(myColor, null, null, null, Font.PLAIN); - } - if (psiElement instanceof PsiClass psiClass) - { - myHighlightedText.getEnding().addText(ClassPresentationUtil.getNameForClass(psiClass, false), classNameAttributes); - myHighlightedText.getEnding().addText( - " (" + JavaHierarchyUtil.getPackageName(psiClass) + ")", - HierarchyNodeDescriptor.getPackageNameAttributes() - ); - } - else if (psiElement instanceof PsiFunctionalExpression functionalExpression) - { - myHighlightedText.getEnding().addText(ClassPresentationUtil.getFunctionalExpressionPresentation(functionalExpression, false)); - } - myName = myHighlightedText.getText(); + TextAttributes classNameAttributes = null; + if (myColor != null) { + classNameAttributes = new TextAttributes(myColor, null, null, null, Font.PLAIN); + } + if (psiElement instanceof PsiClass psiClass) { + myHighlightedText.getEnding().addText(ClassPresentationUtil.getNameForClass(psiClass, false), classNameAttributes); + myHighlightedText.getEnding().addText( + " (" + JavaHierarchyUtil.getPackageName(psiClass) + ")", + HierarchyNodeDescriptor.getPackageNameAttributes() + ); + } + else if (psiElement instanceof PsiFunctionalExpression functionalExpression) { + myHighlightedText.getEnding().addText(ClassPresentationUtil.getFunctionalExpressionPresentation(functionalExpression, false)); + } + myName = myHighlightedText.getText(); - if (!Comparing.equal(myHighlightedText, oldText)) - { - changes = true; - } - return changes; - } + if (!Comparing.equal(myHighlightedText, oldText)) { + changes = true; + } + return changes; + } } diff --git a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/type/TypeHierarchyTreeStructure.java b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/type/TypeHierarchyTreeStructure.java index 71ac8b763c..edc4254de9 100644 --- a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/type/TypeHierarchyTreeStructure.java +++ b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/type/TypeHierarchyTreeStructure.java @@ -23,52 +23,59 @@ import java.util.ArrayList; public final class TypeHierarchyTreeStructure extends SubtypesHierarchyTreeStructure { - - public TypeHierarchyTreeStructure(final Project project, final PsiClass aClass, String currentScopeType) { - super(project, buildHierarchyElement(project, aClass), currentScopeType); - setBaseElement(myBaseDescriptor); //to set myRoot - } - - private static HierarchyNodeDescriptor buildHierarchyElement(final Project project, final PsiClass aClass) { - HierarchyNodeDescriptor descriptor = null; - final PsiClass[] superClasses = createSuperClasses(aClass); - for(int i = superClasses.length - 1; i >= 0; i--){ - final PsiClass superClass = superClasses[i]; - final HierarchyNodeDescriptor newDescriptor = new TypeHierarchyNodeDescriptor(project, descriptor, superClass, false); - if (descriptor != null){ - descriptor.setCachedChildren(new HierarchyNodeDescriptor[] {newDescriptor}); - } - descriptor = newDescriptor; + public TypeHierarchyTreeStructure(final Project project, final PsiClass aClass, String currentScopeType) { + super(project, buildHierarchyElement(project, aClass), currentScopeType); + setBaseElement(myBaseDescriptor); //to set myRoot } - final HierarchyNodeDescriptor newDescriptor = new TypeHierarchyNodeDescriptor(project, descriptor, aClass, true); - if (descriptor != null) { - descriptor.setCachedChildren(new HierarchyNodeDescriptor[] {newDescriptor}); + + private static HierarchyNodeDescriptor buildHierarchyElement(final Project project, final PsiClass aClass) { + HierarchyNodeDescriptor descriptor = null; + final PsiClass[] superClasses = createSuperClasses(aClass); + for (int i = superClasses.length - 1; i >= 0; i--) { + final PsiClass superClass = superClasses[i]; + final HierarchyNodeDescriptor newDescriptor = new TypeHierarchyNodeDescriptor(project, descriptor, superClass, false); + if (descriptor != null) { + descriptor.setCachedChildren(new HierarchyNodeDescriptor[]{newDescriptor}); + } + descriptor = newDescriptor; + } + final HierarchyNodeDescriptor newDescriptor = new TypeHierarchyNodeDescriptor(project, descriptor, aClass, true); + if (descriptor != null) { + descriptor.setCachedChildren(new HierarchyNodeDescriptor[]{newDescriptor}); + } + return newDescriptor; } - return newDescriptor; - } - private static PsiClass[] createSuperClasses(PsiClass aClass) { - if (!aClass.isValid()) return PsiClass.EMPTY_ARRAY; - if (aClass.isInterface()) return PsiClass.EMPTY_ARRAY; + private static PsiClass[] createSuperClasses(PsiClass aClass) { + if (!aClass.isValid()) { + return PsiClass.EMPTY_ARRAY; + } + if (aClass.isInterface()) { + return PsiClass.EMPTY_ARRAY; + } - final ArrayList superClasses = new ArrayList(); - while (!JavaClassNames.JAVA_LANG_OBJECT.equals(aClass.getQualifiedName())) { - final PsiClass aClass1 = aClass; - final PsiClass[] superTypes = aClass1.getSupers(); - PsiClass superType = null; - for (int i = 0; i < superTypes.length; i++) { - final PsiClass type = superTypes[i]; - if (!type.isInterface()) { - superType = type; - break; + final ArrayList superClasses = new ArrayList(); + while (!JavaClassNames.JAVA_LANG_OBJECT.equals(aClass.getQualifiedName())) { + final PsiClass aClass1 = aClass; + final PsiClass[] superTypes = aClass1.getSupers(); + PsiClass superType = null; + for (int i = 0; i < superTypes.length; i++) { + final PsiClass type = superTypes[i]; + if (!type.isInterface()) { + superType = type; + break; + } + } + if (superType == null) { + break; + } + if (superClasses.contains(superType)) { + break; + } + superClasses.add(superType); + aClass = superType; } - } - if (superType == null) break; - if (superClasses.contains(superType)) break; - superClasses.add(superType); - aClass = superType; - } - return superClasses.toArray(new PsiClass[superClasses.size()]); - } + return superClasses.toArray(new PsiClass[superClasses.size()]); + } } From 082a9b3a30916446e63322d4a7d03cd8b3c253f1 Mon Sep 17 00:00:00 2001 From: UNV Date: Fri, 25 Apr 2025 20:58:53 +0300 Subject: [PATCH 2/2] Refactoring of hierarchy. --- .../impl/ide/hierarchy/JavaHierarchyUtil.java | 20 +-- .../hierarchy/call/CallHierarchyBrowser.java | 18 +-- .../call/CallHierarchyNodeDescriptor.java | 58 +++---- .../call/CalleeMethodsTreeStructure.java | 55 ++++--- .../call/CallerMethodsTreeStructure.java | 134 ++++++++-------- .../call/JavaCallHierarchyProvider.java | 12 +- .../method/ImplementMethodAction.java | 3 +- .../method/JavaMethodHierarchyProvider.java | 32 ++-- .../method/MethodHierarchyBrowser.java | 23 +-- .../method/MethodHierarchyNodeDescriptor.java | 54 +++---- .../method/MethodHierarchyTreeStructure.java | 144 +++++++++--------- .../hierarchy/method/MethodHierarchyUtil.java | 15 +- .../method/OverrideImplementMethodAction.java | 115 +++++++------- .../method/OverrideMethodAction.java | 3 +- .../type/JavaTypeHierarchyProvider.java | 28 ++-- .../type/SubtypesHierarchyTreeStructure.java | 18 +-- .../SupertypesHierarchyTreeStructure.java | 20 ++- .../hierarchy/type/TypeHierarchyBrowser.java | 27 ++-- .../type/TypeHierarchyNodeDescriptor.java | 14 +- .../type/TypeHierarchyTreeStructure.java | 21 ++- 20 files changed, 402 insertions(+), 412 deletions(-) diff --git a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/JavaHierarchyUtil.java b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/JavaHierarchyUtil.java index 403a9d3d30..deaf6ad7b8 100644 --- a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/JavaHierarchyUtil.java +++ b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/JavaHierarchyUtil.java @@ -35,22 +35,16 @@ private JavaHierarchyUtil() { } @Nullable - public static String getPackageName(final PsiClass psiClass) { - final PsiFile file = psiClass.getContainingFile(); - if (file instanceof PsiClassOwner) { - return ((PsiClassOwner)file).getPackageName(); - } - else { - return null; + public static String getPackageName(PsiClass psiClass) { + if (psiClass.getContainingFile() instanceof PsiClassOwner classOwner) { + return classOwner.getPackageName(); } + return null; } public static Comparator getComparator(Project project) { - if (HierarchyBrowserManager.getInstance(project).getState().SORT_ALPHABETICALLY) { - return AlphaComparator.INSTANCE; - } - else { - return SourceComparator.INSTANCE; - } + HierarchyBrowserManager.State state = HierarchyBrowserManager.getInstance(project).getState(); + assert state != null; + return state.SORT_ALPHABETICALLY ? AlphaComparator.INSTANCE : SourceComparator.INSTANCE; } } diff --git a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/call/CallHierarchyBrowser.java b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/call/CallHierarchyBrowser.java index 735e1da681..617cb45d5b 100644 --- a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/call/CallHierarchyBrowser.java +++ b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/call/CallHierarchyBrowser.java @@ -43,16 +43,16 @@ public CallHierarchyBrowser(@Nonnull Project project, @Nonnull PsiMethod method) } @Override - protected void createTrees(@Nonnull final Map type2TreeMap) { + protected void createTrees(@Nonnull Map type2TreeMap) { ActionGroup group = (ActionGroup)ActionManager.getInstance().getAction(IdeActions.GROUP_CALL_HIERARCHY_POPUP); - final JTree tree1 = createTree(false); + JTree tree1 = createTree(false); PopupHandler.installPopupHandler(tree1, group, ActionPlaces.CALL_HIERARCHY_VIEW_POPUP, ActionManager.getInstance()); - final BaseOnThisMethodAction baseOnThisMethodAction = new BaseOnThisMethodAction(); + BaseOnThisMethodAction baseOnThisMethodAction = new BaseOnThisMethodAction(); baseOnThisMethodAction .registerCustomShortcutSet(ActionManager.getInstance().getAction(IdeActions.ACTION_CALL_HIERARCHY).getShortcutSet(), tree1); type2TreeMap.put(CALLEE_TYPE, tree1); - final JTree tree2 = createTree(false); + JTree tree2 = createTree(false); PopupHandler.installPopupHandler(tree2, group, ActionPlaces.CALL_HIERARCHY_VIEW_POPUP, ActionManager.getInstance()); baseOnThisMethodAction .registerCustomShortcutSet(ActionManager.getInstance().getAction(IdeActions.ACTION_CALL_HIERARCHY).getShortcutSet(), tree2); @@ -61,8 +61,7 @@ protected void createTrees(@Nonnull final Map type2TreeMap) { @Override protected PsiElement getElementFromDescriptor(@Nonnull HierarchyNodeDescriptor descriptor) { - if (descriptor instanceof CallHierarchyNodeDescriptor) { - CallHierarchyNodeDescriptor nodeDescriptor = (CallHierarchyNodeDescriptor)descriptor; + if (descriptor instanceof CallHierarchyNodeDescriptor nodeDescriptor) { return nodeDescriptor.getEnclosingElement(); } return null; @@ -70,20 +69,19 @@ protected PsiElement getElementFromDescriptor(@Nonnull HierarchyNodeDescriptor d @Override protected PsiElement getOpenFileElementFromDescriptor(@Nonnull HierarchyNodeDescriptor descriptor) { - if (descriptor instanceof CallHierarchyNodeDescriptor) { - CallHierarchyNodeDescriptor nodeDescriptor = (CallHierarchyNodeDescriptor)descriptor; + if (descriptor instanceof CallHierarchyNodeDescriptor nodeDescriptor) { return nodeDescriptor.getTargetElement(); } return null; } @Override - protected boolean isApplicableElement(@Nonnull final PsiElement element) { + protected boolean isApplicableElement(@Nonnull PsiElement element) { return element instanceof PsiMethod; } @Override - protected HierarchyTreeStructure createHierarchyTreeStructure(@Nonnull final String typeName, @Nonnull final PsiElement psiElement) { + protected HierarchyTreeStructure createHierarchyTreeStructure(@Nonnull String typeName, @Nonnull PsiElement psiElement) { if (CALLER_TYPE.equals(typeName)) { return new CallerMethodsTreeStructure(myProject, (PsiMethod)psiElement, getCurrentScopeType()); } diff --git a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/call/CallHierarchyNodeDescriptor.java b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/call/CallHierarchyNodeDescriptor.java index 2745470baf..19e58ba53b 100644 --- a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/call/CallHierarchyNodeDescriptor.java +++ b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/call/CallHierarchyNodeDescriptor.java @@ -24,7 +24,6 @@ import com.intellij.java.language.psi.util.PsiFormatUtil; import com.intellij.java.language.psi.util.PsiFormatUtilBase; import consulo.annotation.access.RequiredReadAction; -import consulo.application.AllIcons; import consulo.codeEditor.Editor; import consulo.codeEditor.EditorColors; import consulo.codeEditor.markup.RangeHighlighter; @@ -45,6 +44,7 @@ import consulo.language.psi.SyntheticElement; import consulo.language.psi.util.PsiTreeUtil; import consulo.navigation.Navigatable; +import consulo.platform.base.icon.PlatformIconGroup; import consulo.project.Project; import consulo.ui.annotation.RequiredUIAccess; import consulo.ui.ex.awtUnsafe.TargetAWT; @@ -60,15 +60,15 @@ public final class CallHierarchyNodeDescriptor extends HierarchyNodeDescriptor implements Navigatable { private int myUsageCount = 1; - private final List myReferences = new ArrayList(); + private final List myReferences = new ArrayList<>(); private final boolean myNavigateToReference; public CallHierarchyNodeDescriptor( @Nonnull Project project, - final HierarchyNodeDescriptor parentDescriptor, + HierarchyNodeDescriptor parentDescriptor, @Nonnull PsiElement element, - final boolean isBase, - final boolean navigateToReference + boolean isBase, + boolean navigateToReference ) { super(project, parentDescriptor, element, isBase); myNavigateToReference = navigateToReference; @@ -82,7 +82,7 @@ public final PsiMember getEnclosingElement() { return element == null ? null : getEnclosingElement(element); } - public static PsiMember getEnclosingElement(final PsiElement element) { + public static PsiMember getEnclosingElement(PsiElement element) { return PsiTreeUtil.getNonStrictParentOfType(element, PsiMethod.class, PsiClass.class); } @@ -105,8 +105,8 @@ public final boolean isValid() { @Override @RequiredUIAccess public final boolean update() { - final CompositeAppearance oldText = myHighlightedText; - final Icon oldIcon = TargetAWT.to(getIcon()); + CompositeAppearance oldText = myHighlightedText; + Icon oldIcon = TargetAWT.to(getIcon()); int flags = Iconable.ICON_FLAG_VISIBILITY; if (isMarkReadOnly()) { @@ -115,10 +115,10 @@ public final boolean update() { boolean changes = super.update(); - final PsiElement enclosingElement = getEnclosingElement(); + PsiElement enclosingElement = getEnclosingElement(); if (enclosingElement == null) { - final String invalidPrefix = IdeLocalize.nodeHierarchyInvalid().get(); + String invalidPrefix = IdeLocalize.nodeHierarchyInvalid().get(); if (!myHighlightedText.getText().startsWith(invalidPrefix)) { myHighlightedText.getBeginning().addText(invalidPrefix, HierarchyNodeDescriptor.getInvalidPrefixAttributes()); } @@ -127,7 +127,7 @@ public final boolean update() { Image newIcon = IconDescriptorUpdaters.getIcon(enclosingElement, flags); if (changes && myIsBase) { - newIcon = ImageEffects.appendRight(AllIcons.Hierarchy.Base, newIcon); + newIcon = ImageEffects.appendRight(PlatformIconGroup.hierarchyBase(), newIcon); } setIcon(newIcon); @@ -145,14 +145,14 @@ public final boolean update() { ); } else { - final PsiMethod method = (PsiMethod)enclosingElement; - final StringBuilder buffer = new StringBuilder(128); - final PsiClass containingClass = method.getContainingClass(); + PsiMethod method = (PsiMethod)enclosingElement; + StringBuilder buffer = new StringBuilder(128); + PsiClass containingClass = method.getContainingClass(); if (containingClass != null) { buffer.append(ClassPresentationUtil.getNameForClass(containingClass, false)); buffer.append('.'); } - final String methodText = PsiFormatUtil.formatMethod( + String methodText = PsiFormatUtil.formatMethod( method, PsiSubstitutor.EMPTY, PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_PARAMETERS, @@ -175,10 +175,10 @@ public final boolean update() { ); } - final PsiClass containingClass = + PsiClass containingClass = enclosingElement instanceof PsiMethod method ? method.getContainingClass() : (PsiClass)enclosingElement; if (containingClass != null) { - final String packageName = JavaHierarchyUtil.getPackageName(containingClass); + String packageName = JavaHierarchyUtil.getPackageName(containingClass); myHighlightedText.getEnding().addText(" (" + packageName + ")", HierarchyNodeDescriptor.getPackageNameAttributes()); } @@ -190,7 +190,7 @@ public final boolean update() { return changes; } - public void addReference(final PsiReference reference) { + public void addReference(PsiReference reference) { myReferences.add(reference); } @@ -209,17 +209,17 @@ public void navigate(boolean requestFocus) { return; } - final PsiReference firstReference = myReferences.get(0); - final PsiElement element = firstReference.getElement(); + PsiReference firstReference = myReferences.get(0); + PsiElement element = firstReference.getElement(); if (element == null) { return; } - final PsiElement callElement = element.getParent(); + PsiElement callElement = element.getParent(); if (callElement instanceof Navigatable navigatable && navigatable.canNavigate()) { navigatable.navigate(requestFocus); } else { - final PsiFile psiFile = callElement.getContainingFile(); + PsiFile psiFile = callElement.getContainingFile(); if (psiFile == null || psiFile.getVirtualFile() == null) { return; } @@ -235,11 +235,11 @@ public void navigate(boolean requestFocus) { TextAttributes attributes = colorManager.getGlobalScheme().getAttributes(EditorColors.SEARCH_RESULT_ATTRIBUTES); ArrayList highlighters = new ArrayList<>(); for (PsiReference psiReference : myReferences) { - final PsiElement eachElement = psiReference.getElement(); + PsiElement eachElement = psiReference.getElement(); if (eachElement != null) { - final PsiElement eachMethodCall = eachElement.getParent(); + PsiElement eachMethodCall = eachElement.getParent(); if (eachMethodCall != null) { - final TextRange textRange = eachMethodCall.getTextRange(); + TextRange textRange = eachMethodCall.getTextRange(); highlightManager.addRangeHighlight( editor, textRange.getStartOffset(), @@ -255,6 +255,7 @@ public void navigate(boolean requestFocus) { } @Override + @RequiredReadAction public boolean canNavigate() { if (!myNavigateToReference) { PsiElement element = getPsiElement(); @@ -263,13 +264,13 @@ public boolean canNavigate() { if (myReferences.isEmpty()) { return false; } - final PsiReference firstReference = myReferences.get(0); - final PsiElement callElement = firstReference.getElement().getParent(); + PsiReference firstReference = myReferences.get(0); + PsiElement callElement = firstReference.getElement().getParent(); if (callElement == null || !callElement.isValid()) { return false; } if (!(callElement instanceof Navigatable navigatable && navigatable.canNavigate())) { - final PsiFile psiFile = callElement.getContainingFile(); + PsiFile psiFile = callElement.getContainingFile(); if (psiFile == null) { return false; } @@ -278,6 +279,7 @@ public boolean canNavigate() { } @Override + @RequiredReadAction public boolean canNavigateToSource() { return canNavigate(); } diff --git a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/call/CalleeMethodsTreeStructure.java b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/call/CalleeMethodsTreeStructure.java index 675347094a..2375b37b1a 100644 --- a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/call/CalleeMethodsTreeStructure.java +++ b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/call/CalleeMethodsTreeStructure.java @@ -15,6 +15,7 @@ */ package com.intellij.java.impl.ide.hierarchy.call; +import consulo.annotation.access.RequiredReadAction; import consulo.ide.impl.idea.ide.hierarchy.HierarchyNodeDescriptor; import consulo.ide.impl.idea.ide.hierarchy.HierarchyTreeStructure; import com.intellij.java.language.psi.*; @@ -32,33 +33,34 @@ public final class CalleeMethodsTreeStructure extends HierarchyTreeStructure { /** * Should be called in read action */ - public CalleeMethodsTreeStructure(final Project project, final PsiMethod method, final String scopeType) { + public CalleeMethodsTreeStructure(Project project, PsiMethod method, String scopeType) { super(project, new CallHierarchyNodeDescriptor(project, null, method, true, false)); myScopeType = scopeType; } - protected final Object[] buildChildren(final HierarchyNodeDescriptor descriptor) { - final PsiMember enclosingElement = ((CallHierarchyNodeDescriptor)descriptor).getEnclosingElement(); - if (!(enclosingElement instanceof PsiMethod)) { + @Override + @RequiredReadAction + protected final Object[] buildChildren(HierarchyNodeDescriptor descriptor) { + PsiMember enclosingElement = ((CallHierarchyNodeDescriptor)descriptor).getEnclosingElement(); + if (!(enclosingElement instanceof PsiMethod method)) { return ArrayUtil.EMPTY_OBJECT_ARRAY; } - final PsiMethod method = (PsiMethod)enclosingElement; - final ArrayList methods = new ArrayList(); + ArrayList methods = new ArrayList<>(); - final PsiCodeBlock body = method.getBody(); + PsiCodeBlock body = method.getBody(); if (body != null) { visitor(body, methods); } - final PsiMethod baseMethod = (PsiMethod)((CallHierarchyNodeDescriptor)getBaseDescriptor()).getTargetElement(); - final PsiClass baseClass = baseMethod.getContainingClass(); + PsiMethod baseMethod = (PsiMethod)((CallHierarchyNodeDescriptor)getBaseDescriptor()).getTargetElement(); + PsiClass baseClass = baseMethod.getContainingClass(); - final HashMap methodToDescriptorMap = new HashMap(); + HashMap methodToDescriptorMap = new HashMap<>(); - final ArrayList result = new ArrayList(); + ArrayList result = new ArrayList<>(); - for (final PsiMethod calledMethod : methods) { + for (PsiMethod calledMethod : methods) { if (!isInScope(baseClass, calledMethod, myScopeType)) { continue; } @@ -75,12 +77,13 @@ protected final Object[] buildChildren(final HierarchyNodeDescriptor descriptor) } // also add overriding methods as children - final PsiMethod[] overridingMethods = OverridingMethodsSearch.search(method, true).toArray(PsiMethod.EMPTY_ARRAY); - for (final PsiMethod overridingMethod : overridingMethods) { + PsiMethod[] overridingMethods = OverridingMethodsSearch.search(method, true).toArray(PsiMethod.EMPTY_ARRAY); + for (PsiMethod overridingMethod : overridingMethods) { if (!isInScope(baseClass, overridingMethod, myScopeType)) { continue; } - final CallHierarchyNodeDescriptor node = new CallHierarchyNodeDescriptor(myProject, descriptor, overridingMethod, false, false); + CallHierarchyNodeDescriptor node = + new CallHierarchyNodeDescriptor(myProject, descriptor, overridingMethod, false, false); if (!result.contains(node)) { result.add(node); } @@ -88,7 +91,7 @@ protected final Object[] buildChildren(final HierarchyNodeDescriptor descriptor) /* // show method implementations in EJB Class - final PsiMethod[] ejbImplementations = EjbUtil.findEjbImplementations(method, null); + PsiMethod[] ejbImplementations = EjbUtil.findEjbImplementations(method, null); for (int i = 0; i < ejbImplementations.length; i++) { PsiMethod ejbImplementation = ejbImplementations[i]; result.add(new CallHierarchyNodeDescriptor(myProject, descriptor, ejbImplementation, false)); @@ -97,22 +100,18 @@ protected final Object[] buildChildren(final HierarchyNodeDescriptor descriptor) return ArrayUtil.toObjectArray(result); } - - private static void visitor(final PsiElement element, final ArrayList methods) { - final PsiElement[] children = element.getChildren(); - for (final PsiElement child : children) { + @RequiredReadAction + private static void visitor(PsiElement element, ArrayList methods) { + PsiElement[] children = element.getChildren(); + for (PsiElement child : children) { visitor(child, methods); - if (child instanceof PsiMethodCallExpression) { - final PsiMethodCallExpression callExpression = (PsiMethodCallExpression)child; - final PsiReferenceExpression methodExpression = callExpression.getMethodExpression(); - final PsiMethod method = (PsiMethod)methodExpression.resolve(); - if (method != null) { + if (child instanceof PsiMethodCallExpression methodCall) { + if (methodCall.getMethodExpression().resolve() instanceof PsiMethod method) { methods.add(method); } } - else if (child instanceof PsiNewExpression) { - final PsiNewExpression newExpression = (PsiNewExpression)child; - final PsiMethod method = newExpression.resolveConstructor(); + else if (child instanceof PsiNewExpression newExpr) { + PsiMethod method = newExpr.resolveConstructor(); if (method != null) { methods.add(method); } diff --git a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/call/CallerMethodsTreeStructure.java b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/call/CallerMethodsTreeStructure.java index 46e25c560f..429746eedf 100644 --- a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/call/CallerMethodsTreeStructure.java +++ b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/call/CallerMethodsTreeStructure.java @@ -15,17 +15,17 @@ */ package com.intellij.java.impl.ide.hierarchy.call; -import consulo.ide.impl.idea.ide.hierarchy.HierarchyNodeDescriptor; -import consulo.ide.impl.idea.ide.hierarchy.HierarchyTreeStructure; -import com.intellij.java.language.psi.*; -import consulo.project.Project; -import consulo.language.psi.*; -import consulo.content.scope.SearchScope; import com.intellij.java.indexing.search.searches.MethodReferencesSearch; +import com.intellij.java.language.psi.*; import com.intellij.java.language.psi.util.PsiUtil; import com.intellij.java.language.psi.util.TypeConversionUtil; +import consulo.annotation.access.RequiredReadAction; +import consulo.content.scope.SearchScope; +import consulo.ide.impl.idea.ide.hierarchy.HierarchyNodeDescriptor; +import consulo.ide.impl.idea.ide.hierarchy.HierarchyTreeStructure; +import consulo.language.psi.PsiElement; +import consulo.project.Project; import consulo.util.collection.ArrayUtil; -import consulo.application.util.function.Processor; import consulo.util.collection.ContainerUtil; import java.util.HashMap; @@ -39,95 +39,93 @@ public final class CallerMethodsTreeStructure extends HierarchyTreeStructure { /** * Should be called in read action */ - public CallerMethodsTreeStructure(final Project project, final PsiMethod method, final String scopeType) { + public CallerMethodsTreeStructure(Project project, PsiMethod method, String scopeType) { super(project, new CallHierarchyNodeDescriptor(project, null, method, true, false)); myScopeType = scopeType; } @Override - protected final Object[] buildChildren(final HierarchyNodeDescriptor descriptor) { - final PsiMember enclosingElement = ((CallHierarchyNodeDescriptor)descriptor).getEnclosingElement(); + @RequiredReadAction + protected final Object[] buildChildren(HierarchyNodeDescriptor descriptor) { + PsiMember enclosingElement = ((CallHierarchyNodeDescriptor)descriptor).getEnclosingElement(); HierarchyNodeDescriptor nodeDescriptor = getBaseDescriptor(); if (!(enclosingElement instanceof PsiMethod) || nodeDescriptor == null) { return ArrayUtil.EMPTY_OBJECT_ARRAY; } - final PsiMethod method = (PsiMethod)enclosingElement; - final PsiMethod baseMethod = (PsiMethod)((CallHierarchyNodeDescriptor)nodeDescriptor).getTargetElement(); - final SearchScope searchScope = getSearchScope(myScopeType, baseMethod.getContainingClass()); + PsiMethod method = (PsiMethod)enclosingElement; + PsiMethod baseMethod = (PsiMethod)((CallHierarchyNodeDescriptor)nodeDescriptor).getTargetElement(); + SearchScope searchScope = getSearchScope(myScopeType, baseMethod.getContainingClass()); - final PsiClass originalClass = method.getContainingClass(); + PsiClass originalClass = method.getContainingClass(); assert originalClass != null; - final PsiClassType originalType = JavaPsiFacade.getElementFactory(myProject).createType(originalClass); - final Set methodsToFind = new HashSet(); + PsiClassType originalType = JavaPsiFacade.getElementFactory(myProject).createType(originalClass); + Set methodsToFind = new HashSet<>(); methodsToFind.add(method); ContainerUtil.addAll(methodsToFind, method.findDeepestSuperMethods()); - final Map methodToDescriptorMap = new HashMap(); - for (final PsiMethod methodToFind : methodsToFind) { - MethodReferencesSearch.search(methodToFind, searchScope, true).forEach(new Processor() { - @Override - public boolean process(final PsiReference reference) { - if (reference instanceof PsiReferenceExpression) { - final PsiExpression qualifier = ((PsiReferenceExpression)reference).getQualifierExpression(); - if (qualifier instanceof PsiSuperExpression) { // filter super.foo() call inside foo() and similar cases (bug 8411) - final PsiClass superClass = PsiUtil.resolveClassInType(qualifier.getType()); - if (originalClass.isInheritor(superClass, true)) { - return true; - } + Map methodToDescriptorMap = new HashMap<>(); + for (PsiMethod methodToFind : methodsToFind) { + MethodReferencesSearch.search(methodToFind, searchScope, true).forEach(reference -> { + if (reference instanceof PsiReferenceExpression refExpr) { + PsiExpression qualifier = refExpr.getQualifierExpression(); + if (qualifier instanceof PsiSuperExpression) { + // filter super.foo() call inside foo() and similar cases (bug 8411) + PsiClass superClass = PsiUtil.resolveClassInType(qualifier.getType()); + if (originalClass.isInheritor(superClass, true)) { + return true; } - if (qualifier != null && !methodToFind.hasModifierProperty(PsiModifier.STATIC)) { - final PsiType qualifierType = qualifier.getType(); - if (qualifierType instanceof PsiClassType && - !TypeConversionUtil.isAssignable(qualifierType, originalType) && - methodToFind != method) { - final PsiClass psiClass = ((PsiClassType)qualifierType).resolve(); - if (psiClass != null) { - final PsiMethod callee = psiClass.findMethodBySignature(methodToFind, true); - if (callee != null && !methodsToFind.contains(callee)) { - // skip sibling methods - return true; - } + } + if (qualifier != null && !methodToFind.isStatic()) { + PsiType qualifierType = qualifier.getType(); + if (qualifierType instanceof PsiClassType classType && + !TypeConversionUtil.isAssignable(classType, originalType) && methodToFind != method) { + PsiClass psiClass = classType.resolve(); + if (psiClass != null) { + PsiMethod callee = psiClass.findMethodBySignature(methodToFind, true); + if (callee != null && !methodsToFind.contains(callee)) { + // skip sibling methods + return true; } } } } - else { - if (!(reference instanceof PsiElement)) { - return true; - } + } + else { + if (!(reference instanceof PsiElement element)) { + return true; + } - final PsiElement parent = ((PsiElement)reference).getParent(); - if (parent instanceof PsiNewExpression) { - if (((PsiNewExpression)parent).getClassReference() != reference) { - return true; - } - } - else if (parent instanceof PsiAnonymousClass) { - if (((PsiAnonymousClass)parent).getBaseClassReference() != reference) { - return true; - } + PsiElement parent = element.getParent(); + if (parent instanceof PsiNewExpression newExpr) { + if (newExpr.getClassReference() != reference) { + return true; } - else { + } + else if (parent instanceof PsiAnonymousClass anonymousClass) { + if (anonymousClass.getBaseClassReference() != reference) { return true; } } + else { + return true; + } + } - final PsiElement element = reference.getElement(); - final PsiMember key = CallHierarchyNodeDescriptor.getEnclosingElement(element); + PsiElement element = reference.getElement(); + PsiMember key = CallHierarchyNodeDescriptor.getEnclosingElement(element); - synchronized (methodToDescriptorMap) { - CallHierarchyNodeDescriptor d = methodToDescriptorMap.get(key); - if (d == null) { - d = new CallHierarchyNodeDescriptor(myProject, descriptor, element, false, true); - methodToDescriptorMap.put(key, d); - } - else if (!d.hasReference(reference)) { - d.incrementUsageCount(); - } - d.addReference(reference); + synchronized (methodToDescriptorMap) { + CallHierarchyNodeDescriptor d = methodToDescriptorMap.get(key); + if (d == null) { + d = new CallHierarchyNodeDescriptor(myProject, descriptor, element, false, true); + methodToDescriptorMap.put(key, d); + } + else if (!d.hasReference(reference)) { + d.incrementUsageCount(); } - return true; + d.addReference(reference); } + return true; }); } diff --git a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/call/JavaCallHierarchyProvider.java b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/call/JavaCallHierarchyProvider.java index ae18053009..0e7a971977 100644 --- a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/call/JavaCallHierarchyProvider.java +++ b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/call/JavaCallHierarchyProvider.java @@ -17,6 +17,7 @@ import com.intellij.java.language.JavaLanguage; import com.intellij.java.language.psi.PsiMethod; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; import consulo.dataContext.DataContext; import consulo.ide.impl.idea.ide.hierarchy.CallHierarchyBrowserBase; @@ -35,24 +36,25 @@ @ExtensionImpl public class JavaCallHierarchyProvider implements CallHierarchyProvider { @Override - public PsiElement getTarget(@Nonnull final DataContext dataContext) { - final Project project = dataContext.getData(Project.KEY); + public PsiElement getTarget(@Nonnull DataContext dataContext) { + Project project = dataContext.getData(Project.KEY); if (project == null) { return null; } - final PsiElement element = dataContext.getData(PsiElement.KEY); + PsiElement element = dataContext.getData(PsiElement.KEY); return PsiTreeUtil.getParentOfType(element, PsiMethod.class, false); } @Override @Nonnull - public HierarchyBrowser createHierarchyBrowser(final PsiElement target) { + public HierarchyBrowser createHierarchyBrowser(PsiElement target) { return new CallHierarchyBrowser(target.getProject(), (PsiMethod)target); } @Override - public void browserActivated(@Nonnull final HierarchyBrowser hierarchyBrowser) { + @RequiredReadAction + public void browserActivated(@Nonnull HierarchyBrowser hierarchyBrowser) { ((CallHierarchyBrowser)hierarchyBrowser).changeView(CallHierarchyBrowserBase.CALLER_TYPE); } diff --git a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/ImplementMethodAction.java b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/ImplementMethodAction.java index fcd731a647..030bcf5e84 100644 --- a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/ImplementMethodAction.java +++ b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/ImplementMethodAction.java @@ -19,7 +19,8 @@ import consulo.ui.ex.action.Presentation; public final class ImplementMethodAction extends OverrideImplementMethodAction { - protected final void update(final Presentation presentation, final int toImplement, final int toOverride) { + @Override + protected final void update(Presentation presentation, int toImplement, int toOverride) { if (toImplement > 0) { presentation.setEnabled(true); presentation.setVisible(true); diff --git a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/JavaMethodHierarchyProvider.java b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/JavaMethodHierarchyProvider.java index 65b4d12da0..d812953e28 100644 --- a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/JavaMethodHierarchyProvider.java +++ b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/JavaMethodHierarchyProvider.java @@ -19,7 +19,6 @@ import com.intellij.java.language.psi.JavaTokenType; import com.intellij.java.language.psi.PsiJavaToken; import com.intellij.java.language.psi.PsiMethod; -import com.intellij.java.language.psi.PsiModifier; import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; import consulo.codeEditor.Editor; @@ -34,7 +33,6 @@ import consulo.language.psi.PsiWhiteSpace; import consulo.language.psi.util.PsiTreeUtil; import consulo.project.Project; - import jakarta.annotation.Nonnull; import jakarta.annotation.Nullable; @@ -43,46 +41,44 @@ */ @ExtensionImpl public class JavaMethodHierarchyProvider implements MethodHierarchyProvider { + @Override @RequiredReadAction - public PsiElement getTarget(@Nonnull final DataContext dataContext) { - final PsiMethod method = getMethodImpl(dataContext); - if (method != null && method.getContainingClass() != null && !method.hasModifierProperty(PsiModifier.PRIVATE) - && !method.hasModifierProperty(PsiModifier.STATIC)) { + public PsiElement getTarget(@Nonnull DataContext dataContext) { + PsiMethod method = getMethodImpl(dataContext); + if (method != null && method.getContainingClass() != null && !method.isPrivate() && !method.isStatic()) { return method; } - else { - return null; - } + return null; } @RequiredReadAction @Nullable - private static PsiMethod getMethodImpl(final DataContext dataContext) { - final Project project = dataContext.getData(Project.KEY); + private static PsiMethod getMethodImpl(DataContext dataContext) { + Project project = dataContext.getData(Project.KEY); if (project == null) { return null; } PsiElement element = dataContext.getData(PsiElement.KEY); - final PsiMethod method = PsiTreeUtil.getParentOfType(element, PsiMethod.class, false); + PsiMethod method = PsiTreeUtil.getParentOfType(element, PsiMethod.class, false); if (method != null) { return method; } - final Editor editor = dataContext.getData(Editor.KEY); + Editor editor = dataContext.getData(Editor.KEY); if (editor == null) { return null; } - final PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); + PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); if (psiFile == null) { return null; } PsiDocumentManager.getInstance(project).commitAllDocuments(); - final int offset = editor.getCaretModel().getOffset(); + int offset = editor.getCaretModel().getOffset(); if (offset < 1) { return null; } @@ -101,12 +97,14 @@ private static PsiMethod getMethodImpl(final DataContext dataContext) { } @Nonnull - public HierarchyBrowser createHierarchyBrowser(final PsiElement target) { + @Override + public HierarchyBrowser createHierarchyBrowser(PsiElement target) { return new MethodHierarchyBrowser(target.getProject(), (PsiMethod)target); } + @Override @RequiredReadAction - public void browserActivated(@Nonnull final HierarchyBrowser hierarchyBrowser) { + public void browserActivated(@Nonnull HierarchyBrowser hierarchyBrowser) { ((MethodHierarchyBrowser)hierarchyBrowser).changeView(MethodHierarchyBrowserBase.METHOD_TYPE); } diff --git a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/MethodHierarchyBrowser.java b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/MethodHierarchyBrowser.java index 7ceab713d5..0f27652dce 100644 --- a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/MethodHierarchyBrowser.java +++ b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/MethodHierarchyBrowser.java @@ -40,22 +40,24 @@ public class MethodHierarchyBrowser extends MethodHierarchyBrowserBase { private static final Logger LOG = Logger.getInstance(MethodHierarchyBrowser.class); - public MethodHierarchyBrowser(final Project project, final PsiMethod method) { + public MethodHierarchyBrowser(Project project, PsiMethod method) { super(project, method); } + @Override protected void createTrees(@Nonnull Map trees) { - final JTree tree = createTree(false); + JTree tree = createTree(false); ActionGroup group = (ActionGroup)ActionManager.getInstance().getAction(IdeActions.GROUP_METHOD_HIERARCHY_POPUP); PopupHandler.installPopupHandler(tree, group, ActionPlaces.METHOD_HIERARCHY_VIEW_POPUP, ActionManager.getInstance()); - final BaseOnThisMethodAction baseOnThisMethodAction = new BaseOnThisMethodAction(); + BaseOnThisMethodAction baseOnThisMethodAction = new BaseOnThisMethodAction(); baseOnThisMethodAction .registerCustomShortcutSet(ActionManager.getInstance().getAction(IdeActions.ACTION_METHOD_HIERARCHY).getShortcutSet(), tree); trees.put(METHOD_TYPE, tree); } + @Override protected JPanel createLegendPanel() { return createStandardLegendPanel( IdeLocalize.hierarchyLegendMethodIsDefinedInClass().get(), @@ -64,17 +66,19 @@ protected JPanel createLegendPanel() { ); } - - protected PsiElement getElementFromDescriptor(@Nonnull final HierarchyNodeDescriptor descriptor) { + @Override + protected PsiElement getElementFromDescriptor(@Nonnull HierarchyNodeDescriptor descriptor) { return descriptor instanceof MethodHierarchyNodeDescriptor methodHierarchyNodeDescriptor ? methodHierarchyNodeDescriptor.getTargetElement() : null; } - protected boolean isApplicableElement(@Nonnull final PsiElement psiElement) { + @Override + protected boolean isApplicableElement(@Nonnull PsiElement psiElement) { return psiElement instanceof PsiMethod; } - protected HierarchyTreeStructure createHierarchyTreeStructure(@Nonnull final String typeName, @Nonnull final PsiElement psiElement) { + @Override + protected HierarchyTreeStructure createHierarchyTreeStructure(@Nonnull String typeName, @Nonnull PsiElement psiElement) { if (!METHOD_TYPE.equals(typeName)) { LOG.error("unexpected type: " + typeName); return null; @@ -82,13 +86,14 @@ protected HierarchyTreeStructure createHierarchyTreeStructure(@Nonnull final Str return new MethodHierarchyTreeStructure(myProject, (PsiMethod)psiElement); } + @Override protected Comparator getComparator() { return JavaHierarchyUtil.getComparator(myProject); } public PsiMethod getBaseMethod() { - final HierarchyTreeBuilder builder = myBuilders.get(myCurrentViewType); - final MethodHierarchyTreeStructure treeStructure = (MethodHierarchyTreeStructure)builder.getTreeStructure(); + HierarchyTreeBuilder builder = myBuilders.get(myCurrentViewType); + MethodHierarchyTreeStructure treeStructure = (MethodHierarchyTreeStructure)builder.getTreeStructure(); return treeStructure.getBaseMethod(); } diff --git a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/MethodHierarchyNodeDescriptor.java b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/MethodHierarchyNodeDescriptor.java index 3aa4165dc8..c3d174f0dd 100644 --- a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/MethodHierarchyNodeDescriptor.java +++ b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/MethodHierarchyNodeDescriptor.java @@ -20,8 +20,6 @@ import com.intellij.java.language.psi.PsiClass; import com.intellij.java.language.psi.PsiFunctionalExpression; import com.intellij.java.language.psi.PsiMethod; -import com.intellij.java.language.psi.PsiModifier; -import consulo.application.AllIcons; import consulo.colorScheme.TextAttributes; import consulo.component.util.Iconable; import consulo.ide.impl.idea.ide.hierarchy.HierarchyNodeDescriptor; @@ -29,6 +27,7 @@ import consulo.ide.localize.IdeLocalize; import consulo.language.icon.IconDescriptorUpdaters; import consulo.language.psi.PsiElement; +import consulo.platform.base.icon.PlatformIconGroup; import consulo.project.Project; import consulo.ui.annotation.RequiredUIAccess; import consulo.ui.image.Image; @@ -43,21 +42,21 @@ public final class MethodHierarchyNodeDescriptor extends HierarchyNodeDescriptor private MethodHierarchyTreeStructure myTreeStructure; public MethodHierarchyNodeDescriptor( - final Project project, - final HierarchyNodeDescriptor parentDescriptor, - final PsiElement aClass, - final boolean isBase, - final MethodHierarchyTreeStructure treeStructure + Project project, + HierarchyNodeDescriptor parentDescriptor, + PsiElement aClass, + boolean isBase, + MethodHierarchyTreeStructure treeStructure ) { super(project, parentDescriptor, aClass, isBase); myTreeStructure = treeStructure; } - public final void setTreeStructure(final MethodHierarchyTreeStructure treeStructure) { + public final void setTreeStructure(MethodHierarchyTreeStructure treeStructure) { myTreeStructure = treeStructure; } - PsiMethod getMethod(final PsiClass aClass, final boolean checkBases) { + PsiMethod getMethod(PsiClass aClass, boolean checkBases) { return MethodHierarchyUtil.findBaseMethodInClass(myTreeStructure.getBaseMethod(), aClass, checkBases); } @@ -69,15 +68,14 @@ public final PsiElement getPsiClass() { * Element for OpenFileDescriptor */ public final PsiElement getTargetElement() { - final PsiElement element = getPsiClass(); - if (!(element instanceof PsiClass)) { + PsiElement element = getPsiClass(); + if (!(element instanceof PsiClass aClass)) { return element; } - final PsiClass aClass = (PsiClass)getPsiClass(); if (!aClass.isValid()) { return null; } - final PsiMethod method = getMethod(aClass, false); + PsiMethod method = getMethod(aClass, false); if (method != null) { return method; } @@ -94,18 +92,18 @@ public final boolean update() { boolean changes = super.update(); - final PsiElement aClass = getPsiClass(); + PsiElement aClass = getPsiClass(); if (aClass == null) { - final String invalidPrefix = IdeLocalize.nodeHierarchyInvalid().get(); + String invalidPrefix = IdeLocalize.nodeHierarchyInvalid().get(); if (!myHighlightedText.getText().startsWith(invalidPrefix)) { myHighlightedText.getBeginning().addText(invalidPrefix, HierarchyNodeDescriptor.getInvalidPrefixAttributes()); } return true; } - final Image newRawIcon = IconDescriptorUpdaters.getIcon(aClass, flags); - final Image newStateIcon = aClass instanceof PsiClass psiClass ? calculateState(psiClass) : AllIcons.Hierarchy.MethodDefined; + Image newRawIcon = IconDescriptorUpdaters.getIcon(aClass, flags); + Image newStateIcon = aClass instanceof PsiClass psiClass ? calculateState(psiClass) : PlatformIconGroup.hierarchyMethoddefined(); if (changes || newRawIcon != myRawIcon || newStateIcon != myStateIcon) { changes = true; @@ -116,7 +114,7 @@ public final boolean update() { Image newIcon = myRawIcon; if (myIsBase) { - newIcon = ImageEffects.appendRight(AllIcons.Hierarchy.Base, newIcon); + newIcon = ImageEffects.appendRight(PlatformIconGroup.hierarchyBase(), newIcon); } if (myStateIcon != null) { @@ -126,7 +124,7 @@ public final boolean update() { setIcon(newIcon); } - final CompositeAppearance oldText = myHighlightedText; + CompositeAppearance oldText = myHighlightedText; myHighlightedText = new CompositeAppearance(); TextAttributes classNameAttributes = null; @@ -152,23 +150,25 @@ else if (aClass instanceof PsiFunctionalExpression functionalExpression) { return changes; } - private Image calculateState(final PsiClass psiClass) { - final PsiMethod method = getMethod(psiClass, false); + private Image calculateState(PsiClass psiClass) { + PsiMethod method = getMethod(psiClass, false); if (method != null) { - return method.hasModifierProperty(PsiModifier.ABSTRACT) ? null : AllIcons.Hierarchy.MethodDefined; + return method.isAbstract() ? null : PlatformIconGroup.hierarchyMethoddefined(); } if (myTreeStructure.isSuperClassForBaseClass(psiClass)) { - return AllIcons.Hierarchy.MethodNotDefined; + return PlatformIconGroup.hierarchyMethodnotdefined(); } - final boolean isAbstractClass = psiClass.hasModifierProperty(PsiModifier.ABSTRACT); + boolean isAbstractClass = psiClass.isAbstract(); // was it implemented is in superclasses? - final PsiMethod baseClassMethod = getMethod(psiClass, true); + PsiMethod baseClassMethod = getMethod(psiClass, true); - final boolean hasBaseImplementation = baseClassMethod != null && !baseClassMethod.hasModifierProperty(PsiModifier.ABSTRACT); + boolean hasBaseImplementation = baseClassMethod != null && !baseClassMethod.isAbstract(); - return hasBaseImplementation || isAbstractClass ? AllIcons.Hierarchy.MethodNotDefined : AllIcons.Hierarchy.ShouldDefineMethod; + return hasBaseImplementation || isAbstractClass + ? PlatformIconGroup.hierarchyMethodnotdefined() + : PlatformIconGroup.hierarchyShoulddefinemethod(); } } diff --git a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/MethodHierarchyTreeStructure.java b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/MethodHierarchyTreeStructure.java index 10a04749c6..1b0683f514 100644 --- a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/MethodHierarchyTreeStructure.java +++ b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/MethodHierarchyTreeStructure.java @@ -15,32 +15,34 @@ */ package com.intellij.java.impl.ide.hierarchy.method; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; - -import jakarta.annotation.Nonnull; +import com.intellij.java.indexing.search.searches.ClassInheritorsSearch; +import com.intellij.java.indexing.search.searches.FunctionalExpressionSearch; +import com.intellij.java.language.psi.*; +import consulo.annotation.access.RequiredReadAction; import consulo.ide.impl.idea.ide.hierarchy.HierarchyBrowserManager; import consulo.ide.impl.idea.ide.hierarchy.HierarchyNodeDescriptor; import consulo.ide.impl.idea.ide.hierarchy.HierarchyTreeStructure; -import com.intellij.java.language.psi.*; +import consulo.java.language.module.util.JavaClassNames; +import consulo.language.psi.PsiElement; +import consulo.language.psi.SmartPointerManager; +import consulo.language.psi.SmartPsiElementPointer; import consulo.project.Project; -import consulo.language.psi.*; -import com.intellij.java.indexing.search.searches.ClassInheritorsSearch; -import com.intellij.java.indexing.search.searches.FunctionalExpressionSearch; import consulo.util.collection.ArrayUtil; -import consulo.application.util.function.Processor; -import consulo.java.language.module.util.JavaClassNames; +import jakarta.annotation.Nonnull; import jakarta.annotation.Nullable; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + public final class MethodHierarchyTreeStructure extends HierarchyTreeStructure { private final SmartPsiElementPointer myMethod; /** * Should be called in read action */ - public MethodHierarchyTreeStructure(final Project project, final PsiMethod method) { + public MethodHierarchyTreeStructure(Project project, PsiMethod method) { super(project, null); myBaseDescriptor = buildHierarchyElement(project, method); ((MethodHierarchyNodeDescriptor)myBaseDescriptor).setTreeStructure(this); @@ -48,11 +50,11 @@ public MethodHierarchyTreeStructure(final Project project, final PsiMethod metho setBaseElement(myBaseDescriptor); //to set myRoot } - private HierarchyNodeDescriptor buildHierarchyElement(final Project project, final PsiMethod method) { - final PsiClass suitableBaseClass = findSuitableBaseClass(method); + private HierarchyNodeDescriptor buildHierarchyElement(Project project, PsiMethod method) { + PsiClass suitableBaseClass = findSuitableBaseClass(method); HierarchyNodeDescriptor descriptor = null; - final ArrayList superClasses = createSuperClasses(suitableBaseClass); + ArrayList superClasses = createSuperClasses(suitableBaseClass); if (!suitableBaseClass.equals(method.getContainingClass())) { superClasses.add(0, suitableBaseClass); @@ -60,7 +62,7 @@ private HierarchyNodeDescriptor buildHierarchyElement(final Project project, fin // remove from the top of the branch the classes that contain no 'method' for (int i = superClasses.size() - 1; i >= 0; i--) { - final PsiClass psiClass = superClasses.get(i); + PsiClass psiClass = superClasses.get(i); if (MethodHierarchyUtil.findBaseMethodInClass(method, psiClass, false) == null) { superClasses.remove(i); @@ -71,15 +73,15 @@ private HierarchyNodeDescriptor buildHierarchyElement(final Project project, fin } for (int i = superClasses.size() - 1; i >= 0; i--) { - final PsiClass superClass = superClasses.get(i); - final HierarchyNodeDescriptor newDescriptor = + PsiClass superClass = superClasses.get(i); + HierarchyNodeDescriptor newDescriptor = new MethodHierarchyNodeDescriptor(project, descriptor, superClass, false, this); if (descriptor != null) { descriptor.setCachedChildren(new HierarchyNodeDescriptor[]{newDescriptor}); } descriptor = newDescriptor; } - final HierarchyNodeDescriptor newDescriptor = + HierarchyNodeDescriptor newDescriptor = new MethodHierarchyNodeDescriptor(project, descriptor, method.getContainingClass(), true, this); if (descriptor != null) { descriptor.setCachedChildren(new HierarchyNodeDescriptor[]{newDescriptor}); @@ -89,16 +91,16 @@ private HierarchyNodeDescriptor buildHierarchyElement(final Project project, fin private static ArrayList createSuperClasses(PsiClass aClass) { if (!aClass.isValid()) { - return new ArrayList(); + return new ArrayList<>(); } - final ArrayList superClasses = new ArrayList(); + ArrayList superClasses = new ArrayList<>(); while (!isJavaLangObject(aClass)) { - final PsiClass aClass1 = aClass; - final PsiClass[] superTypes = aClass1.getSupers(); + PsiClass aClass1 = aClass; + PsiClass[] superTypes = aClass1.getSupers(); PsiClass superType = null; // find class first - for (final PsiClass type : superTypes) { + for (PsiClass type : superTypes) { if (!type.isInterface() && !isJavaLangObject(type)) { superType = type; break; @@ -106,7 +108,7 @@ private static ArrayList createSuperClasses(PsiClass aClass) { } // if we haven't found a class, try to find an interface if (superType == null) { - for (final PsiClass type : superTypes) { + for (PsiClass type : superTypes) { if (!isJavaLangObject(type)) { superType = type; break; @@ -126,24 +128,24 @@ private static ArrayList createSuperClasses(PsiClass aClass) { return superClasses; } - private static boolean isJavaLangObject(final PsiClass aClass) { + private static boolean isJavaLangObject(PsiClass aClass) { return JavaClassNames.JAVA_LANG_OBJECT.equals(aClass.getQualifiedName()); } - private static PsiClass findSuitableBaseClass(final PsiMethod method) { - final PsiClass containingClass = method.getContainingClass(); + private static PsiClass findSuitableBaseClass(PsiMethod method) { + PsiClass containingClass = method.getContainingClass(); if (containingClass instanceof PsiAnonymousClass) { return containingClass; } - final PsiClass superClass = containingClass.getSuperClass(); + PsiClass superClass = containingClass.getSuperClass(); if (superClass == null) { return containingClass; } if (MethodHierarchyUtil.findBaseMethodInClass(method, superClass, true) == null) { - for (final PsiClass anInterface : containingClass.getInterfaces()) { + for (PsiClass anInterface : containingClass.getInterfaces()) { if (MethodHierarchyUtil.findBaseMethodInClass(method, anInterface, true) != null) { return anInterface; } @@ -154,69 +156,66 @@ private static PsiClass findSuitableBaseClass(final PsiMethod method) { } @Nullable + @RequiredReadAction public final PsiMethod getBaseMethod() { - final PsiElement element = myMethod.getElement(); - return element instanceof PsiMethod ? (PsiMethod)element : null; + return myMethod.getElement() instanceof PsiMethod method ? method : null; } - @Nonnull @Override - protected final Object[] buildChildren(@Nonnull final HierarchyNodeDescriptor descriptor) { - final PsiElement psiElement = ((MethodHierarchyNodeDescriptor)descriptor).getPsiClass(); - if (!(psiElement instanceof PsiClass)) { + @RequiredReadAction + protected final Object[] buildChildren(@Nonnull HierarchyNodeDescriptor descriptor) { + PsiElement psiElement = ((MethodHierarchyNodeDescriptor)descriptor).getPsiClass(); + if (!(psiElement instanceof PsiClass psiClass)) { return ArrayUtil.EMPTY_OBJECT_ARRAY; } - final PsiClass psiClass = (PsiClass)psiElement; - final Collection subclasses = getSubclasses(psiClass); - - final List descriptors = new ArrayList(subclasses.size()); - for (final PsiClass aClass : subclasses) { - if (HierarchyBrowserManager.getInstance(myProject).getState().HIDE_CLASSES_WHERE_METHOD_NOT_IMPLEMENTED) { - if (shouldHideClass(aClass)) { - continue; - } + Collection subclasses = getSubclasses(psiClass); + + List descriptors = new ArrayList<>(subclasses.size()); + for (PsiClass aClass : subclasses) { + HierarchyBrowserManager.State state = HierarchyBrowserManager.getInstance(myProject).getState(); + assert state != null; + if (state.HIDE_CLASSES_WHERE_METHOD_NOT_IMPLEMENTED && shouldHideClass(aClass)) { + continue; } - final MethodHierarchyNodeDescriptor d = new MethodHierarchyNodeDescriptor(myProject, descriptor, aClass, false, this); + MethodHierarchyNodeDescriptor d = new MethodHierarchyNodeDescriptor(myProject, descriptor, aClass, false, this); descriptors.add(d); } - final PsiMethod existingMethod = ((MethodHierarchyNodeDescriptor)descriptor).getMethod(psiClass, false); + PsiMethod existingMethod = ((MethodHierarchyNodeDescriptor)descriptor).getMethod(psiClass, false); if (existingMethod != null) { - FunctionalExpressionSearch.search(existingMethod).forEach(new Processor() { - @Override - public boolean process(PsiFunctionalExpression expression) { - descriptors.add(new MethodHierarchyNodeDescriptor( - myProject, - descriptor, - expression, - false, - MethodHierarchyTreeStructure.this - )); - return true; - } + FunctionalExpressionSearch.search(existingMethod).forEach(expression -> { + descriptors.add(new MethodHierarchyNodeDescriptor( + myProject, + descriptor, + expression, + false, + MethodHierarchyTreeStructure.this + )); + return true; }); } return descriptors.toArray(new HierarchyNodeDescriptor[descriptors.size()]); } - private static Collection getSubclasses(final PsiClass psiClass) { - if (psiClass instanceof PsiAnonymousClass || psiClass.hasModifierProperty(PsiModifier.FINAL)) { + private static Collection getSubclasses(PsiClass psiClass) { + if (psiClass instanceof PsiAnonymousClass || psiClass.isFinal()) { return Collections.emptyList(); } return ClassInheritorsSearch.search(psiClass, false).findAll(); } - private boolean shouldHideClass(final PsiClass psiClass) { + @RequiredReadAction + private boolean shouldHideClass(PsiClass psiClass) { if (getMethod(psiClass, false) != null || isSuperClassForBaseClass(psiClass)) { return false; } if (hasBaseClassMethod(psiClass) || isAbstract(psiClass)) { - for (final PsiClass subclass : getSubclasses(psiClass)) { + for (PsiClass subclass : getSubclasses(psiClass)) { if (!shouldHideClass(subclass)) { return false; } @@ -227,25 +226,28 @@ private boolean shouldHideClass(final PsiClass psiClass) { return false; } - private boolean isAbstract(final PsiModifierListOwner owner) { + private boolean isAbstract(PsiModifierListOwner owner) { return owner.hasModifierProperty(PsiModifier.ABSTRACT); } - private boolean hasBaseClassMethod(final PsiClass psiClass) { - final PsiMethod baseClassMethod = getMethod(psiClass, true); + @RequiredReadAction + private boolean hasBaseClassMethod(PsiClass psiClass) { + PsiMethod baseClassMethod = getMethod(psiClass, true); return baseClassMethod != null && !isAbstract(baseClassMethod); } - private PsiMethod getMethod(final PsiClass aClass, final boolean checkBases) { + @RequiredReadAction + private PsiMethod getMethod(PsiClass aClass, boolean checkBases) { return MethodHierarchyUtil.findBaseMethodInClass(getBaseMethod(), aClass, checkBases); } - boolean isSuperClassForBaseClass(final PsiClass aClass) { - final PsiMethod baseMethod = getBaseMethod(); + @RequiredReadAction + boolean isSuperClassForBaseClass(PsiClass aClass) { + PsiMethod baseMethod = getBaseMethod(); if (baseMethod == null) { return false; } - final PsiClass baseClass = baseMethod.getContainingClass(); + PsiClass baseClass = baseMethod.getContainingClass(); if (baseClass == null) { return false; } diff --git a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/MethodHierarchyUtil.java b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/MethodHierarchyUtil.java index 8416fdf5ea..5fc8643596 100644 --- a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/MethodHierarchyUtil.java +++ b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/MethodHierarchyUtil.java @@ -17,11 +17,10 @@ import com.intellij.java.language.psi.PsiClass; import com.intellij.java.language.psi.PsiMethod; -import com.intellij.java.language.psi.PsiModifier; import com.intellij.java.language.psi.util.MethodSignatureUtil; final class MethodHierarchyUtil { - public static PsiMethod findBaseMethodInClass(final PsiMethod baseMethod, final PsiClass aClass, final boolean checkBases) { + public static PsiMethod findBaseMethodInClass(PsiMethod baseMethod, PsiClass aClass, boolean checkBases) { if (baseMethod == null) { return null; // base method is invalid } @@ -30,16 +29,12 @@ public static PsiMethod findBaseMethodInClass(final PsiMethod baseMethod, final } /*if (!checkBases) return MethodSignatureUtil.findMethodBySignature(aClass, signature, false);*/ return MethodSignatureUtil.findMethodBySuperMethod(aClass, baseMethod, checkBases); - /*final MethodSignatureBackedByPsiMethod signature = SuperMethodsSearch.search(baseMethod, aClass, checkBases, false).findFirst(); + /*MethodSignatureBackedByPsiMethod signature = SuperMethodsSearch.search(baseMethod, aClass, checkBases, false).findFirst(); return signature == null ? null : signature.getMethod();*/ } - private static boolean cannotBeOverridding(final PsiMethod method) { - final PsiClass parentClass = method.getContainingClass(); - return parentClass == null - || method.isConstructor() - || method.hasModifierProperty(PsiModifier.STATIC) - || method.hasModifierProperty(PsiModifier.PRIVATE); + private static boolean cannotBeOverridding(PsiMethod method) { + PsiClass parentClass = method.getContainingClass(); + return parentClass == null || method.isConstructor() || method.isStatic() || method.isPrivate(); } - } diff --git a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/OverrideImplementMethodAction.java b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/OverrideImplementMethodAction.java index a2efaa6e70..b5b2a27c3b 100644 --- a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/OverrideImplementMethodAction.java +++ b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/OverrideImplementMethodAction.java @@ -29,6 +29,7 @@ import consulo.language.psi.PsiElement; import consulo.language.psi.PsiFile; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; import consulo.logging.Logger; import consulo.project.Project; import consulo.project.ui.wm.ToolWindowManager; @@ -51,91 +52,86 @@ abstract class OverrideImplementMethodAction extends AnAction { @RequiredUIAccess @Override - public final void actionPerformed(@Nonnull final AnActionEvent event) { - final DataContext dataContext = event.getDataContext(); - final MethodHierarchyBrowser methodHierarchyBrowser = - (MethodHierarchyBrowser)dataContext.getData(MethodHierarchyBrowserBase.DATA_KEY); + public final void actionPerformed(@Nonnull AnActionEvent event) { + DataContext dataContext = event.getDataContext(); + MethodHierarchyBrowser methodHierarchyBrowser = (MethodHierarchyBrowser)dataContext.getData(MethodHierarchyBrowserBase.DATA_KEY); if (methodHierarchyBrowser == null) { return; } - final Project project = dataContext.getData(Project.KEY); + Project project = dataContext.getData(Project.KEY); if (project == null) { return; } - final String commandName = event.getPresentation().getText(); - Application.get().runWriteAction(() -> CommandProcessor.getInstance().executeCommand( - project, - new Runnable() { - @Override - @RequiredUIAccess - public void run() { - try { - final HierarchyNodeDescriptor[] selectedDescriptors = methodHierarchyBrowser.getSelectedDescriptors(); - if (selectedDescriptors.length > 0) { - final List files = new ArrayList<>(selectedDescriptors.length); - for (HierarchyNodeDescriptor selectedDescriptor : selectedDescriptors) { - final PsiFile containingFile = - ((MethodHierarchyNodeDescriptor)selectedDescriptor).getPsiClass().getContainingFile(); - if (containingFile != null) { - final VirtualFile vFile = containingFile.getVirtualFile(); - if (vFile != null) { - files.add(vFile); - } + LocalizeValue commandName = event.getPresentation().getTextValue(); + CommandProcessor.getInstance().newCommand() + .project(project) + .name(commandName) + .inWriteAction() + .run(() -> { + try { + HierarchyNodeDescriptor[] selectedDescriptors = methodHierarchyBrowser.getSelectedDescriptors(); + if (selectedDescriptors.length > 0) { + List files = new ArrayList<>(selectedDescriptors.length); + for (HierarchyNodeDescriptor selectedDescriptor : selectedDescriptors) { + PsiFile containingFile = + ((MethodHierarchyNodeDescriptor)selectedDescriptor).getPsiClass().getContainingFile(); + if (containingFile != null) { + VirtualFile vFile = containingFile.getVirtualFile(); + if (vFile != null) { + files.add(vFile); } } - final ReadonlyStatusHandler.OperationStatus status = - ReadonlyStatusHandler.getInstance(project).ensureFilesWritable(VfsUtil.toVirtualFileArray(files)); - if (!status.hasReadonlyFiles()) { - for (HierarchyNodeDescriptor selectedDescriptor : selectedDescriptors) { - final PsiElement aClass = ((MethodHierarchyNodeDescriptor)selectedDescriptor).getPsiClass(); - if (aClass instanceof PsiClass psiClass) { - OverrideImplementUtil.overrideOrImplement(psiClass, methodHierarchyBrowser.getBaseMethod()); - } + } + ReadonlyStatusHandler.OperationStatus status = + ReadonlyStatusHandler.getInstance(project).ensureFilesWritable(VfsUtil.toVirtualFileArray(files)); + if (!status.hasReadonlyFiles()) { + for (HierarchyNodeDescriptor selectedDescriptor : selectedDescriptors) { + PsiElement aClass = ((MethodHierarchyNodeDescriptor)selectedDescriptor).getPsiClass(); + if (aClass instanceof PsiClass psiClass) { + OverrideImplementUtil.overrideOrImplement(psiClass, methodHierarchyBrowser.getBaseMethod()); } - ToolWindowManager.getInstance(project).activateEditorComponent(); - } - else { - Application.get() - .invokeLater(() -> Messages.showErrorDialog(project, status.getReadonlyFilesMessage(), commandName)); } + ToolWindowManager.getInstance(project).activateEditorComponent(); + } + else { + Application.get().invokeLater( + () -> Messages.showErrorDialog(project, status.getReadonlyFilesMessage(), commandName.get()) + ); } } - catch (IncorrectOperationException e) { - LOG.error(e); - } } - }, - commandName, - null - )); + catch (IncorrectOperationException e) { + LOG.error(e); + } + }); } @RequiredUIAccess @Override - public final void update(@Nonnull final AnActionEvent e) { - final Presentation presentation = e.getPresentation(); - final DataContext dataContext = e.getDataContext(); + public final void update(@Nonnull AnActionEvent e) { + Presentation presentation = e.getPresentation(); + DataContext dataContext = e.getDataContext(); - final MethodHierarchyBrowser methodHierarchyBrowser = + MethodHierarchyBrowser methodHierarchyBrowser = (MethodHierarchyBrowser)dataContext.getData(MethodHierarchyBrowserBase.DATA_KEY); if (methodHierarchyBrowser == null) { presentation.setEnabled(false); presentation.setVisible(false); return; } - final Project project = dataContext.getData(Project.KEY); + Project project = dataContext.getData(Project.KEY); if (project == null) { presentation.setEnabled(false); presentation.setVisible(false); return; } - final HierarchyNodeDescriptor[] selectedDescriptors = methodHierarchyBrowser.getSelectedDescriptors(); + HierarchyNodeDescriptor[] selectedDescriptors = methodHierarchyBrowser.getSelectedDescriptors(); int toImplement = 0; int toOverride = 0; - for (final HierarchyNodeDescriptor descriptor : selectedDescriptors) { + for (HierarchyNodeDescriptor descriptor : selectedDescriptors) { if (canImplementOverride((MethodHierarchyNodeDescriptor)descriptor, methodHierarchyBrowser, true)) { if (toOverride > 0) { // no mixed actions allowed @@ -170,28 +166,27 @@ else if (canImplementOverride((MethodHierarchyNodeDescriptor)descriptor, methodH protected abstract void update(Presentation presentation, int toImplement, int toOverride); private static boolean canImplementOverride( - final MethodHierarchyNodeDescriptor descriptor, - final MethodHierarchyBrowser methodHierarchyBrowser, - final boolean toImplement + MethodHierarchyNodeDescriptor descriptor, + MethodHierarchyBrowser methodHierarchyBrowser, + boolean toImplement ) { - final PsiElement psiElement = descriptor.getPsiClass(); - if (!(psiElement instanceof PsiClass)) { + PsiElement psiElement = descriptor.getPsiClass(); + if (!(psiElement instanceof PsiClass psiClass)) { return false; } - final PsiClass psiClass = (PsiClass)psiElement; if (psiClass instanceof PsiSyntheticClass) { return false; } - final PsiMethod baseMethod = methodHierarchyBrowser.getBaseMethod(); + PsiMethod baseMethod = methodHierarchyBrowser.getBaseMethod(); if (baseMethod == null) { return false; } - final MethodSignature signature = baseMethod.getSignature(PsiSubstitutor.EMPTY); + MethodSignature signature = baseMethod.getSignature(PsiSubstitutor.EMPTY); Collection allOriginalSignatures = toImplement ? OverrideImplementUtil.getMethodSignaturesToImplement(psiClass) : OverrideImplementUtil.getMethodSignaturesToOverride(psiClass); - for (final MethodSignature originalSignature : allOriginalSignatures) { + for (MethodSignature originalSignature : allOriginalSignatures) { if (originalSignature.equals(signature)) { return true; } diff --git a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/OverrideMethodAction.java b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/OverrideMethodAction.java index 9a6badfab6..447014ccd3 100644 --- a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/OverrideMethodAction.java +++ b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/method/OverrideMethodAction.java @@ -19,7 +19,8 @@ import consulo.ui.ex.action.Presentation; public final class OverrideMethodAction extends OverrideImplementMethodAction { - protected final void update(final Presentation presentation, final int toImplement, final int toOverride) { + @Override + protected final void update(Presentation presentation, int toImplement, int toOverride) { if (toOverride > 0) { presentation.setEnabled(true); presentation.setVisible(true); diff --git a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/type/JavaTypeHierarchyProvider.java b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/type/JavaTypeHierarchyProvider.java index 417afbcced..acca4af7f4 100644 --- a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/type/JavaTypeHierarchyProvider.java +++ b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/type/JavaTypeHierarchyProvider.java @@ -20,6 +20,7 @@ import com.intellij.java.language.psi.PsiClass; import com.intellij.java.language.psi.PsiClassOwner; import com.intellij.java.language.psi.PsiSyntheticClass; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; import consulo.codeEditor.Editor; import consulo.dataContext.DataContext; @@ -45,20 +46,20 @@ public class JavaTypeHierarchyProvider implements TypeHierarchyProvider { @Override @RequiredUIAccess - public PsiElement getTarget(@Nonnull final DataContext dataContext) { - final Project project = dataContext.getData(Project.KEY); + public PsiElement getTarget(@Nonnull DataContext dataContext) { + Project project = dataContext.getData(Project.KEY); if (project == null) { return null; } - final Editor editor = dataContext.getData(Editor.KEY); + Editor editor = dataContext.getData(Editor.KEY); if (editor != null) { - final PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); + PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); if (file == null) { return null; } - final PsiElement targetElement = TargetElementUtil.findTargetElement( + PsiElement targetElement = TargetElementUtil.findTargetElement( editor, Set.of( TargetElementUtilExtender.ELEMENT_NAME_ACCEPTED, @@ -70,14 +71,14 @@ public PsiElement getTarget(@Nonnull final DataContext dataContext) { return targetElement; } - final int offset = editor.getCaretModel().getOffset(); + int offset = editor.getCaretModel().getOffset(); PsiElement element = file.findElementAt(offset); while (element != null) { if (element instanceof PsiFile) { - if (!(element instanceof PsiClassOwner)) { + if (!(element instanceof PsiClassOwner classOwner)) { return null; } - final PsiClass[] classes = ((PsiClassOwner)element).getClasses(); + PsiClass[] classes = classOwner.getClasses(); return classes.length == 1 ? classes[0] : null; } if (element instanceof PsiClass && !(element instanceof PsiAnonymousClass) && !(element instanceof PsiSyntheticClass)) { @@ -89,21 +90,22 @@ public PsiElement getTarget(@Nonnull final DataContext dataContext) { return null; } else { - final PsiElement element = dataContext.getData(PsiElement.KEY); + PsiElement element = dataContext.getData(PsiElement.KEY); return element instanceof PsiClass psiClass ? psiClass : null; } } @Override @Nonnull - public HierarchyBrowser createHierarchyBrowser(final PsiElement target) { + public HierarchyBrowser createHierarchyBrowser(PsiElement target) { return new TypeHierarchyBrowser(target.getProject(), (PsiClass)target); } @Override - public void browserActivated(@Nonnull final HierarchyBrowser hierarchyBrowser) { - final TypeHierarchyBrowser browser = (TypeHierarchyBrowser)hierarchyBrowser; - final String typeName = browser.isInterface() + @RequiredReadAction + public void browserActivated(@Nonnull HierarchyBrowser hierarchyBrowser) { + TypeHierarchyBrowser browser = (TypeHierarchyBrowser)hierarchyBrowser; + String typeName = browser.isInterface() ? TypeHierarchyBrowserBase.SUBTYPES_HIERARCHY_TYPE : TypeHierarchyBrowserBase.TYPE_HIERARCHY_TYPE; browser.changeView(typeName); } diff --git a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/type/SubtypesHierarchyTreeStructure.java b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/type/SubtypesHierarchyTreeStructure.java index d19ce3702d..cdc86a51b5 100644 --- a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/type/SubtypesHierarchyTreeStructure.java +++ b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/type/SubtypesHierarchyTreeStructure.java @@ -19,7 +19,6 @@ import com.intellij.java.indexing.search.searches.FunctionalExpressionSearch; import com.intellij.java.language.psi.PsiAnonymousClass; import com.intellij.java.language.psi.PsiClass; -import com.intellij.java.language.psi.PsiModifier; import consulo.content.scope.SearchScope; import consulo.ide.impl.idea.ide.hierarchy.HierarchyNodeDescriptor; import consulo.ide.impl.idea.ide.hierarchy.HierarchyTreeStructure; @@ -35,7 +34,7 @@ public class SubtypesHierarchyTreeStructure extends HierarchyTreeStructure { private final String myCurrentScopeType; - protected SubtypesHierarchyTreeStructure(final Project project, final HierarchyNodeDescriptor descriptor, String currentScopeType) { + protected SubtypesHierarchyTreeStructure(Project project, HierarchyNodeDescriptor descriptor, String currentScopeType) { super(project, descriptor); myCurrentScopeType = currentScopeType; } @@ -47,24 +46,23 @@ public SubtypesHierarchyTreeStructure(Project project, PsiClass psiClass, String @Override @Nonnull - protected final Object[] buildChildren(@Nonnull final HierarchyNodeDescriptor descriptor) { - final Object element = ((TypeHierarchyNodeDescriptor)descriptor).getPsiClass(); - if (!(element instanceof PsiClass)) { + protected final Object[] buildChildren(@Nonnull HierarchyNodeDescriptor descriptor) { + Object element = ((TypeHierarchyNodeDescriptor)descriptor).getPsiClass(); + if (!(element instanceof PsiClass psiClass)) { return ArrayUtil.EMPTY_OBJECT_ARRAY; } - final PsiClass psiClass = (PsiClass)element; if (JavaClassNames.JAVA_LANG_OBJECT.equals(psiClass.getQualifiedName())) { return new Object[]{IdeLocalize.nodeHierarchyJavaLangObject().get()}; } if (psiClass instanceof PsiAnonymousClass) { return ArrayUtil.EMPTY_OBJECT_ARRAY; } - if (psiClass.hasModifierProperty(PsiModifier.FINAL)) { + if (psiClass.isFinal()) { return ArrayUtil.EMPTY_OBJECT_ARRAY; } - final SearchScope searchScope = psiClass.getUseScope().intersectWith(getSearchScope(myCurrentScopeType, psiClass)); - final List classes = new ArrayList<>(ClassInheritorsSearch.search(psiClass, searchScope, false).findAll()); - final List descriptors = new ArrayList<>(classes.size()); + SearchScope searchScope = psiClass.getUseScope().intersectWith(getSearchScope(myCurrentScopeType, psiClass)); + List classes = new ArrayList<>(ClassInheritorsSearch.search(psiClass, searchScope, false).findAll()); + List descriptors = new ArrayList<>(classes.size()); for (PsiClass aClass : classes) { descriptors.add(new TypeHierarchyNodeDescriptor(myProject, descriptor, aClass, false)); } diff --git a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/type/SupertypesHierarchyTreeStructure.java b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/type/SupertypesHierarchyTreeStructure.java index 393379312d..3644c212c3 100644 --- a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/type/SupertypesHierarchyTreeStructure.java +++ b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/type/SupertypesHierarchyTreeStructure.java @@ -31,19 +31,18 @@ import consulo.util.collection.ArrayUtil; public final class SupertypesHierarchyTreeStructure extends HierarchyTreeStructure { - public SupertypesHierarchyTreeStructure(final Project project, final PsiClass aClass) { + public SupertypesHierarchyTreeStructure(Project project, PsiClass aClass) { super(project, new TypeHierarchyNodeDescriptor(project, null, aClass, true)); } @Override @Nonnull - protected final Object[] buildChildren(@Nonnull final HierarchyNodeDescriptor descriptor) { - final Object element = ((TypeHierarchyNodeDescriptor)descriptor).getPsiClass(); - if (element instanceof PsiClass) { - final PsiClass psiClass = (PsiClass)element; - final PsiClass[] supers = psiClass.getSupers(); - final List descriptors = new ArrayList(); - final PsiClass objectClass = + protected final Object[] buildChildren(@Nonnull HierarchyNodeDescriptor descriptor) { + Object element = ((TypeHierarchyNodeDescriptor)descriptor).getPsiClass(); + if (element instanceof PsiClass psiClass) { + PsiClass[] supers = psiClass.getSupers(); + List descriptors = new ArrayList<>(); + PsiClass objectClass = JavaPsiFacade.getInstance(myProject).findClass(JavaClassNames.JAVA_LANG_OBJECT, psiClass.getResolveScope()); for (PsiClass aSuper : supers) { if (!psiClass.isInterface() || !aSuper.equals(objectClass)) { @@ -52,9 +51,8 @@ protected final Object[] buildChildren(@Nonnull final HierarchyNodeDescriptor de } return descriptors.toArray(new HierarchyNodeDescriptor[descriptors.size()]); } - else if (element instanceof PsiFunctionalExpression) { - final PsiClass functionalInterfaceClass = - PsiUtil.resolveClassInType(((PsiFunctionalExpression)element).getFunctionalInterfaceType()); + else if (element instanceof PsiFunctionalExpression funcExpr) { + PsiClass functionalInterfaceClass = PsiUtil.resolveClassInType(funcExpr.getFunctionalInterfaceType()); if (functionalInterfaceClass != null) { return new HierarchyNodeDescriptor[]{new TypeHierarchyNodeDescriptor( myProject, diff --git a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/type/TypeHierarchyBrowser.java b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/type/TypeHierarchyBrowser.java index a80425c879..6067c42784 100644 --- a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/type/TypeHierarchyBrowser.java +++ b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/type/TypeHierarchyBrowser.java @@ -19,6 +19,7 @@ import java.util.Comparator; import java.util.Map; +import consulo.annotation.access.RequiredReadAction; import jakarta.annotation.Nonnull; import javax.swing.JPanel; @@ -45,13 +46,13 @@ public class TypeHierarchyBrowser extends TypeHierarchyBrowserBase { private static final Logger LOG = Logger.getInstance(TypeHierarchyBrowser.class); - public TypeHierarchyBrowser(final Project project, final PsiClass psiClass) { + public TypeHierarchyBrowser(Project project, PsiClass psiClass) { super(project, psiClass); } @Override protected boolean isInterface(PsiElement psiElement) { - return psiElement instanceof PsiClass && ((PsiClass)psiElement).isInterface(); + return psiElement instanceof PsiClass psiClass && psiClass.isInterface(); } @Override @@ -71,16 +72,17 @@ protected boolean isEnabled() { } @Override + @RequiredReadAction protected String getContentDisplayName(@Nonnull String typeName, @Nonnull PsiElement element) { return MessageFormat.format(typeName, ClassPresentationUtil.getNameForClass((PsiClass)element, false)); } @Override protected PsiElement getElementFromDescriptor(@Nonnull HierarchyNodeDescriptor descriptor) { - if (!(descriptor instanceof TypeHierarchyNodeDescriptor)) { - return null; + if (descriptor instanceof TypeHierarchyNodeDescriptor nodeDescriptor) { + return nodeDescriptor.getPsiClass(); } - return ((TypeHierarchyNodeDescriptor)descriptor).getPsiClass(); + return null; } @Override @@ -90,7 +92,7 @@ protected JPanel createLegendPanel() { } @Override - protected boolean isApplicableElement(@Nonnull final PsiElement element) { + protected boolean isApplicableElement(@Nonnull PsiElement element) { return element instanceof PsiClass; } @@ -100,7 +102,7 @@ protected Comparator getComparator() { } @Override - protected HierarchyTreeStructure createHierarchyTreeStructure(@Nonnull final String typeName, @Nonnull final PsiElement psiElement) { + protected HierarchyTreeStructure createHierarchyTreeStructure(@Nonnull String typeName, @Nonnull PsiElement psiElement) { if (SUPERTYPES_HIERARCHY_TYPE.equals(typeName)) { return new SupertypesHierarchyTreeStructure(myProject, (PsiClass)psiElement); } @@ -117,20 +119,21 @@ else if (TYPE_HIERARCHY_TYPE.equals(typeName)) { } @Override - protected boolean canBeDeleted(final PsiElement psiElement) { + protected boolean canBeDeleted(PsiElement psiElement) { return psiElement instanceof PsiClass && !(psiElement instanceof PsiAnonymousClass); } @Override - protected String getQualifiedName(final PsiElement psiElement) { - if (psiElement instanceof PsiClass) { - return ((PsiClass)psiElement).getQualifiedName(); + protected String getQualifiedName(PsiElement psiElement) { + if (psiElement instanceof PsiClass psiClass) { + return psiClass.getQualifiedName(); } return ""; } public static class BaseOnThisTypeAction extends TypeHierarchyBrowserBase.BaseOnThisTypeAction { - protected boolean isEnabled(@Nonnull final HierarchyBrowserBaseEx browser, @Nonnull final PsiElement psiElement) { + @Override + protected boolean isEnabled(@Nonnull HierarchyBrowserBaseEx browser, @Nonnull PsiElement psiElement) { return super.isEnabled(browser, psiElement) && !JavaClassNames.JAVA_LANG_OBJECT.equals(((PsiClass)psiElement).getQualifiedName()); } diff --git a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/type/TypeHierarchyNodeDescriptor.java b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/type/TypeHierarchyNodeDescriptor.java index 2ae355c244..f955d2a303 100644 --- a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/type/TypeHierarchyNodeDescriptor.java +++ b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/type/TypeHierarchyNodeDescriptor.java @@ -34,10 +34,10 @@ public final class TypeHierarchyNodeDescriptor extends HierarchyNodeDescriptor { public TypeHierarchyNodeDescriptor( - final Project project, - final HierarchyNodeDescriptor parentDescriptor, - final PsiElement classOrFunctionalExpression, - final boolean isBase + Project project, + HierarchyNodeDescriptor parentDescriptor, + PsiElement classOrFunctionalExpression, + boolean isBase ) { super(project, parentDescriptor, classOrFunctionalExpression, isBase); } @@ -51,7 +51,7 @@ public final boolean update() { boolean changes = super.update(); if (getPsiElement() == null) { - final String invalidPrefix = IdeLocalize.nodeHierarchyInvalid().get(); + String invalidPrefix = IdeLocalize.nodeHierarchyInvalid().get(); if (!myHighlightedText.getText().startsWith(invalidPrefix)) { myHighlightedText.getBeginning().addText(invalidPrefix, HierarchyNodeDescriptor.getInvalidPrefixAttributes()); } @@ -62,9 +62,9 @@ public final boolean update() { setIcon(ImageEffects.appendRight(AllIcons.Hierarchy.Base, getIcon())); } - final PsiElement psiElement = getPsiClass(); + PsiElement psiElement = getPsiClass(); - final CompositeAppearance oldText = myHighlightedText; + CompositeAppearance oldText = myHighlightedText; myHighlightedText = new CompositeAppearance(); diff --git a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/type/TypeHierarchyTreeStructure.java b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/type/TypeHierarchyTreeStructure.java index edc4254de9..c0cae4ba17 100644 --- a/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/type/TypeHierarchyTreeStructure.java +++ b/plugin/src/main/java/com/intellij/java/impl/ide/hierarchy/type/TypeHierarchyTreeStructure.java @@ -23,23 +23,23 @@ import java.util.ArrayList; public final class TypeHierarchyTreeStructure extends SubtypesHierarchyTreeStructure { - public TypeHierarchyTreeStructure(final Project project, final PsiClass aClass, String currentScopeType) { + public TypeHierarchyTreeStructure(Project project, PsiClass aClass, String currentScopeType) { super(project, buildHierarchyElement(project, aClass), currentScopeType); setBaseElement(myBaseDescriptor); //to set myRoot } - private static HierarchyNodeDescriptor buildHierarchyElement(final Project project, final PsiClass aClass) { + private static HierarchyNodeDescriptor buildHierarchyElement(Project project, PsiClass aClass) { HierarchyNodeDescriptor descriptor = null; - final PsiClass[] superClasses = createSuperClasses(aClass); + PsiClass[] superClasses = createSuperClasses(aClass); for (int i = superClasses.length - 1; i >= 0; i--) { - final PsiClass superClass = superClasses[i]; - final HierarchyNodeDescriptor newDescriptor = new TypeHierarchyNodeDescriptor(project, descriptor, superClass, false); + PsiClass superClass = superClasses[i]; + HierarchyNodeDescriptor newDescriptor = new TypeHierarchyNodeDescriptor(project, descriptor, superClass, false); if (descriptor != null) { descriptor.setCachedChildren(new HierarchyNodeDescriptor[]{newDescriptor}); } descriptor = newDescriptor; } - final HierarchyNodeDescriptor newDescriptor = new TypeHierarchyNodeDescriptor(project, descriptor, aClass, true); + HierarchyNodeDescriptor newDescriptor = new TypeHierarchyNodeDescriptor(project, descriptor, aClass, true); if (descriptor != null) { descriptor.setCachedChildren(new HierarchyNodeDescriptor[]{newDescriptor}); } @@ -54,13 +54,12 @@ private static PsiClass[] createSuperClasses(PsiClass aClass) { return PsiClass.EMPTY_ARRAY; } - final ArrayList superClasses = new ArrayList(); + ArrayList superClasses = new ArrayList<>(); while (!JavaClassNames.JAVA_LANG_OBJECT.equals(aClass.getQualifiedName())) { - final PsiClass aClass1 = aClass; - final PsiClass[] superTypes = aClass1.getSupers(); + PsiClass aClass1 = aClass; + PsiClass[] superTypes = aClass1.getSupers(); PsiClass superType = null; - for (int i = 0; i < superTypes.length; i++) { - final PsiClass type = superTypes[i]; + for (PsiClass type : superTypes) { if (!type.isInterface()) { superType = type; break;