Skip to content

Commit

Permalink
Implement grouping of the stack frames
Browse files Browse the repository at this point in the history
The rules how the frames are categorized are not editable as of now,
just a single action is visible to switch on-off the behaviour, with
enough javadocs
  • Loading branch information
gzsombor committed Jan 15, 2025
1 parent ff239f3 commit 2fcfe4c
Show file tree
Hide file tree
Showing 18 changed files with 582 additions and 45 deletions.
3 changes: 3 additions & 0 deletions org.eclipse.jdt.debug.ui/plugin.properties
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,9 @@ showMonitorThreadInfo.tooltip=Show the Thread & Monitor Information
showNullEntriesAction.label=Show &Null Array Entries
showNullEntriesAction.tooltip=Show Null Array Entries

collapseStackFrames.label=Collapse Stack Frames
collapseStackFrames.tooltip=Hide less relevant stack frames

stepIntoSelectionHyperlinkDetector.label=Step Into Selection
stepIntoSelectionHyperlinkDetector.description=Performs the step into selection command on demand via a hyperlink

Expand Down
8 changes: 8 additions & 0 deletions org.eclipse.jdt.debug.ui/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2242,6 +2242,14 @@
style="toggle"
menubarPath="org.eclipse.jdt.debug.ui.LaunchView.javaSubmenu/javaPart"
id="org.eclipse.jdt.debug.ui.launchViewActions.ShowMonitorThreadInfo"/>
<action
helpContextId="collapse_stack_frames_action_context"
label="%collapseStackFrames.label"
tooltip="%collapseStackFrames.tooltip"
class="org.eclipse.jdt.internal.debug.ui.actions.CollapseStackFramesAction"
style="toggle"
menubarPath="org.eclipse.jdt.debug.ui.LaunchView.javaSubmenu/javaPart"
id="org.eclipse.jdt.debug.ui.launchViewActions.CollapseStackFrames"/>
<menu
id="org.eclipse.jdt.debug.ui.LaunchView.javaSubmenu"
label="%LaunchViewJavaSubmenu.label"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ public class DebugUIMessages extends NLS {
public static String JDIModelPresentation__garbage_collected_object__6;
public static String JDIModelPresentation__obsolete_method_in__1;
public static String JDIModelPresentation__terminated__2;
public static String JDIModelPresentation_collapsed_frames;

public static String JDIModelPresentation_117;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ JDIModelPresentation_modification_72=\ [modification]
JDIModelPresentation_native_method=[native method]
JDIModelPresentation_not_available=not available
JDIModelPresentation_Suspend_VM=[Suspend VM]
JDIModelPresentation_collapsed_frames={0} collapsed frames

###############################################################################
# Thread label keys are built programmatically
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,34 @@ public interface IJDIPreferencesConstants {
*/
public static final String PREF_STEP_THRU_FILTERS = IJavaDebugUIConstants.PLUGIN_ID + ".step_thru_filters"; //$NON-NLS-1$

public static final String PREF_COLLAPSE_STACK_FRAMES = IJavaDebugUIConstants.PLUGIN_ID + ".collapse_stack_frames"; //$NON-NLS-1$

/**
* List of active step filters. A String containing a comma
* separated list of fully qualified type names/patterns.
* List of active filters for custom stack frame categorization. A String containing a comma separated list of fully qualified type
* names/patterns.
*/
public static final String PREF_ACTIVE_CUSTOM_FRAME_FILTER_LIST = IJavaDebugUIConstants.PLUGIN_ID + ".active_custom_frames_filters"; //$NON-NLS-1$

/**
* List of inactive filters for custom stack frame categorization. A String containing a comma separated list of fully qualified type
* names/patterns.
*/
public static final String PREF_INACTIVE_CUSTOM_FRAME_FILTER_LIST = IJavaDebugUIConstants.PLUGIN_ID + ".inactive_custom_frames_filters"; //$NON-NLS-1$

/**
* List of active filters for custom stack frame categorization. A String containing a comma separated list of fully qualified type
* names/patterns.
*/
public static final String PREF_ACTIVE_PLATFORM_FRAME_FILTER_LIST = IJavaDebugUIConstants.PLUGIN_ID + ".active_platform_frames_filters"; //$NON-NLS-1$

/**
* List of inactive filters for custom stack frame categorization. A String containing a comma separated list of fully qualified type
* names/patterns.
*/
public static final String PREF_INACTIVE_PLATFORM_FRAME_FILTER_LIST = IJavaDebugUIConstants.PLUGIN_ID + ".inactive_platform_frames_filters"; //$NON-NLS-1$

/**
* List of active step filters. A String containing a comma separated list of fully qualified type names/patterns.
*/
public static final String PREF_ACTIVE_FILTERS_LIST = IJavaDebugUIConstants.PLUGIN_ID + ".active_filters"; //$NON-NLS-1$

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2000, 2022 IBM Corporation and others.
* Copyright (c) 2000, 2024 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
Expand Down Expand Up @@ -57,6 +57,7 @@
import org.eclipse.jdt.debug.core.IJavaVariable;
import org.eclipse.jdt.debug.core.JDIDebugModel;
import org.eclipse.jdt.debug.ui.IJavaDebugUIConstants;
import org.eclipse.jdt.internal.debug.core.model.GroupedStackFrame;
import org.eclipse.jdt.internal.debug.ui.breakpoints.ExceptionInspector;
import org.eclipse.jdt.internal.debug.ui.breakpoints.JavaBreakpointTypeAdapterFactory;
import org.eclipse.jdt.internal.debug.ui.classpath.ClasspathEntryAdapterFactory;
Expand Down Expand Up @@ -382,6 +383,7 @@ public void start(BundleContext context) throws Exception {
manager.registerAdapters(monitorFactory, JavaOwningThread.class);
manager.registerAdapters(monitorFactory, JavaWaitingThread.class);
manager.registerAdapters(monitorFactory, IJavaStackFrame.class);
manager.registerAdapters(monitorFactory, GroupedStackFrame.class);

IAdapterFactory targetFactory = new TargetAdapterFactory();
manager.registerAdapters(targetFactory, IJavaDebugTarget.class);
Expand All @@ -391,6 +393,7 @@ public void start(BundleContext context) throws Exception {

IAdapterFactory showInFactory = new JavaDebugShowInAdapterFactory();
manager.registerAdapters(showInFactory, IJavaStackFrame.class);
manager.registerAdapters(showInFactory, GroupedStackFrame.class);

IAdapterFactory columnFactory = new ColumnPresentationAdapterFactory();
manager.registerAdapters(columnFactory, IJavaVariable.class);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2004, 2020 IBM Corporation and others.
* Copyright (c) 2004, 2024 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
Expand All @@ -20,6 +20,7 @@
import org.eclipse.jdt.debug.ui.IJavaDebugUIConstants;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.util.Util;

public class JDIDebugUIPreferenceInitializer extends AbstractPreferenceInitializer {

Expand All @@ -46,6 +47,12 @@ public void initializeDefaultPreferences() {
store.setDefault(IJDIPreferencesConstants.PREF_INACTIVE_FILTERS_LIST, "com.ibm.*,com.sun.*,java.*,javax.*,jdk.*,jrockit.*,org.omg.*,sun.*,sunw.*"); //$NON-NLS-1$
store.setDefault(IJDIPreferencesConstants.PREF_STEP_THRU_FILTERS, true);

store.setDefault(IJDIPreferencesConstants.PREF_ACTIVE_PLATFORM_FRAME_FILTER_LIST, "java.*,javax.*,jdk.*,sun.*,sunw.*,org.junit.*,org.eclipse.jdt.internal.*"); //$NON-NLS-1$
store.setDefault(IJDIPreferencesConstants.PREF_INACTIVE_PLATFORM_FRAME_FILTER_LIST, Util.ZERO_LENGTH_STRING);
store.setDefault(IJDIPreferencesConstants.PREF_ACTIVE_CUSTOM_FRAME_FILTER_LIST, Util.ZERO_LENGTH_STRING);
store.setDefault(IJDIPreferencesConstants.PREF_INACTIVE_CUSTOM_FRAME_FILTER_LIST, Util.ZERO_LENGTH_STRING);
store.setDefault(IJDIPreferencesConstants.PREF_COLLAPSE_STACK_FRAMES, true);

store.setDefault(IDebugUIConstants.ID_VARIABLE_VIEW + "." + IJDIPreferencesConstants.PREF_SHOW_CONSTANTS, false); //$NON-NLS-1$
store.setDefault(IDebugUIConstants.ID_EXPRESSION_VIEW + "." + IJDIPreferencesConstants.PREF_SHOW_CONSTANTS, false); //$NON-NLS-1$
store.setDefault(IDebugUIConstants.ID_VARIABLE_VIEW + "." + IJDIPreferencesConstants.PREF_SHOW_STATIC_VARIABLES, false); //$NON-NLS-1$
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
import org.eclipse.jdt.internal.debug.core.breakpoints.JavaExceptionBreakpoint;
import org.eclipse.jdt.internal.debug.core.logicalstructures.JDIAllInstancesValue;
import org.eclipse.jdt.internal.debug.core.logicalstructures.JDIReturnValueVariable;
import org.eclipse.jdt.internal.debug.core.model.GroupedStackFrame;
import org.eclipse.jdt.internal.debug.core.model.JDIDebugModelMessages;
import org.eclipse.jdt.internal.debug.core.model.JDIReferenceListEntryVariable;
import org.eclipse.jdt.internal.debug.core.model.JDIReferenceListValue;
Expand Down Expand Up @@ -151,6 +152,8 @@ public class JDIModelPresentation extends LabelProvider implements IDebugModelPr

private JavaElementLabelProvider fJavaLabelProvider;

private StackFramePresentationProvider fStackFrameProvider;

public JDIModelPresentation() {
super();
}
Expand All @@ -165,6 +168,9 @@ public void dispose() {
fJavaLabelProvider.dispose();
}
fAttributes.clear();
if (fStackFrameProvider != null) {
fStackFrameProvider.close();
}
}

/**
Expand Down Expand Up @@ -244,6 +250,8 @@ public String getText(Object item) {
return getJavaOwningTreadText((JavaOwningThread)item);
} else if (item instanceof JavaWaitingThread) {
return getJavaWaitingTreadText((JavaWaitingThread)item);
} else if (item instanceof GroupedStackFrame groupping) {
return getFormattedString(DebugUIMessages.JDIModelPresentation_collapsed_frames, String.valueOf(groupping.getFrameCount()));
} else if (item instanceof NoMonitorInformationElement) {
return DebugUIMessages.JDIModelPresentation_5;
} else {
Expand Down Expand Up @@ -737,7 +745,10 @@ public Image getImage(Object item) {
return DebugUITools.getImage(IDebugUIConstants.IMG_OBJS_THREAD_RUNNING);
}
}
if (item instanceof IJavaStackFrame || item instanceof IJavaThread || item instanceof IJavaDebugTarget) {
if (item instanceof IJavaStackFrame) {
return getStackFrameImage((IJavaStackFrame) item);
}
if (item instanceof IJavaThread || item instanceof IJavaDebugTarget) {
return getDebugElementImage(item);
}
if (item instanceof IJavaValue) {
Expand Down Expand Up @@ -937,6 +948,30 @@ protected Image getDebugElementImage(Object element) {
return getDebugImage(image, flags);
}

/**
* Returns the image associated with the given {@link IJavaStackFrame}, decorated with overlays, if the stack frame is out of sync
* ({@link IJavaStackFrame#isOutOfSynch()} or synchronized ({@link IJavaStackFrame#isSynchronized()}). The base image is acquired from the
* {@link StackFramePresentationProvider}.
*/
private Image getStackFrameImage(IJavaStackFrame stackFrame) {
var image = getStackFrameProvider().getStackFrameImage(stackFrame);
if (image == null) {
image = DebugUITools.getDefaultImageDescriptor(stackFrame);
}

int flags = 0;
try {
if (stackFrame.isOutOfSynch()) {
flags = JDIImageDescriptor.IS_OUT_OF_SYNCH;
} else if (!stackFrame.isObsolete() && stackFrame.isSynchronized()) {
flags = JDIImageDescriptor.SYNCHRONIZED;
}
} catch (DebugException e) {
// no need to log errors - elements may no longer exist by the time we render them
}

return getDebugImage(image, flags);
}
/**
* Returns the image associated with the given element or <code>null</code>
* if none is defined.
Expand All @@ -959,21 +994,11 @@ protected Image getExpressionImage(Object expression) {
}

/**
* Returns the adornment flags for the given element.
* These flags are used to render appropriate overlay
* icons for the element.
* Returns the adornment flags for the given element. These flags are used to render appropriate overlay icons for the element. It only supports
* {@link IJavaThread} and {@link IJavaDebugTarget}, for other types it always returns 0.
*/
private int computeJDIAdornmentFlags(Object element) {
try {
if (element instanceof IJavaStackFrame) {
IJavaStackFrame javaStackFrame = ((IJavaStackFrame)element);
if (javaStackFrame.isOutOfSynch()) {
return JDIImageDescriptor.IS_OUT_OF_SYNCH;
}
if (!javaStackFrame.isObsolete() && javaStackFrame.isSynchronized()) {
return JDIImageDescriptor.SYNCHRONIZED;
}
}
if (element instanceof IJavaThread) {
int flag= 0;
IJavaThread javaThread = ((IJavaThread)element);
Expand Down Expand Up @@ -2049,6 +2074,16 @@ protected JavaElementLabelProvider getJavaLabelProvider() {
return fJavaLabelProvider;
}

/**
* @return a {@link StackFramePresentationProvider} which responsible to classify stack frames into categories and could provide category specific
* visual representations.
*/
private StackFramePresentationProvider getStackFrameProvider() {
if (fStackFrameProvider == null) {
fStackFrameProvider = new StackFramePresentationProvider();
}
return fStackFrameProvider;
}
/**
* Returns whether the given field variable has the same name as any variables
*/
Expand Down
Loading

0 comments on commit 2fcfe4c

Please sign in to comment.