From d08f10e8bc1e31742102c6cb9552a7d1095aa0c4 Mon Sep 17 00:00:00 2001 From: fedejeanne Date: Mon, 20 Jan 2025 15:38:58 +0100 Subject: [PATCH] Do not expand same class twice in (quick) type hierarchy Fixes eclipse-jdt#1830 --- org.eclipse.jdt.ui/.settings/.api_filters | 8 +++++ .../HierarchyInformationControl.java | 30 +++++++++++++++- .../typehierarchy/TypeHierarchyViewPart.java | 7 +++- .../ui/typehierarchy/TypeHierarchyViewer.java | 36 +++++++++++++++++++ 4 files changed, 79 insertions(+), 2 deletions(-) diff --git a/org.eclipse.jdt.ui/.settings/.api_filters b/org.eclipse.jdt.ui/.settings/.api_filters index b181190c4ad..ab29fec0ba9 100644 --- a/org.eclipse.jdt.ui/.settings/.api_filters +++ b/org.eclipse.jdt.ui/.settings/.api_filters @@ -137,6 +137,14 @@ + + + + + + + + diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/typehierarchy/HierarchyInformationControl.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/typehierarchy/HierarchyInformationControl.java index fe4cf55e3ad..33a0ae879ee 100644 --- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/typehierarchy/HierarchyInformationControl.java +++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/typehierarchy/HierarchyInformationControl.java @@ -14,6 +14,8 @@ package org.eclipse.jdt.internal.ui.typehierarchy; import java.lang.reflect.InvocationTargetException; +import java.util.HashSet; +import java.util.Set; import org.eclipse.swt.SWT; import org.eclipse.swt.events.KeyAdapter; @@ -23,6 +25,7 @@ import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; import org.eclipse.swt.widgets.Tree; +import org.eclipse.swt.widgets.Widget; import org.eclipse.jface.bindings.TriggerSequence; import org.eclipse.jface.bindings.keys.KeySequence; @@ -130,7 +133,32 @@ protected TreeViewer createTreeViewer(Composite parent, int style) { gd.heightHint= tree.getItemHeight() * 12; tree.setLayoutData(gd); - TreeViewer treeViewer= new TreeViewer(tree); + TreeViewer treeViewer= new TreeViewer(tree) { + private Set visited; + + @Override + protected void inputChanged(Object input, Object oldInput) { + visited= new HashSet<>(); + super.inputChanged(input, oldInput); + visited= null; + } + + @Override + protected void internalExpandToLevel(Widget node, int level) { + if (!shouldExpand(node)) + return; + + super.internalExpandToLevel(node, level); + } + + private boolean shouldExpand(Widget widget) { + if (widget == null) { + return false; + } + Object data= widget.getData(); + return data == null || visited.add(data); + } + }; treeViewer.addFilter(new ViewerFilter() { @Override public boolean select(Viewer viewer, Object parentElement, Object element) { diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/typehierarchy/TypeHierarchyViewPart.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/typehierarchy/TypeHierarchyViewPart.java index 285e509ea7a..3d41b627128 100644 --- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/typehierarchy/TypeHierarchyViewPart.java +++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/typehierarchy/TypeHierarchyViewPart.java @@ -1212,7 +1212,12 @@ private void updateHierarchyViewer(final boolean doExpand) { fPagebook.showPage(fNoHierarchyShownLabel); } else { if (getCurrentViewer().containsElements() != null) { - Runnable runnable= () -> JavaCore.runReadOnly(() -> getCurrentViewer().updateContent(doExpand)); + Runnable runnable= () -> JavaCore.runReadOnly(() -> { + TypeHierarchyViewer viewer= getCurrentViewer(); + viewer.preUpdateContent(); + viewer.updateContent(doExpand); + viewer.postUpdateContent(); + }); BusyIndicator.showWhile(getDisplay(), runnable); if (!isChildVisible(fViewerbook, getCurrentViewer().getControl())) { setViewerVisibility(true); diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/typehierarchy/TypeHierarchyViewer.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/typehierarchy/TypeHierarchyViewer.java index f8f3c9d72dd..357fabf1d9e 100644 --- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/typehierarchy/TypeHierarchyViewer.java +++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/typehierarchy/TypeHierarchyViewer.java @@ -13,10 +13,14 @@ *******************************************************************************/ package org.eclipse.jdt.internal.ui.typehierarchy; +import java.util.HashSet; +import java.util.Set; + import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.Tree; +import org.eclipse.swt.widgets.Widget; import org.eclipse.core.runtime.Assert; @@ -42,6 +46,8 @@ public abstract class TypeHierarchyViewer extends ProblemTreeViewer { private HierarchyLabelProvider fLabelProvider; + private Set visited; + public TypeHierarchyViewer(Composite parent, IContentProvider contentProvider, TypeHierarchyLifeCycle lifeCycle) { super(new Tree(parent, SWT.SINGLE)); @@ -182,4 +188,34 @@ protected TypeHierarchyContentProvider getHierarchyContentProvider() { return (TypeHierarchyContentProvider)getContentProvider(); } + @Override + protected void inputChanged(Object input, Object oldInput) { + preUpdateContent(); + super.inputChanged(input, oldInput); + postUpdateContent(); + } + + @Override + protected void internalExpandToLevel(Widget node, int level) { + if (!shouldExpand(node)) + return; + + super.internalExpandToLevel(node, level); + } + + private boolean shouldExpand(Widget widget) { + if (widget == null) { + return false; + } + Object data= widget.getData(); + return data == null || visited.add(data); + } + + void preUpdateContent() { + visited= new HashSet<>(); + } + + void postUpdateContent() { + visited= null; + } }