diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/callhierarchy/CallHierarchyContentProvider.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/callhierarchy/CallHierarchyContentProvider.java index 3fb2fdf113e..404f026161f 100644 --- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/callhierarchy/CallHierarchyContentProvider.java +++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/callhierarchy/CallHierarchyContentProvider.java @@ -20,7 +20,6 @@ import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.jface.operation.IRunnableContext; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.viewers.AbstractTreeViewer; import org.eclipse.jface.viewers.ITreeContentProvider; @@ -47,6 +46,9 @@ import org.eclipse.jdt.internal.ui.JavaPlugin; import org.eclipse.jdt.internal.ui.util.ExceptionHandler; +/** + * Content provider for call hierarchy. + */ public class CallHierarchyContentProvider implements ITreeContentProvider { /** @@ -57,215 +59,218 @@ public class CallHierarchyContentProvider implements ITreeContentProvider { * It has been replaced in 3.6 by API: * {@link PreferenceConstants#PREF_DEFAULT_EXPAND_WITH_CONSTRUCTORS_MEMBERS} *

- * * @since 3.5 */ - public static final String OLD_PREF_DEFAULT_EXPAND_WITH_CONSTRUCTORS= "CallHierarchy.defaultExpandWithConstructors"; //$NON-NLS-1$ + public static final String OLD_PREF_DEFAULT_EXPAND_WITH_CONSTRUCTORS + = "CallHierarchy.defaultExpandWithConstructors"; //$NON-NLS-1$ - private final static Object[] EMPTY_ARRAY= new Object[0]; + /** Empty object array. */ + private static final Object[] EMPTY_ARRAY = new Object[0]; + /** Tree content manager. */ + private DeferredTreeContentManager fManager; + /** View part. */ + private CallHierarchyViewPart fPart; - private DeferredTreeContentManager fManager; - private CallHierarchyViewPart fPart; + /** + * Class representing a method wrapper runnable. + */ + private static class MethodWrapperRunnable implements IRunnableWithProgress { + /** Method wrapper. */ + private MethodWrapper fMethodWrapper; + /** The calls. */ + private MethodWrapper[] fCalls = null; + + /** + * Constructor. + * @param methodWrapper Method wrapper + */ + MethodWrapperRunnable(MethodWrapper methodWrapper) { + fMethodWrapper = methodWrapper; + } - private static class MethodWrapperRunnable implements IRunnableWithProgress { - private MethodWrapper fMethodWrapper; - private MethodWrapper[] fCalls= null; + /** + * {@inheritDoc} + * @see org.eclipse.jface.operation.IRunnableWithProgress#run(IProgressMonitor) + */ + @Override + public void run(IProgressMonitor pm) { + fCalls = fMethodWrapper.getCalls(pm); + } - MethodWrapperRunnable(MethodWrapper methodWrapper) { - fMethodWrapper= methodWrapper; - } + /** + * Answers the calls. + * @return The calls + */ + MethodWrapper[] getCalls() { + return fCalls == null ? new MethodWrapper[0] : fCalls; + } + } - @Override - public void run(IProgressMonitor pm) { - fCalls= fMethodWrapper.getCalls(pm); - } - - MethodWrapper[] getCalls() { - if (fCalls != null) { - return fCalls; - } - return new MethodWrapper[0]; - } - } - - public CallHierarchyContentProvider(CallHierarchyViewPart part) { - super(); - fPart= part; - } - - /** - * @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object) - */ + /** + * Constructor. + * @param part Call hierarchy view part + */ + public CallHierarchyContentProvider(CallHierarchyViewPart part) { + super(); + fPart = part; + } + + /** + * {@inheritDoc} + * @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object) + */ @Override public Object[] getChildren(Object parentElement) { - if (parentElement instanceof TreeRoot) { - TreeRoot dummyRoot= (TreeRoot)parentElement; - return dummyRoot.getRoots(); - - } else if (parentElement instanceof RealCallers) { - MethodWrapper parentWrapper= ((RealCallers)parentElement).getParent(); - RealCallers element= ((RealCallers)parentElement); + if (parentElement instanceof TreeRoot tr) { + return tr.getRoots(); + } + if (parentElement instanceof RealCallers rc) { + MethodWrapper parentWrapper = rc.getParent(); if (fManager != null) { - Object[] children= fManager.getChildren(new DeferredMethodWrapper(this, element)); - if (children != null) + Object[] children = fManager.getChildren(new DeferredMethodWrapper(this, rc)); + if (children != null) { return children; + } } return fetchChildren(parentWrapper); - - } else if (parentElement instanceof MethodWrapper) { - MethodWrapper methodWrapper= ((MethodWrapper)parentElement); - - if (shouldStopTraversion(methodWrapper)) { + } + if (parentElement instanceof MethodWrapper mw) { + if (shouldStopTraversion(mw)) { return EMPTY_ARRAY; - } else { - if (parentElement instanceof CallerMethodWrapper) { - CallerMethodWrapper caller= (CallerMethodWrapper)parentElement; - ensureDefaultExpandWithConstructors(caller); - if (caller.getExpandWithConstructors()) { - IType type= caller.getMember().getDeclaringType(); - try { - if (type.isAnonymous()) { - IMember anonymousClass= type; - MethodCall anonymousConstructor= new MethodCall(anonymousClass); - CallerMethodWrapper anonymousWrapper= (CallerMethodWrapper)caller.createMethodWrapper(anonymousConstructor); - return new Object[] { anonymousWrapper, new RealCallers(methodWrapper, caller.getMethodCall()) }; - } if (type.isLambda()) { - IJavaElement definingMethod = type.getParent(); - if (definingMethod instanceof IMember) { - MethodCall methodCall = new MethodCall((IMember) definingMethod); - MethodWrapper wrapper = caller.createMethodWrapper(methodCall); - return new Object [] { wrapper, new RealCallers(methodWrapper, caller.getMethodCall()) }; - } - } else { - IMember[] constructors= JavaElementUtil.getAllConstructors(type); - if (constructors.length == 0) { - constructors= new IType[] { type }; // type stands for the default constructor - } - Object children[]= new Object[constructors.length + 1]; - for (int j= 0; j < constructors.length; j++) { - MethodCall constructor= new MethodCall(constructors[j]); - CallerMethodWrapper constructorWrapper= (CallerMethodWrapper)caller.createMethodWrapper(constructor); - children[j]= constructorWrapper; - } - children[constructors.length]= new RealCallers(methodWrapper, caller.getMethodCall()); - return children; + } + if (parentElement instanceof CallerMethodWrapper caller) { + ensureDefaultExpandWithConstructors(caller); + if (caller.getExpandWithConstructors()) { + IType type = caller.getMember().getDeclaringType(); + try { + if (type.isAnonymous()) { + MethodCall anonConstructor = new MethodCall(type); + CallerMethodWrapper anonWrapper + = (CallerMethodWrapper) caller.createMethodWrapper(anonConstructor); + return new Object[] { anonWrapper, new RealCallers(mw, caller.getMethodCall()) }; + } + if (type.isLambda()) { + IJavaElement definingMethod = type.getParent(); + if (definingMethod instanceof IMember mb) { + MethodWrapper wrapper = caller.createMethodWrapper(new MethodCall(mb)); + return new Object [] { wrapper, new RealCallers(mw, caller.getMethodCall()) }; } - } catch (JavaModelException e) { - JavaPlugin.log(e); - return null; + } else { + IMember[] constructors = JavaElementUtil.getAllConstructors(type); + if (constructors.length == 0) { + constructors = new IType[] { type }; // type stands for the default constructor + } + Object[] children = new Object[constructors.length + 1]; + for (int j = 0; j < constructors.length; j++) { + MethodCall constructor = new MethodCall(constructors[j]); + children[j] = caller.createMethodWrapper(constructor); + } + children[constructors.length] = new RealCallers(mw, caller.getMethodCall()); + return children; } - + } catch (JavaModelException e) { + JavaPlugin.log(e); + return null; } } - if (fManager != null) { - Object[] children= fManager.getChildren(new DeferredMethodWrapper(this, methodWrapper)); - if (children != null) - return children; + } + if (fManager != null) { + Object[] children = fManager.getChildren(new DeferredMethodWrapper(this, mw)); + if (children != null) { + return children; } - return fetchChildren(methodWrapper); } + return fetchChildren(mw); } - return EMPTY_ARRAY; - } + return EMPTY_ARRAY; + } /** * Sets the default "expand with constructors" mode for the method wrapper. Does nothing if the * mode has already been set. - * - * * @param wrapper the caller method wrapper * @since 3.5 */ static void ensureDefaultExpandWithConstructors(CallerMethodWrapper wrapper) { - - if (!wrapper.isExpandWithConstructorsSet()) { - if (CallHierarchyContentProvider.canExpandWithConstructors(wrapper)) { - IMethod method= (IMethod)wrapper.getMember(); - IType type= method.getDeclaringType(); - try { - boolean withConstructors= false; - if (type != null) { - boolean anonymousPref= PreferenceConstants.getPreferenceStore().getBoolean(PreferenceConstants.PREF_ANONYMOUS_EXPAND_WITH_CONSTRUCTORS); - if ((anonymousPref && (type.isAnonymous() || type.isLambda())) - || isInTheDefaultExpandWithConstructorList(method)) { - withConstructors= true; - } + if (!wrapper.isExpandWithConstructorsSet() && canExpandWithConstructors(wrapper)) { + IMethod method = (IMethod) wrapper.getMember(); + IType type = method.getDeclaringType(); + try { + boolean withConstructors = false; + if (type != null) { + final String key = PreferenceConstants.PREF_ANONYMOUS_EXPAND_WITH_CONSTRUCTORS; + boolean anonymousPref = PreferenceConstants.getPreferenceStore().getBoolean(key); + if ((anonymousPref && (type.isAnonymous() || type.isLambda())) + || isInTheDefaultExpandWithConstructorList(method)) { + withConstructors = true; } - wrapper.setExpandWithConstructors(withConstructors); - } catch (JavaModelException e) { - // ignore: expand mode will be off } + wrapper.setExpandWithConstructors(withConstructors); + } catch (JavaModelException e) { + // ignore: expand mode will be off } } - } /** * Checks whether given caller method wrapper can be expanded with constructors. - * * @param wrapper the caller method wrapper * @return true if the wrapper can be expanded with constructors, false otherwise * @since 3.5 */ static boolean canExpandWithConstructors(CallerMethodWrapper wrapper) { - IMember member= wrapper.getMember(); - if (!(member instanceof IMethod)) - return false; - IMethod method= (IMethod)member; - try { - if (JdtFlags.isStatic(method) || method.isConstructor()) - return false; - } catch (JavaModelException e) { - return false; // don't try to work with inexistent elements + if (wrapper.getMember() instanceof IMethod method) { + try { + return !JdtFlags.isStatic(method) && !method.isConstructor(); + } catch (JavaModelException e) { + return false; // don't try to work with inexistent elements + } } - return true; + return false; } /** * Checks if the method or its declaring type matches the pre-defined array of methods and types * for default expand with constructors. - * * @param method the wrapped method - * @return true if method or type matches the pre-defined list, false - * otherwise - * + * @return true if method or type matches the pre-defined list, false otherwise * @since 3.5 */ static boolean isInTheDefaultExpandWithConstructorList(IMethod method) { - String serializedMembers= PreferenceConstants.getPreferenceStore().getString(PreferenceConstants.PREF_DEFAULT_EXPAND_WITH_CONSTRUCTORS_MEMBERS); - if (serializedMembers.length() == 0) + final String key = PreferenceConstants.PREF_DEFAULT_EXPAND_WITH_CONSTRUCTORS_MEMBERS; + String serializedMembers = PreferenceConstants.getPreferenceStore().getString(key); + if (serializedMembers.isEmpty()) { return false; + } - String[] defaultMemberPatterns= serializedMembers.split(";"); //$NON-NLS-1$ - - String methodName= method.getElementName(); - IType declaringType= method.getDeclaringType(); - String declaringTypeName= declaringType.getFullyQualifiedName('.'); + IType declaringType = method.getDeclaringType(); String superClassName; String[] superInterfaceNames; try { - superClassName= declaringType.getSuperclassName(); + superClassName = declaringType.getSuperclassName(); if (superClassName != null) { - superClassName= stripTypeArguments(superClassName); + superClassName = stripTypeArguments(superClassName); } - superInterfaceNames= declaringType.getSuperInterfaceNames(); - for (int i= 0; i < superInterfaceNames.length; i++) { - superInterfaceNames[i]= stripTypeArguments(superInterfaceNames[i]); + superInterfaceNames = declaringType.getSuperInterfaceNames(); + for (int i = 0; i < superInterfaceNames.length; i++) { + superInterfaceNames[i] = stripTypeArguments(superInterfaceNames[i]); } } catch (JavaModelException e) { return false; } + String[] defaultMemberPatterns = serializedMembers.split(";"); //$NON-NLS-1$ + String declaringTypeName = declaringType.getFullyQualifiedName('.'); for (String defaultMemberPattern : defaultMemberPatterns) { - int pos= defaultMemberPattern.lastIndexOf('.'); - String defaultTypeName= defaultMemberPattern.substring(0, pos); - String defaultMethodName= defaultMemberPattern.substring(pos + 1); + int pos = defaultMemberPattern.lastIndexOf('.'); + String defaultTypeName = defaultMemberPattern.substring(0, pos); + String defaultMethodName = defaultMemberPattern.substring(pos + 1); if ("*".equals(defaultMethodName)) { //$NON-NLS-1$ if (declaringTypeName.equals(defaultTypeName)) { return true; } } else { - if (!methodName.equals(defaultMethodName)) { + if (!method.getElementName().equals(defaultMethodName)) { continue; } if (declaringTypeName.equals(defaultTypeName)) { @@ -286,123 +291,124 @@ static boolean isInTheDefaultExpandWithConstructorList(IMethod method) { /** * Strips type arguments from the given type name and returns only erased type name. - * * @param typeName the type name * @return the erased type name - * * @since 3.6 */ private static String stripTypeArguments(String typeName) { - int pos= typeName.indexOf('<'); - if (pos != -1) - return typeName.substring(0, pos); - return typeName; + int pos = typeName.indexOf('<'); + return pos == -1 ? typeName : typeName.substring(0, pos); } + /** + * Fetches the children. + * @param methodWrapper Method wrapper + * @return Fetched children + */ protected Object[] fetchChildren(final MethodWrapper methodWrapper) { - IRunnableContext context= JavaPlugin.getActiveWorkbenchWindow(); - MethodWrapperRunnable runnable= new MethodWrapperRunnable(methodWrapper); - try { - context.run(true, true, runnable); - } catch (InvocationTargetException e) { - ExceptionHandler.handle(e, CallHierarchyMessages.CallHierarchyContentProvider_searchError_title, CallHierarchyMessages.CallHierarchyContentProvider_searchError_message); - return EMPTY_ARRAY; - } catch (InterruptedException e) { - final CallerMethodWrapper element= (CallerMethodWrapper)methodWrapper; - if (!isExpandWithConstructors(element)) { - Display.getDefault().asyncExec(() -> collapseAndRefresh(element)); - } - } - - return runnable.getCalls(); - } - - - /** - * Returns whether the given element is an "Expand witch Constructors" node. - * + MethodWrapperRunnable runnable = new MethodWrapperRunnable(methodWrapper); + try { + JavaPlugin.getActiveWorkbenchWindow().run(true, true, runnable); + } catch (InvocationTargetException e) { + final String title = CallHierarchyMessages.CallHierarchyContentProvider_searchError_title; + ExceptionHandler.handle(e, title, CallHierarchyMessages.CallHierarchyContentProvider_searchError_message); + return EMPTY_ARRAY; + } catch (InterruptedException e) { + final CallerMethodWrapper element = (CallerMethodWrapper) methodWrapper; + if (!isExpandWithConstructors(element)) { + Display.getDefault().asyncExec(() -> collapseAndRefresh(element)); + } + } + return runnable.getCalls(); + } + + /** + * Returns whether the given element is an "Expand witch Constructors" node. * @param element a method wrapped - * @return true iff the element is an "Expand witch Constructors" node + * @return true if the element is an "Expand witch Constructors" node * @since 3.5 */ static boolean isExpandWithConstructors(MethodWrapper element) { - return element instanceof CallerMethodWrapper && ((CallerMethodWrapper)element).getExpandWithConstructors(); + return element instanceof CallerMethodWrapper cmw && cmw.getExpandWithConstructors(); } /** - * Collapses and refreshes the given element when search has been canceled. - * - * @param element the element on which search has been canceled and which has to be collapsed - * @since 3.5 - */ - protected void collapseAndRefresh(MethodWrapper element) { - CallHierarchyViewer viewer= fPart.getViewer(); + * Collapses and refreshes the given element when search has been canceled. + * @param element the element on which search has been canceled and which has to be collapsed + * @since 3.5 + */ + protected void collapseAndRefresh(MethodWrapper element) { + CallHierarchyViewer viewer = fPart.getViewer(); /* Problem case: The user expands the RealCallers node and then unchecks "Expand with Constructors" * while the search for the real callers is still in progress. * * In this scenario, the RealCallers is not even part of the current tree any more, since the * ExpandWithConstructorsAction already toggled the flag and refreshed the tree. - * - * But since setExpandedState(element, false) walks up the getParent() chain of the given element, - * this causes the parent's children to be created, which would wrongly start a deferred search. - * - * The fix is to do nothing when the RealCaller's parent is expandWithConstructors. + * + * But since setExpandedState(element, false) walks up the getParent() chain of the given element, + * this causes the parent's children to be created, which would wrongly start a deferred search. + * + * The fix is to do nothing when the RealCaller's parent is expandWithConstructors. */ - boolean elementStays= true; - if (element instanceof RealCallers) { - elementStays= isExpandWithConstructors(element.getParent()); - } + boolean elementStays = true; + if (element instanceof RealCallers) { + elementStays = isExpandWithConstructors(element.getParent()); + } if (elementStays) { - viewer.setExpandedState(element, false); - } + viewer.setExpandedState(element, false); + } - viewer.refresh(element); - } + viewer.refresh(element); + } /** - * Returns the call hierarchy view part. - * + * Returns the call hierarchy view part. * @return the call hierarchy view part * @since 3.5 */ - public CallHierarchyViewPart getViewPart() { - return fPart; - } - - private boolean shouldStopTraversion(MethodWrapper methodWrapper) { - return (methodWrapper.getLevel() > CallHierarchyUI.getDefault().getMaxCallDepth()) || methodWrapper.isRecursive(); - } - - /** - * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object) - */ - @Override + public CallHierarchyViewPart getViewPart() { + return fPart; + } + + /** + * Checks if traversion should be stopped. + * @param mw Method wrapper + * @return true if traversion should be stopped, false otherwise + */ + private boolean shouldStopTraversion(MethodWrapper mw) { + return mw.getLevel() > CallHierarchyUI.getDefault().getMaxCallDepth() || mw.isRecursive(); + } + + /** + * {@inheritDoc} + * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object) + */ + @Override public Object[] getElements(Object inputElement) { - return getChildren(inputElement); - } + return getChildren(inputElement); + } - /** - * @see org.eclipse.jface.viewers.ITreeContentProvider#getParent(java.lang.Object) - */ - @Override + /** + * {@inheritDoc} + * @see org.eclipse.jface.viewers.ITreeContentProvider#getParent(java.lang.Object) + */ + @Override public Object getParent(Object element) { - if (element instanceof MethodWrapper) { - return ((MethodWrapper) element).getParent(); - } - - return null; - } + return element instanceof MethodWrapper mw ? mw.getParent() : null; + } - /** - * @see org.eclipse.jface.viewers.IContentProvider#dispose() - */ - @Override + /** + * {@inheritDoc} + * @see org.eclipse.jface.viewers.IContentProvider#dispose() + */ + @Override public void dispose() { - // Nothing to dispose - } + // Nothing to dispose + } - /** + /** + * {@inheritDoc} * @see org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java.lang.Object) */ @Override @@ -413,17 +419,9 @@ public boolean hasChildren(Object element) { // Only certain members can have subelements, so there's no need to fool the // user into believing that there is more - if (element instanceof MethodWrapper) { - MethodWrapper methodWrapper= (MethodWrapper) element; - if (! methodWrapper.canHaveChildren()) { - return false; - } - if (shouldStopTraversion(methodWrapper)) { - return false; - } - return true; - } else if (element instanceof TreeRoot - || element instanceof DeferredMethodWrapper) { + if (element instanceof MethodWrapper mw) { + return mw.canHaveChildren() && !shouldStopTraversion(mw); + } else if (element instanceof TreeRoot || element instanceof DeferredMethodWrapper) { // Err on the safe side by returning true even though // we don't know for sure that there are children. return true; @@ -432,45 +430,51 @@ public boolean hasChildren(Object element) { return false; // the "Update ..." placeholder has no children } - /** + /** + * {@inheritDoc} * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, - * java.lang.Object, java.lang.Object) + * java.lang.Object, java.lang.Object) */ - @Override + @Override public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - if (oldInput instanceof TreeRoot) { - MethodWrapper[] roots = ((TreeRoot) oldInput).getRoots(); - cancelJobs(roots); - } - if (viewer instanceof AbstractTreeViewer) { - fManager = new DeferredTreeContentManager((AbstractTreeViewer) viewer, fPart.getSite()); - } - } - - /** - * Cancel all current jobs. - * @param wrappers the parents to cancel jobs for - */ - void cancelJobs(MethodWrapper[] wrappers) { - if (fManager != null && wrappers != null) { - for (MethodWrapper wrapper : wrappers) { - fManager.cancel(wrapper); - } - if (fPart != null) { - fPart.setCancelEnabled(false); - } - } - } - - public void doneFetching() { - if (fPart != null) { - fPart.setCancelEnabled(false); - } - } - - public void startFetching() { - if (fPart != null) { - fPart.setCancelEnabled(true); - } - } -} + if (oldInput instanceof TreeRoot tr) { + cancelJobs(tr.getRoots()); + } + if (viewer instanceof AbstractTreeViewer atv) { + fManager = new DeferredTreeContentManager(atv, fPart.getSite()); + } + } + + /** + * Cancel all current jobs. + * @param wrappers the parents to cancel jobs for + */ + void cancelJobs(MethodWrapper[] wrappers) { + if (fManager != null && wrappers != null) { + for (MethodWrapper wrapper : wrappers) { + fManager.cancel(wrapper); + } + if (fPart != null) { + fPart.setCancelEnabled(false); + } + } + } + + /** + * Actions after fetching is done. + */ + public void doneFetching() { + if (fPart != null) { + fPart.setCancelEnabled(false); + } + } + + /** + * Actions when fetching is starting. + */ + public void startFetching() { + if (fPart != null) { + fPart.setCancelEnabled(true); + } + } +} \ No newline at end of file