From 077e37aa29f70ccdbfc5638def8d889360af4722 Mon Sep 17 00:00:00 2001 From: Zsombor Gegesy Date: Sun, 13 Jun 2021 00:40:31 +0200 Subject: [PATCH] Bug 574170 - Add coloring to the stack frames of the debug thread view and add an action to enable/disable colorization from the context menu. All of the categorize can be switched on or off Use separate images for different stack frame categories. Update the labels to 'Your Source code', 'Your Test code', 'Highlighted ...' --- .../jdt/debug/tests/AutomatedSuite.java | 2 + .../StackFramePresentationProviderTest.java | 149 ++++++ org.eclipse.jdt.debug.ui/META-INF/MANIFEST.MF | 2 +- org.eclipse.jdt.debug.ui/plugin.properties | 35 ++ org.eclipse.jdt.debug.ui/plugin.xml | 118 +++++ .../internal/debug/ui/DebugUIMessages.java | 32 ++ .../debug/ui/DebugUIMessages.properties | 33 ++ .../debug/ui/IJDIPreferencesConstants.java | 58 ++- .../debug/ui/IJavaDebugHelpContextIds.java | 1 + .../ui/JDIDebugUIPreferenceInitializer.java | 13 + .../debug/ui/JDIModelPresentation.java | 169 +++---- .../ui/JavaStackFramePreferencePage.java | 429 ++++++++++++++++++ .../ui/StackFramePresentationProvider.java | 290 ++++++++++++ .../ui/actions/ColorizeStackFramesAction.java | 44 ++ .../variables/JavaVariableLabelProvider.java | 2 +- org.eclipse.jdt.debug/META-INF/MANIFEST.MF | 2 +- .../jdt/debug/core/IJavaStackFrame.java | 25 + .../debug/core/model/JDIStackFrame.java | 12 + org.eclipse.jdt.debug/pom.xml | 2 +- .../launching/JavaSourceLookupDirector.java | 2 +- 20 files changed, 1335 insertions(+), 85 deletions(-) create mode 100644 org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/ui/StackFramePresentationProviderTest.java create mode 100644 org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JavaStackFramePreferencePage.java create mode 100644 org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/StackFramePresentationProvider.java create mode 100644 org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/ColorizeStackFramesAction.java diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AutomatedSuite.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AutomatedSuite.java index 5da479aeb6..470d108985 100644 --- a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AutomatedSuite.java +++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AutomatedSuite.java @@ -142,6 +142,7 @@ import org.eclipse.jdt.debug.tests.ui.DebugViewTests; import org.eclipse.jdt.debug.tests.ui.DetailPaneManagerTests; import org.eclipse.jdt.debug.tests.ui.OpenFromClipboardTests; +import org.eclipse.jdt.debug.tests.ui.StackFramePresentationProviderTest; import org.eclipse.jdt.debug.tests.ui.ViewManagementTests; import org.eclipse.jdt.debug.tests.ui.presentation.ModelPresentationTests; import org.eclipse.jdt.debug.tests.ui.presentation.ModelPresentationTests18; @@ -231,6 +232,7 @@ public AutomatedSuite() { addTest(new TestSuite(StepFilterTests.class)); addTest(new TestSuite(StepIntoSelectionTests.class)); addTest(new TestSuite(InstanceFilterTests.class)); + addTest(new TestSuite(StackFramePresentationProviderTest.class)); if (JavaProjectHelper.isJava6Compatible()) { addTest(new TestSuite(ForceReturnTests.class)); } diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/ui/StackFramePresentationProviderTest.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/ui/StackFramePresentationProviderTest.java new file mode 100644 index 0000000000..f8e6029266 --- /dev/null +++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/ui/StackFramePresentationProviderTest.java @@ -0,0 +1,149 @@ +/******************************************************************************* + * Copyright (c) 2021 Zsombor Gegesy. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Zsombor Gegesy - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.debug.tests.ui; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; + +import org.eclipse.debug.core.DebugException; +import org.eclipse.debug.core.ILaunch; +import org.eclipse.jdt.debug.core.IJavaReferenceType; +import org.eclipse.jdt.debug.core.IJavaStackFrame; +import org.eclipse.jdt.debug.tests.AbstractDebugTest; +import org.eclipse.jdt.internal.debug.ui.IJDIPreferencesConstants; +import org.eclipse.jdt.internal.debug.ui.StackFramePresentationProvider; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.preference.PreferenceStore; + +public class StackFramePresentationProviderTest extends AbstractDebugTest { + + public StackFramePresentationProviderTest(String name) { + super(name); + } + + private StackFramePresentationProvider provider; + private IPreferenceStore preferenceStore; + + private static class LaunchMock implements InvocationHandler { + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + return null; + } + } + private static class JavaStackFrameMock implements InvocationHandler { + + final IJavaReferenceType referenceType; + final boolean synthetic; + + public JavaStackFrameMock(IJavaReferenceType referenceType, boolean synthetic) { + this.referenceType = referenceType; + this.synthetic = synthetic; + } + + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + var methodName = method.getName(); + if ("getReferenceType".equals(methodName)) { + return referenceType; + } + if ("isSynthetic".equals(methodName)) { + return synthetic; + } + if ("getLaunch".equals(methodName)) { + return Proxy.newProxyInstance(StackFramePresentationProviderTest.class.getClassLoader(), new Class[] { + ILaunch.class }, new LaunchMock()); + + } + return null; + } + } + + private static class JavaReferenceTypeMock implements InvocationHandler { + + final String name; + + public JavaReferenceTypeMock(String name) { + this.name = name; + } + + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + if ("getName".equals(method.getName())) { + return name; + } + return null; + } + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + preferenceStore = new PreferenceStore(); + preferenceStore.setValue(IJDIPreferencesConstants.PREF_ACTIVE_PLATFORM_FRAME_FILTER_LIST, "java.*,javax.*"); + preferenceStore.setValue(IJDIPreferencesConstants.PREF_COLORIZE_STACK_FRAMES, true); + preferenceStore.setValue(IJDIPreferencesConstants.PREF_COLORIZE_PLATFORM_METHODS, true); + preferenceStore.setValue(IJDIPreferencesConstants.PREF_COLORIZE_CUSTOM_METHODS, true); + preferenceStore.setValue(IJDIPreferencesConstants.PREF_COLORIZE_SYNTHETIC_METHODS, true); + provider = new StackFramePresentationProvider(preferenceStore); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + provider.close(); + } + + private IJavaReferenceType createReference(String name) { + return (IJavaReferenceType) Proxy.newProxyInstance(StackFramePresentationProviderTest.class.getClassLoader(), new Class[] { + IJavaReferenceType.class }, new JavaReferenceTypeMock(name)); + } + + private IJavaStackFrame createFrame(IJavaReferenceType refType, boolean syntetic) { + return (IJavaStackFrame) Proxy.newProxyInstance(StackFramePresentationProviderTest.class.getClassLoader(), new Class[] { + IJavaStackFrame.class }, new JavaStackFrameMock(refType, syntetic)); + } + + private IJavaStackFrame.Category categorize(String refTypeName, boolean syntetic) throws DebugException { + return categorize(createReference(refTypeName), syntetic); + } + + private IJavaStackFrame.Category categorize(IJavaReferenceType refType, boolean syntetic) throws DebugException { + return provider.categorize(createFrame(refType, syntetic)); + } + + public void testFiltering() throws DebugException { + assertEquals(IJavaStackFrame.Category.SYNTHETIC, categorize("org.eclipse.Something", true)); + assertEquals(IJavaStackFrame.Category.PLATFORM, categorize("java.lang.String", false)); + assertEquals(IJavaStackFrame.Category.UNKNOWN, categorize("org.eclipse.Other", false)); + } + + public void testUpdateWorks() throws DebugException { + var something = createReference("org.eclipse.Something"); + var other = createReference("org.eclipse.Other"); + assertEquals(IJavaStackFrame.Category.UNKNOWN, categorize(something, false)); + assertEquals(IJavaStackFrame.Category.UNKNOWN, categorize(other, false)); + preferenceStore.setValue(IJDIPreferencesConstants.PREF_ACTIVE_CUSTOM_FRAME_FILTER_LIST, "org.eclipse.Something"); + + assertEquals(IJavaStackFrame.Category.CUSTOM_FILTERED, categorize(something, false)); + assertEquals(IJavaStackFrame.Category.UNKNOWN, categorize(other, false)); + } + + public void testSwitchOffPlatform() throws DebugException { + assertEquals(IJavaStackFrame.Category.PLATFORM, categorize("java.lang.String", false)); + preferenceStore.setValue(IJDIPreferencesConstants.PREF_COLORIZE_PLATFORM_METHODS, false); + assertEquals(IJavaStackFrame.Category.UNKNOWN, categorize("java.lang.String", false)); + } + +} diff --git a/org.eclipse.jdt.debug.ui/META-INF/MANIFEST.MF b/org.eclipse.jdt.debug.ui/META-INF/MANIFEST.MF index c2c652fd87..a1c51a398a 100644 --- a/org.eclipse.jdt.debug.ui/META-INF/MANIFEST.MF +++ b/org.eclipse.jdt.debug.ui/META-INF/MANIFEST.MF @@ -40,7 +40,7 @@ Require-Bundle: org.eclipse.ui.ide;bundle-version="[3.5.0,4.0.0)", org.eclipse.core.expressions;bundle-version="[3.4.0,4.0.0)", org.eclipse.jdt.core;bundle-version="[3.28.0,4.0.0)", org.eclipse.debug.ui;bundle-version="[3.13.400,4.0.0)", - org.eclipse.jdt.debug;bundle-version="[3.19.0,4.0.0)", + org.eclipse.jdt.debug;bundle-version="[3.20.0,4.0.0)", org.eclipse.jdt.launching;bundle-version="[3.19.0,4.0.0)", org.eclipse.jdt.ui;bundle-version="[3.26.0,4.0.0)", org.eclipse.core.runtime;bundle-version="[3.11.0,4.0.0)", diff --git a/org.eclipse.jdt.debug.ui/plugin.properties b/org.eclipse.jdt.debug.ui/plugin.properties index cdb3237cc6..8a9974c3e0 100644 --- a/org.eclipse.jdt.debug.ui/plugin.properties +++ b/org.eclipse.jdt.debug.ui/plugin.properties @@ -98,6 +98,8 @@ JavaSnippetEditor.label= Scrapbook javaStepFilterPrefName=Step Filtering javaDetailFormattersPrefName=Detail Formatters +javaStackFramePrefName=Stack Frames + javaVariableHoverLabel=Variable Values javaVariableHoverDescription=Shows the value of the selected variable when debugging. @@ -178,6 +180,9 @@ showMonitorThreadInfo.tooltip=Show the Thread & Monitor Information showNullEntriesAction.label=Show &Null Array Entries showNullEntriesAction.tooltip=Show Null Array Entries +colorizeStackFrames.label=Mark Stack Frames with &Colors +colorizeStackFrames.tooltip=Based on the function mark the stack frames with different colors + stepIntoSelectionHyperlinkDetector.label=Step Into Selection stepIntoSelectionHyperlinkDetector.description=Performs the step into selection command on demand via a hyperlink @@ -289,6 +294,36 @@ InDeadlockColorDefinition.description=The color used to render deadlocked thread LabeledObjectColorDefinition.label=Labeled objects LabeledObjectColorDefinition.description=The color used to render labeled objects in debug views. +CustomFilteredStackFrameFgColorDefinition.label=Highlighted methods +CustomFilteredStackFrameBgColorDefinition.label=Highlighted methods background +CustomFilteredStackFrameFgColorDefinition.description=The color used to render the Highlighted stack frames in the Debug view. +CustomFilteredStackFrameBgColorDefinition.description=The background color used to render the Highlighted stack frames in the Debug view. + +SyntheticStackFrameFgColorDefinition.label=Synthetic methods +SyntheticStackFrameBgColorDefinition.label=Synthetic methods background +SyntheticStackFrameFgColorDefinition.description=The color used to render stack frames for synthetic methods in the Debug view. +SyntheticStackFrameBgColorDefinition.description=The background color used to render stack frames for synthetic methods in the Debug view. + +PlatformStackFrameFgColorDefinition.label=Platform methods +PlatformStackFrameBgColorDefinition.label=Platform methods background +PlatformStackFrameFgColorDefinition.description=The color used to render stack frames for Platform methods in the Debug view. +PlatformStackFrameBgColorDefinition.description=The background color used to render stack frame for Platform methods in the Debug view. + +TestStackFrameFgColorDefinition.label=Your Test code +TestStackFrameBgColorDefinition.label=Your Test code background +TestStackFrameFgColorDefinition.description=The color used to render stack frames for Your Test code in the Debug view. +TestStackFrameBgColorDefinition.description=The background color used to render stack frames for Your Test code in the Debug view. + +LibraryStackFrameFgColorDefinition.label=Library code +LibraryStackFrameBgColorDefinition.label=Library code background +LibraryStackFrameFgColorDefinition.description=The color used to render stack frames for Library code in the Debug view. +LibraryStackFrameBgColorDefinition.description=The background color used to render stack frames for Library code in the Debug view. + +ProductionStackFrameFgColorDefinition.label=Your Source code +ProductionStackFrameBgColorDefinition.label=Your Source code background +ProductionStackFrameFgColorDefinition.description=The color used used to render stack frames for Your Source code in the Debug view. +ProductionStackFrameBgColorDefinition.description=The background color used to render stack frames for Your Source code in the Debug view. + javaStackTraceConsole.label= Java Stack Trace Console FormatStackTraceActionDelegate.name= Format FormatStackTraceActionDelegate.tooltip= Format diff --git a/org.eclipse.jdt.debug.ui/plugin.xml b/org.eclipse.jdt.debug.ui/plugin.xml index 878d14182d..a4b13b3c2c 100644 --- a/org.eclipse.jdt.debug.ui/plugin.xml +++ b/org.eclipse.jdt.debug.ui/plugin.xml @@ -2208,6 +2208,15 @@ style="toggle" menubarPath="org.eclipse.jdt.debug.ui.LaunchView.javaSubmenu/javaPart" id="org.eclipse.jdt.debug.ui.launchViewActions.ShowMonitorThreadInfo"/> + + + + + %LabeledObjectColorDefinition.description + + + %CustomFilteredStackFrameFgColorDefinition.description + + + %CustomFilteredStackFrameBgColorDefinition.description + + + + %SyntheticStackFrameFgColorDefinition.description + + + %SyntheticStackFrameBgColorDefinition.description + + + + %PlatformStackFrameFgColorDefinition.description + + + %PlatformStackFrameBgColorDefinition.description + + + + %TestStackFrameFgColorDefinition.description + + + %TestStackFrameBgColorDefinition.description + + + + %ProductionStackFrameFgColorDefinition.description + + + %ProductionStackFrameBgColorDefinition.description + + + + %LibraryStackFrameFgColorDefinition.description + + + %LibraryStackFrameBgColorDefinition.description + diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/DebugUIMessages.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/DebugUIMessages.java index c4392c0273..ed8ab35354 100644 --- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/DebugUIMessages.java +++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/DebugUIMessages.java @@ -100,6 +100,38 @@ public class DebugUIMessages extends NLS { public static String JavaHotCodeReplaceListener_0; + public static String JavaStackFramesPreferencePage_title; + public static String JavaStackFramesPreferencePage_description; + public static String JavaStackFramesPreferencePage__Color_stack_frames; + public static String JavaStackFramesPreferencePage_Defined_stack_frame_filters_for_platform; + public static String JavaStackFramesPreferencePage_Defined_custom_stack_frame_filters; + public static String JavaStackFramesPreferencePage_Appearance_of_stack_frames; + public static String JavaStackFramesPreferencePage_fg_color; + public static String JavaStackFramesPreferencePage_bg_color; + public static String JavaStackFramesPreferencePage_category_platform; + public static String JavaStackFramesPreferencePage_category_synthetic; + public static String JavaStackFramesPreferencePage_category_library; + public static String JavaStackFramesPreferencePage_category_test; + public static String JavaStackFramesPreferencePage_category_production; + public static String JavaStackFramesPreferencePage_category_custom_filter; + public static String JavaStackFramesPreferencePage_Filter_platform; + public static String JavaStackFramesPreferencePage_Filter_synthetic; + public static String JavaStackFramesPreferencePage_Filter_library; + public static String JavaStackFramesPreferencePage_Filter_test; + public static String JavaStackFramesPreferencePage_Filter_production; + public static String JavaStackFramesPreferencePage_Filter_custom; + public static String JavaStackFramesPreferencePage_Add__Filter; + public static String JavaStackFramesPreferencePage_Add__Package; + public static String JavaStackFramesPreferencePage_Add__Type; + public static String JavaStackFramesPreferencePage_Remove; + public static String JavaStackFramesPreferencePage_Enable_All; + public static String JavaStackFramesPreferencePage_Disable_All; + public static String JavaStackFramesPreferencePage_Add_package_for_stack_filters; + public static String JavaStackFramesPreferencePage_Select_a_package_for_stack_filter; + public static String JavaStackFramesPreferencePage_Add_type_for_stack_filters; + public static String JavaStackFramesPreferencePage_Select_a_type_for_stack_filter; + + public static String JavaStepFilterPreferencePage_0; public static String JavaStepFilterPreferencePage_Filter_co_nstructors_19; diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/DebugUIMessages.properties b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/DebugUIMessages.properties index 19af00256f..bc8b934ea3 100644 --- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/DebugUIMessages.properties +++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/DebugUIMessages.properties @@ -47,6 +47,39 @@ JavaHotCodeReplaceListener_0= JavaPrimitivesPreferencePage_0=Primitive Display Options JavaPrimitivesPreferencePage_1=Display options for primitive values +JavaStackFramesPreferencePage_title=Stack Frame Colors +JavaStackFramesPreferencePage_description=Color of the Stack Frames set accordingly to these filters when 'Mark Stack Frames differently' toggle is activated. +JavaStackFramesPreferencePage__Color_stack_frames=Mark Stack Frames differently +JavaStackFramesPreferencePage_Defined_stack_frame_filters_for_platform=Filters to define &Platform methods: +JavaStackFramesPreferencePage_Defined_custom_stack_frame_filters=Filters for High&lighting stack frames: +JavaStackFramesPreferencePage_Appearance_of_stack_frames=&Appearance of the stack frames: +JavaStackFramesPreferencePage_fg_color=&Foreground Color +JavaStackFramesPreferencePage_bg_color=&Background Color +JavaStackFramesPreferencePage_category_custom_filter=Highlighted methods +JavaStackFramesPreferencePage_category_synthetic=Synthetic methods +JavaStackFramesPreferencePage_category_platform=Platform methods +JavaStackFramesPreferencePage_category_test=Your Test code +JavaStackFramesPreferencePage_category_production=Your Source code +JavaStackFramesPreferencePage_category_library=Library code +JavaStackFramesPreferencePage_Filter_custom=Mark &Highlighted stack frames differently +JavaStackFramesPreferencePage_Filter_synthetic=Mark S&ynthetic methods differently +JavaStackFramesPreferencePage_Filter_platform=Mark &Platform methods differently +JavaStackFramesPreferencePage_Filter_test=Mark Your &Test code differently +JavaStackFramesPreferencePage_Filter_production=Mark Your &Source code differently +JavaStackFramesPreferencePage_Filter_library=Mark &Library code differently + +JavaStackFramesPreferencePage_Add__Filter=Add &Filter... +JavaStackFramesPreferencePage_Add__Package=Add &Packages... +JavaStackFramesPreferencePage_Add__Type=Add &Class... +JavaStackFramesPreferencePage_Remove=&Remove +JavaStackFramesPreferencePage_Enable_All=&Enable All +JavaStackFramesPreferencePage_Disable_All=D&isable All + +JavaStackFramesPreferencePage_Add_package_for_stack_filters=Add Packages to Stack Filters +JavaStackFramesPreferencePage_Select_a_package_for_stack_filter=&Select a package for stack filtering: +JavaStackFramesPreferencePage_Add_type_for_stack_filters=Add Class to Stack Filters +JavaStackFramesPreferencePage_Select_a_type_for_stack_filter=&Select a class for stack filtering: + JavaStepFilterPreferencePage_Filter_co_nstructors_19=Filter co&nstructors JavaStepFilterPreferencePage_Filter_s_ynthetic_methods__requires_VM_support__17=Filter s&ynthetic methods (requires VM support) JavaStepFilterPreferencePage_Filter_static__initializers_18=Filter static &initializers diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/IJDIPreferencesConstants.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/IJDIPreferencesConstants.java index 6f0af1f7d4..758b6360e7 100644 --- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/IJDIPreferencesConstants.java +++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/IJDIPreferencesConstants.java @@ -80,8 +80,43 @@ public interface IJDIPreferencesConstants { public static final String PREF_STEP_THRU_FILTERS = IJavaDebugUIConstants.PLUGIN_ID + ".step_thru_filters"; //$NON-NLS-1$ /** - * List of active step filters. A String containing a comma - * separated list of fully qualified type names/patterns. + * Boolean preference indicating whether to colorize the stack frames in the debug view. + * + */ + public static final String PREF_COLORIZE_STACK_FRAMES = IJavaDebugUIConstants.PLUGIN_ID + ".colorize_stack_frames"; //$NON-NLS-1$ + public static final String PREF_COLORIZE_PLATFORM_METHODS = IJavaDebugUIConstants.PLUGIN_ID + ".colorize_platform_methods"; //$NON-NLS-1$ + public static final String PREF_COLORIZE_SYNTHETIC_METHODS = IJavaDebugUIConstants.PLUGIN_ID + ".colorize_synthetic_methods"; //$NON-NLS-1$ + public static final String PREF_COLORIZE_LIBRARY_METHODS = IJavaDebugUIConstants.PLUGIN_ID + ".colorize_library_methods"; //$NON-NLS-1$ + public static final String PREF_COLORIZE_TEST_METHODS = IJavaDebugUIConstants.PLUGIN_ID + ".colorize_test_methods"; //$NON-NLS-1$ + public static final String PREF_COLORIZE_PRODUCTION_METHODS = IJavaDebugUIConstants.PLUGIN_ID + ".colorize_production_methods"; //$NON-NLS-1$ + public static final String PREF_COLORIZE_CUSTOM_METHODS = IJavaDebugUIConstants.PLUGIN_ID + ".colorize_custom_methods"; //$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_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$ @@ -218,6 +253,25 @@ public interface IJDIPreferencesConstants { public static final String PREF_THREAD_MONITOR_IN_DEADLOCK_COLOR= "org.eclipse.jdt.debug.ui.InDeadlockColor"; //$NON-NLS-1$ public static final String PREF_LABELED_OBJECT_COLOR = IJavaDebugUIConstants.PLUGIN_ID + ".LabeledObject"; //$NON-NLS-1$ + + public static final String PREF_TEST_STACK_FRAME_FG_COLOR = IJavaDebugUIConstants.PLUGIN_ID + ".TestStackFrameFgColor"; //$NON-NLS-1$ + public static final String PREF_TEST_STACK_FRAME_BG_COLOR = IJavaDebugUIConstants.PLUGIN_ID + ".TestStackFrameBgColor"; //$NON-NLS-1$ + + public static final String PREF_LIB_STACK_FRAME_FG_COLOR = IJavaDebugUIConstants.PLUGIN_ID + ".LibraryStackFrameFgColor"; //$NON-NLS-1$ + public static final String PREF_LIB_STACK_FRAME_BG_COLOR = IJavaDebugUIConstants.PLUGIN_ID + ".LibraryStackFrameBgColor"; //$NON-NLS-1$ + + public static final String PREF_SYNT_STACK_FRAME_FG_COLOR = IJavaDebugUIConstants.PLUGIN_ID + ".SyntheticStackFrameFgColor"; //$NON-NLS-1$ + public static final String PREF_SYNT_STACK_FRAME_BG_COLOR = IJavaDebugUIConstants.PLUGIN_ID + ".SyntheticStackFrameBgColor"; //$NON-NLS-1$ + + public static final String PREF_PLATFORM_STACK_FRAME_FG_COLOR = IJavaDebugUIConstants.PLUGIN_ID + ".PlatformStackFrameFgColor"; //$NON-NLS-1$ + public static final String PREF_PLATFORM_STACK_FRAME_BG_COLOR = IJavaDebugUIConstants.PLUGIN_ID + ".PlatformStackFrameBgColor"; //$NON-NLS-1$ + + public static final String PREF_PRODUCTION_STACK_FRAME_FG_COLOR = IJavaDebugUIConstants.PLUGIN_ID + ".ProductionStackFrameFgColor"; //$NON-NLS-1$ + public static final String PREF_PRODUCTION_STACK_FRAME_BG_COLOR = IJavaDebugUIConstants.PLUGIN_ID + ".ProductionStackFrameBgColor"; //$NON-NLS-1$ + + public static final String PREF_CUSTOM_FILTERED_STACK_FRAME_FG_COLOR = IJavaDebugUIConstants.PLUGIN_ID + ".CustomFilteredStackFrameFgColor"; //$NON-NLS-1$ + public static final String PREF_CUSTOM_FILTERED_STACK_FRAME_BG_COLOR = IJavaDebugUIConstants.PLUGIN_ID + ".CustomFilteredStackFrameBgColor"; //$NON-NLS-1$ + /** * @since 3.2 */ diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/IJavaDebugHelpContextIds.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/IJavaDebugHelpContextIds.java index fdff70b19b..cf73993858 100644 --- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/IJavaDebugHelpContextIds.java +++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/IJavaDebugHelpContextIds.java @@ -53,6 +53,7 @@ public interface IJavaDebugHelpContextIds { public static final String LAUNCH_JRE_PROPERTY_PAGE= PREFIX + "launch_jre_property_page_context"; //$NON-NLS-1$ public static final String JAVA_DEBUG_PREFERENCE_PAGE= PREFIX + "java_debug_preference_page_context"; //$NON-NLS-1$ public static final String JAVA_STEP_FILTER_PREFERENCE_PAGE= PREFIX + "java_step_filter_preference_page_context"; //$NON-NLS-1$ + public static final String JAVA_STACK_FRAMES_PREFERENCE_PAGE = PREFIX + "java_stack_frames_preference_page_context"; //$NON-NLS-1$ public static final String JAVA_BREAKPOINT_PREFERENCE_PAGE= PREFIX + "java_breakpoint_preference_page_context"; //$NON-NLS-1$ public static final String JAVA_DETAIL_FORMATTER_PREFERENCE_PAGE= PREFIX + "java_detail_formatter_preference_page_context"; //$NON-NLS-1$ public static final String JAVA_PRIMITIVES_PREFERENCE_PAGE= PREFIX + "java_primitives_preference_page_context"; //$NON-NLS-1$ diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JDIDebugUIPreferenceInitializer.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JDIDebugUIPreferenceInitializer.java index b5963e4aa9..73248d2bd1 100644 --- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JDIDebugUIPreferenceInitializer.java +++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JDIDebugUIPreferenceInitializer.java @@ -46,6 +46,19 @@ 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); + // JavaStackFramePreferencePage + 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, ""); //$NON-NLS-1$ + store.setDefault(IJDIPreferencesConstants.PREF_ACTIVE_CUSTOM_FRAME_FILTER_LIST, ""); //$NON-NLS-1$ + store.setDefault(IJDIPreferencesConstants.PREF_INACTIVE_CUSTOM_FRAME_FILTER_LIST, ""); //$NON-NLS-1$ + store.setDefault(IJDIPreferencesConstants.PREF_COLORIZE_STACK_FRAMES, true); + store.setDefault(IJDIPreferencesConstants.PREF_COLORIZE_PLATFORM_METHODS, true); + store.setDefault(IJDIPreferencesConstants.PREF_COLORIZE_SYNTHETIC_METHODS, true); + store.setDefault(IJDIPreferencesConstants.PREF_COLORIZE_LIBRARY_METHODS, true); + store.setDefault(IJDIPreferencesConstants.PREF_COLORIZE_TEST_METHODS, true); + store.setDefault(IJDIPreferencesConstants.PREF_COLORIZE_PRODUCTION_METHODS, true); + store.setDefault(IJDIPreferencesConstants.PREF_COLORIZE_CUSTOM_METHODS, 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$ diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JDIModelPresentation.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JDIModelPresentation.java index 18503d450f..2699986338 100644 --- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JDIModelPresentation.java +++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JDIModelPresentation.java @@ -149,6 +149,8 @@ public class JDIModelPresentation extends LabelProvider implements IDebugModelPr private JavaElementLabelProvider fJavaLabelProvider; + private StackFramePresentationProvider fStackFrameProvider; + public JDIModelPresentation() { super(); } @@ -163,6 +165,9 @@ public void dispose() { fJavaLabelProvider.dispose(); } fAttributes.clear(); + if (fStackFrameProvider != null) { + fStackFrameProvider.close(); + } } /** @@ -187,7 +192,7 @@ public void computeDetail(IValue value, IValueDetailListener listener) { * required * @return thread or null */ - public static IJavaThread getEvaluationThread(IJavaDebugTarget target) { + private static IJavaThread getEvaluationThread(IJavaDebugTarget target) { IJavaStackFrame frame = EvaluationContextManager.getEvaluationContext((IWorkbenchWindow)null); IJavaThread thread = null; if (frame != null) { @@ -727,7 +732,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) { @@ -749,8 +757,7 @@ public Image getImage(Object item) { return getJavaWaitingThreadImage((JavaWaitingThread)item); } if (item instanceof NoMonitorInformationElement) { - return getDebugImageRegistry().get(new JDIImageDescriptor( - getImageDescriptor(JavaDebugImages.IMG_OBJS_MONITOR), 0)); + return getDebugImage(getImageDescriptor(JavaDebugImages.IMG_OBJS_MONITOR), 0); } } catch (CoreException e) { // no need to log errors - elements may no longer exist by the time we render them @@ -778,14 +785,11 @@ private synchronized void initImageRegistries() { * @return */ private Image getJavaWaitingThreadImage(JavaWaitingThread thread) { - JDIImageDescriptor descriptor; int flag= JDIImageDescriptor.IN_CONTENTION_FOR_MONITOR | (thread.getThread().isInDeadlock() ? JDIImageDescriptor.IN_DEADLOCK : 0); if (thread.isSuspended()) { - descriptor= new JDIImageDescriptor(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_THREAD_SUSPENDED), flag); - } else { - descriptor= new JDIImageDescriptor(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_THREAD_RUNNING), flag); + return getDebugImage(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_THREAD_SUSPENDED), flag); } - return getDebugImageRegistry().get(descriptor); + return getDebugImage(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_THREAD_RUNNING), flag); } /** @@ -793,14 +797,11 @@ private Image getJavaWaitingThreadImage(JavaWaitingThread thread) { * @return */ private Image getJavaOwningThreadImage(JavaOwningThread thread) { - JDIImageDescriptor descriptor; int flag= JDIImageDescriptor.OWNS_MONITOR | (thread.getThread().isInDeadlock() ? JDIImageDescriptor.IN_DEADLOCK : 0); if (thread.isSuspended()) { - descriptor= new JDIImageDescriptor(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_THREAD_SUSPENDED), flag); - } else { - descriptor= new JDIImageDescriptor(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_THREAD_RUNNING), flag); + return getDebugImage(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_THREAD_SUSPENDED), flag); } - return getDebugImageRegistry().get(descriptor); + return getDebugImage(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_THREAD_RUNNING), flag); } /** @@ -809,9 +810,7 @@ private Image getJavaOwningThreadImage(JavaOwningThread thread) { */ private Image getJavaContendedMonitorImage(JavaContendedMonitor monitor) { int flag= monitor.getMonitor().isInDeadlock() ? JDIImageDescriptor.IN_DEADLOCK : 0; - JDIImageDescriptor descriptor= new JDIImageDescriptor( - getImageDescriptor(JavaDebugImages.IMG_OBJS_CONTENDED_MONITOR), flag); - return getDebugImageRegistry().get(descriptor); + return getDebugImage(getImageDescriptor(JavaDebugImages.IMG_OBJS_CONTENDED_MONITOR), flag); } /** @@ -820,8 +819,7 @@ private Image getJavaContendedMonitorImage(JavaContendedMonitor monitor) { */ private Image getJavaOwnedMonitorImage(JavaOwnedMonitor monitor) { int flag= monitor.getMonitor().isInDeadlock() ? JDIImageDescriptor.IN_DEADLOCK : 0; - JDIImageDescriptor descriptor= new JDIImageDescriptor(getImageDescriptor(JavaDebugImages.IMG_OBJS_OWNED_MONITOR), flag); - return getDebugImageRegistry().get(descriptor); + return getDebugImage(getImageDescriptor(JavaDebugImages.IMG_OBJS_OWNED_MONITOR), flag); } protected Image getBreakpointImage(IJavaBreakpoint breakpoint) throws CoreException { @@ -839,15 +837,13 @@ protected Image getBreakpointImage(IJavaBreakpoint breakpoint) throws CoreExcept protected Image getExceptionBreakpointImage(IJavaExceptionBreakpoint exception) throws CoreException { int flags= computeBreakpointAdornmentFlags(exception); - JDIImageDescriptor descriptor= null; if ((flags & JDIImageDescriptor.ENABLED) == 0) { - descriptor= new JDIImageDescriptor(getImageDescriptor(JavaDebugImages.IMG_OBJS_EXCEPTION_DISABLED), flags); + return getDebugImage(getImageDescriptor(JavaDebugImages.IMG_OBJS_EXCEPTION_DISABLED), flags); } else if (exception.isChecked()) { - descriptor= new JDIImageDescriptor(getImageDescriptor(JavaDebugImages.IMG_OBJS_EXCEPTION), flags); + return getDebugImage(getImageDescriptor(JavaDebugImages.IMG_OBJS_EXCEPTION), flags); } else { - descriptor= new JDIImageDescriptor(getImageDescriptor(JavaDebugImages.IMG_OBJS_ERROR), flags); + return getDebugImage(getImageDescriptor(JavaDebugImages.IMG_OBJS_ERROR), flags); } - return getDebugImageRegistry().get(descriptor); } protected Image getJavaBreakpointImage(IJavaBreakpoint breakpoint) throws CoreException { @@ -862,81 +858,61 @@ protected Image getJavaBreakpointImage(IJavaBreakpoint breakpoint) throws CoreEx return getJavaMethodEntryBreakpointImage(meBreakpoint); } else { int flags= computeBreakpointAdornmentFlags(breakpoint); - JDIImageDescriptor descriptor= null; if (breakpoint.isEnabled()) { - descriptor= new JDIImageDescriptor(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_BREAKPOINT), flags); - } else { - descriptor= new JDIImageDescriptor(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_BREAKPOINT_DISABLED), flags); + return getDebugImage(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_BREAKPOINT), flags); } - return getDebugImageRegistry().get(descriptor); + return getDebugImage(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_BREAKPOINT_DISABLED), flags); } } protected Image getJavaMethodBreakpointImage(IJavaMethodBreakpoint mBreakpoint) throws CoreException { int flags= computeBreakpointAdornmentFlags(mBreakpoint); - JDIImageDescriptor descriptor= null; if (mBreakpoint.isEnabled()) { - descriptor= new JDIImageDescriptor(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_BREAKPOINT), flags); - } else { - descriptor= new JDIImageDescriptor(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_BREAKPOINT_DISABLED), flags); + return getDebugImage(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_BREAKPOINT), flags); } - - return getDebugImageRegistry().get(descriptor); + return getDebugImage(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_BREAKPOINT_DISABLED), flags); } protected Image getJavaMethodEntryBreakpointImage(IJavaMethodEntryBreakpoint mBreakpoint) throws CoreException { int flags= computeBreakpointAdornmentFlags(mBreakpoint); - JDIImageDescriptor descriptor= null; if (mBreakpoint.isEnabled()) { - descriptor= new JDIImageDescriptor(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_BREAKPOINT), flags); - } else { - descriptor= new JDIImageDescriptor(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_BREAKPOINT_DISABLED), flags); + return getDebugImage(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_BREAKPOINT), flags); } - - return getDebugImageRegistry().get(descriptor); + return getDebugImage(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_BREAKPOINT_DISABLED), flags); } protected Image getClassPrepareBreakpointImage(IJavaClassPrepareBreakpoint breakpoint) throws CoreException { int flags= computeBreakpointAdornmentFlags(breakpoint); - JDIImageDescriptor descriptor= null; if (breakpoint.getMemberType() == IJavaClassPrepareBreakpoint.TYPE_CLASS) { - descriptor= new JDIImageDescriptor(JavaUI.getSharedImages().getImageDescriptor(ISharedImages.IMG_OBJS_CLASS), flags); - } else { - descriptor= new JDIImageDescriptor(JavaUI.getSharedImages().getImageDescriptor(ISharedImages.IMG_OBJS_INTERFACE), flags); + return getDebugImage(JavaUI.getSharedImages().getImageDescriptor(ISharedImages.IMG_OBJS_CLASS), flags); } - return getDebugImageRegistry().get(descriptor); + return getDebugImage(JavaUI.getSharedImages().getImageDescriptor(ISharedImages.IMG_OBJS_INTERFACE), flags); } protected Image getJavaWatchpointImage(IJavaWatchpoint watchpoint) throws CoreException { - int flags= computeBreakpointAdornmentFlags(watchpoint); - JDIImageDescriptor descriptor= null; - boolean enabled= (flags & JDIImageDescriptor.ENABLED) != 0; + final int flags = computeBreakpointAdornmentFlags(watchpoint); + final boolean enabled = (flags & JDIImageDescriptor.ENABLED) != 0; if (watchpoint.isAccess()) { if (watchpoint.isModification()) { //access and modification if (enabled) { - descriptor= new JDIImageDescriptor(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_WATCHPOINT), flags); - } else { - descriptor= new JDIImageDescriptor(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_WATCHPOINT_DISABLED), flags); - } - } else { - if (enabled) { - descriptor= new JDIImageDescriptor(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_ACCESS_WATCHPOINT), flags); - } else { - descriptor= new JDIImageDescriptor(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_ACCESS_WATCHPOINT_DISABLED), flags); + return getDebugImage(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_WATCHPOINT), flags); } + return getDebugImage(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_WATCHPOINT_DISABLED), flags); + } + if (enabled) { + return getDebugImage(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_ACCESS_WATCHPOINT), flags); } + return getDebugImage(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_ACCESS_WATCHPOINT_DISABLED), flags); } else if (watchpoint.isModification()) { if (enabled) { - descriptor= new JDIImageDescriptor(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_MODIFICATION_WATCHPOINT), flags); - } else { - descriptor= new JDIImageDescriptor(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_MODIFICATION_WATCHPOINT_DISABLED), flags); + return getDebugImage(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_MODIFICATION_WATCHPOINT), flags); } + return getDebugImage(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_MODIFICATION_WATCHPOINT_DISABLED), flags); } else { //neither access nor modification - descriptor= new JDIImageDescriptor(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_WATCHPOINT_DISABLED), flags); + return getDebugImage(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_WATCHPOINT_DISABLED), flags); } - return getDebugImageRegistry().get(descriptor); } protected Image getVariableImage(IAdaptable element) { @@ -993,10 +969,28 @@ protected Image getDebugElementImage(Object element) { return null; } int flags= computeJDIAdornmentFlags(element); - JDIImageDescriptor descriptor= new JDIImageDescriptor(image, flags); - return getDebugImageRegistry().get(descriptor); + return getDebugImage(image, flags); } + 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 null * if none is defined. @@ -1015,7 +1009,7 @@ protected Image getExpressionImage(Object expression) { if (bigSize) { descriptor.setSize(BIG_SIZE); } - return getDebugImageRegistry().get(descriptor); + return getDebugImage(descriptor); } /** @@ -1025,15 +1019,6 @@ protected Image getExpressionImage(Object expression) { */ 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); @@ -1271,6 +1256,10 @@ protected boolean isShowVariableTypeNames() { } } + protected boolean isColorizeStackFrames() { + return getStackFrameProvider().isColorizeStackFrames(); + } + protected boolean isShowHexValues() { return JDIDebugUIPlugin.getDefault().getPreferenceStore().getBoolean(IJDIPreferencesConstants.PREF_SHOW_HEX); } @@ -2031,14 +2020,14 @@ private List getNameList(String listName) { /** * Plug in the single argument to the resource String for the key to get a formatted resource String */ - public static String getFormattedString(String key, String arg) { + private static String getFormattedString(String key, String arg) { return getFormattedString(key, new String[] {arg}); } /** * Plug in the arguments to the resource String for the key to get a formatted resource String */ - public static String getFormattedString(String string, String[] args) { + private static String getFormattedString(String string, String[] args) { return NLS.bind(string, args); } @@ -2078,13 +2067,21 @@ protected void appendInstanceFilter(IJavaBreakpoint breakpoint, StringBuilder bu } } - protected static org.eclipse.jdt.internal.debug.ui.ImageDescriptorRegistry getDebugImageRegistry() { + private static org.eclipse.jdt.internal.debug.ui.ImageDescriptorRegistry getDebugImageRegistry() { if (fgDebugImageRegistry == null) { fgDebugImageRegistry = JDIDebugUIPlugin.getImageDescriptorRegistry(); } return fgDebugImageRegistry; } + private static Image getDebugImage(ImageDescriptor descriptor) { + return getDebugImageRegistry().get(descriptor); + } + + private static Image getDebugImage(ImageDescriptor descriptor, int flags) { + return getDebugImageRegistry().get(new JDIImageDescriptor(descriptor, flags)); + } + protected JavaElementLabelProvider getJavaLabelProvider() { if (fJavaLabelProvider == null) { fJavaLabelProvider = new JavaElementLabelProvider(JavaElementLabelProvider.SHOW_DEFAULT); @@ -2092,6 +2089,12 @@ protected JavaElementLabelProvider getJavaLabelProvider() { return fJavaLabelProvider; } + private StackFramePresentationProvider getStackFrameProvider() { + if (fStackFrameProvider == null) { + fStackFrameProvider = new StackFramePresentationProvider(); + } + return fStackFrameProvider; + } /** * Returns whether the given field variable has the same name as any variables */ @@ -2158,6 +2161,11 @@ public Color getForeground(Object element) { if (element instanceof IJavaThread && ThreadMonitorManager.getDefault().isInDeadlock((IJavaThread)element)) { return getColorFromRegistry(IJDIPreferencesConstants.PREF_THREAD_MONITOR_IN_DEADLOCK_COLOR); } + if (element instanceof IJavaStackFrame && isColorizeStackFrames()) { + IJavaStackFrame frame = (IJavaStackFrame) element; + + return getStackFrameProvider().getForeground(frame); + } return null; } @@ -2173,6 +2181,11 @@ protected Color getColorFromRegistry(String symbolicName) { */ @Override public Color getBackground(Object element) { + if (element instanceof IJavaStackFrame && isColorizeStackFrames()) { + IJavaStackFrame frame = (IJavaStackFrame) element; + + return getStackFrameProvider().getBackground(frame); + } return null; } diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JavaStackFramePreferencePage.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JavaStackFramePreferencePage.java new file mode 100644 index 0000000000..521843028a --- /dev/null +++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JavaStackFramePreferencePage.java @@ -0,0 +1,429 @@ +/******************************************************************************* + * Copyright (c) 2022 Zsombor Gegesy and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Zsombor Gegesy - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.debug.ui; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; + +import org.eclipse.debug.internal.ui.SWTFactory; +import org.eclipse.jdt.debug.core.IJavaStackFrame; +import org.eclipse.jdt.debug.core.IJavaStackFrame.Category; +import org.eclipse.jdt.internal.ui.filtertable.FilterManager; +import org.eclipse.jdt.internal.ui.filtertable.JavaFilterTable; +import org.eclipse.jdt.internal.ui.filtertable.JavaFilterTable.ButtonLabel; +import org.eclipse.jdt.internal.ui.filtertable.JavaFilterTable.DialogLabels; +import org.eclipse.jdt.internal.ui.filtertable.JavaFilterTable.FilterTableConfig; +import org.eclipse.jface.preference.ColorSelector; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.preference.PreferencePage; +import org.eclipse.jface.util.PropertyChangeEvent; +import org.eclipse.jface.viewers.IColorProvider; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPreferencePage; +import org.eclipse.ui.PlatformUI; + +/** + * The preference page for Java stack frame categorization, located at the node Java > Debug > Stack Frames + * + * @since 3.19 + */ +public class JavaStackFramePreferencePage extends PreferencePage implements IWorkbenchPreferencePage { + + private static class CategoryColors { + final IJavaStackFrame.Category category; + final String key; + Color fgColor; + Color bgColor; + + CategoryColors(Category category, String key) { + this.category = category; + this.key = key; + } + + Color getForegroundColor(StackFramePresentationProvider stackFramePresentationProvider) { + if (fgColor != null) { + return fgColor; + } + return stackFramePresentationProvider.getForegroundColor(category); + } + + Color getBackgroundColor(StackFramePresentationProvider stackFramePresentationProvider) { + if (bgColor != null) { + return bgColor; + } + return stackFramePresentationProvider.getBackgroundColor(category); + } + + void setToDefault() { + this.fgColor = null; + this.bgColor = null; + } + } + + private class StackFrameCategoryLabelProvider extends LabelProvider implements IColorProvider { + + @Override + public String getText(Object element) { + return ((CategoryColors) element).key; + } + + @Override + public Color getForeground(Object element) { + return ((CategoryColors) element).getForegroundColor(stackFramePresentationProvider); + } + + @Override + public Color getBackground(Object element) { + return ((CategoryColors) element).getBackgroundColor(stackFramePresentationProvider); + } + } + + private static class StackFrameCategoryContentProvider implements IStructuredContentProvider { + @Override + public Object[] getElements(Object inputElement) { + return ((java.util.List) inputElement).toArray(); + } + } + + private static class PreferenceButton { + private final Button button; + private final String flag; + + PreferenceButton(Composite container, String label, IPreferenceStore store, String flag) { + this.button = SWTFactory.createCheckButton(container, label, null, store.getBoolean(flag), 2); + this.flag = flag; + } + + boolean performDefault(IPreferenceStore store) { + var defValue = store.getBoolean(flag); + button.setSelection(defValue); + return defValue; + } + + void performOk(IPreferenceStore store) { + store.setValue(flag, button.getSelection()); + } + + boolean isSelected() { + return button.getSelection(); + } + + void setEnabled(boolean enabled) { + this.button.setEnabled(enabled); + } + + PreferenceButton widgetSelected(Consumer consumer) { + this.button.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + consumer.accept(button.getSelection()); + } + }); + return this; + } + } + + public static final String PAGE_ID = "org.eclipse.jdt.debug.ui.JavaStackFramePreferencePage"; //$NON-NLS-1$ + final static FilterManager PLATFORM_STACK_FRAMES = new FilterManager(IJDIPreferencesConstants.PREF_ACTIVE_PLATFORM_FRAME_FILTER_LIST, IJDIPreferencesConstants.PREF_INACTIVE_PLATFORM_FRAME_FILTER_LIST); + final static FilterManager CUSTOM_STACK_FRAMES = new FilterManager(IJDIPreferencesConstants.PREF_ACTIVE_CUSTOM_FRAME_FILTER_LIST, IJDIPreferencesConstants.PREF_INACTIVE_CUSTOM_FRAME_FILTER_LIST); + + //widgets + private PreferenceButton fColorizeStackFrames; + private List categoryButtons; + private PreferenceButton fEnablePlatformButton; + private PreferenceButton fEnableCustomButton; + private JavaFilterTable fPlatformStackFilterTable; + private JavaFilterTable fCustomStackFilterTable; + private TableViewer fAppearanceList; + private List colors; + private ColorSelector fFgColorSelector; + private ColorSelector fBgColorSelector; + private StackFramePresentationProvider stackFramePresentationProvider; + + /** + * Constructor + */ + public JavaStackFramePreferencePage() { + super(); + setPreferenceStore(JDIDebugUIPlugin.getDefault().getPreferenceStore()); + setTitle(DebugUIMessages.JavaStackFramesPreferencePage_title); + setDescription(DebugUIMessages.JavaStackFramesPreferencePage_description); + stackFramePresentationProvider = new StackFramePresentationProvider(getPreferenceStore()); + categoryButtons = new ArrayList<>(); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.preference.PreferencePage#createContents(org.eclipse.swt.widgets.Composite) + */ + @Override + protected Control createContents(Composite parent) { + PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), IJavaDebugHelpContextIds.JAVA_STACK_FRAMES_PREFERENCE_PAGE); + // The main composite + Composite composite = SWTFactory.createComposite(parent, parent.getFont(), 1, 1, GridData.FILL_BOTH, 0, 0); + createStepFilterPreferences(composite); + return composite; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench) + */ + @Override + public void init(IWorkbench workbench) {} + + /** + * Create a group to contain the step filter related widgetry + */ + private void createStepFilterPreferences(Composite parent) { + var store = getPreferenceStore(); + Composite container = SWTFactory.createComposite(parent, parent.getFont(), 2, 1, GridData.FILL_BOTH, 0, 0); + fColorizeStackFrames = new PreferenceButton(container, DebugUIMessages.JavaStackFramesPreferencePage__Color_stack_frames, store, IJDIPreferencesConstants.PREF_COLORIZE_STACK_FRAMES); + fColorizeStackFrames.widgetSelected(this::setPageEnablement); + initializeDialogUnits(container); + + this.fEnableCustomButton = new PreferenceButton(container, DebugUIMessages.JavaStackFramesPreferencePage_Filter_custom, store, IJDIPreferencesConstants.PREF_COLORIZE_CUSTOM_METHODS).widgetSelected(selected -> fCustomStackFilterTable.setEnabled(selected + && fColorizeStackFrames.isSelected())); + categoryButtons.add(this.fEnableCustomButton); + + fCustomStackFilterTable = new JavaFilterTable(this, CUSTOM_STACK_FRAMES, + new FilterTableConfig() // configuration for the table + .setAddFilter(new ButtonLabel(DebugUIMessages.JavaStackFramesPreferencePage_Add__Filter)) + .setAddPackage(new ButtonLabel(DebugUIMessages.JavaStackFramesPreferencePage_Add__Package)) + .setAddType(new ButtonLabel(DebugUIMessages.JavaStackFramesPreferencePage_Add__Type)) + .setRemove(new ButtonLabel(DebugUIMessages.JavaStackFramesPreferencePage_Remove)) + .setSelectAll(new ButtonLabel(DebugUIMessages.JavaStackFramesPreferencePage_Enable_All)) + .setDeselectAll(new ButtonLabel(DebugUIMessages.JavaStackFramesPreferencePage_Disable_All)) + .setAddPackageDialog(new DialogLabels(DebugUIMessages.JavaStackFramesPreferencePage_Add_package_for_stack_filters, DebugUIMessages.JavaStackFramesPreferencePage_Select_a_package_for_stack_filter)) + .setAddTypeDialog(new DialogLabels(DebugUIMessages.JavaStackFramesPreferencePage_Add_type_for_stack_filters, DebugUIMessages.JavaStackFramesPreferencePage_Select_a_package_for_stack_filter)) + .setLabelText(DebugUIMessages.JavaStackFramesPreferencePage_Defined_custom_stack_frame_filters) + .setHelpContextId(IJavaDebugHelpContextIds.JAVA_STACK_FRAMES_PREFERENCE_PAGE)); + fCustomStackFilterTable.createTable(container); + + categoryButtons.add(new PreferenceButton(container, DebugUIMessages.JavaStackFramesPreferencePage_Filter_synthetic, store, IJDIPreferencesConstants.PREF_COLORIZE_SYNTHETIC_METHODS)); + + this.fEnablePlatformButton = new PreferenceButton(container, DebugUIMessages.JavaStackFramesPreferencePage_Filter_platform, store, IJDIPreferencesConstants.PREF_COLORIZE_PLATFORM_METHODS).widgetSelected(selected -> fPlatformStackFilterTable.setEnabled(selected + && fColorizeStackFrames.isSelected())); + categoryButtons.add(fEnablePlatformButton); + + fPlatformStackFilterTable = new JavaFilterTable(this, PLATFORM_STACK_FRAMES, + new FilterTableConfig() + .setAddFilter(new ButtonLabel(DebugUIMessages.JavaStackFramesPreferencePage_Add__Filter)) + .setAddPackage(new ButtonLabel(DebugUIMessages.JavaStackFramesPreferencePage_Add__Package)) + .setAddType(new ButtonLabel(DebugUIMessages.JavaStackFramesPreferencePage_Add__Type)) + .setRemove(new ButtonLabel(DebugUIMessages.JavaStackFramesPreferencePage_Remove)) + .setSelectAll(new ButtonLabel(DebugUIMessages.JavaStackFramesPreferencePage_Enable_All)) + .setDeselectAll(new ButtonLabel(DebugUIMessages.JavaStackFramesPreferencePage_Disable_All)) + .setAddPackageDialog(new DialogLabels(DebugUIMessages.JavaStackFramesPreferencePage_Add_package_for_stack_filters, + DebugUIMessages.JavaStackFramesPreferencePage_Select_a_package_for_stack_filter)) + .setAddTypeDialog(new DialogLabels(DebugUIMessages.JavaStackFramesPreferencePage_Add_type_for_stack_filters, + DebugUIMessages.JavaStackFramesPreferencePage_Select_a_package_for_stack_filter)) + .setLabelText(DebugUIMessages.JavaStackFramesPreferencePage_Defined_stack_frame_filters_for_platform) + .setHelpContextId(IJavaDebugHelpContextIds.JAVA_STACK_FRAMES_PREFERENCE_PAGE) + ); + fPlatformStackFilterTable.createTable(container); + + categoryButtons.add(new PreferenceButton(container, DebugUIMessages.JavaStackFramesPreferencePage_Filter_test, store, IJDIPreferencesConstants.PREF_COLORIZE_TEST_METHODS)); + categoryButtons.add(new PreferenceButton(container, DebugUIMessages.JavaStackFramesPreferencePage_Filter_production, store, IJDIPreferencesConstants.PREF_COLORIZE_PRODUCTION_METHODS)); + categoryButtons.add(new PreferenceButton(container, DebugUIMessages.JavaStackFramesPreferencePage_Filter_library, store, IJDIPreferencesConstants.PREF_COLORIZE_LIBRARY_METHODS)); + + createAppearanceList(container); + + setPageEnablement(fColorizeStackFrames.isSelected()); + initList(); + } + + private void createAppearanceList(Composite container) { + + SWTFactory.createLabel(container, DebugUIMessages.JavaStackFramesPreferencePage_Appearance_of_stack_frames, 2); + + var editorComposite = new Composite(container, SWT.NONE); + var layout = new GridLayout(); + layout.numColumns = 2; + layout.marginHeight = 0; + layout.marginWidth = 0; + editorComposite.setLayout(layout); + var gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.FILL_VERTICAL); + gd.horizontalSpan = 2; + editorComposite.setLayoutData(gd); + + fAppearanceList = new TableViewer(editorComposite, SWT.SINGLE | SWT.V_SCROLL | SWT.BORDER | SWT.FULL_SELECTION); + fAppearanceList.setLabelProvider(new StackFrameCategoryLabelProvider()); + fAppearanceList.setContentProvider(new StackFrameCategoryContentProvider()); + + gd = new GridData(SWT.BEGINNING, SWT.FILL, false, true); + gd.heightHint = convertHeightInCharsToPixels(8); + fAppearanceList.getControl().setLayoutData(gd); + fAppearanceList.addSelectionChangedListener(event -> { + var selection = event.getStructuredSelection(); + var valid = !selection.isEmpty(); + fFgColorSelector.getButton().setEnabled(valid); + fBgColorSelector.getButton().setEnabled(valid); + if (valid) { + CategoryColors category = (CategoryColors) selection.getFirstElement(); + var color = category.getForegroundColor(stackFramePresentationProvider); + if (color != null) { + fFgColorSelector.setColorValue(color.getRGB()); + } + var bgColor = category.getBackgroundColor(stackFramePresentationProvider); + if (bgColor != null) { + fBgColorSelector.setColorValue(bgColor.getRGB()); + } + } + }); + + Composite stylesComposite = new Composite(editorComposite, SWT.NONE); + layout = new GridLayout(); + layout.marginHeight = 0; + layout.marginWidth = 0; + layout.numColumns = 2; + stylesComposite.setLayout(layout); + stylesComposite.setLayoutData(new GridData(GridData.FILL_BOTH)); + + SWTFactory.createLabel(stylesComposite, DebugUIMessages.JavaStackFramesPreferencePage_fg_color, 1); + + fFgColorSelector = createColorSelector(stylesComposite); + fFgColorSelector.addListener(event -> { + var selection = getSelected(); + if (selection != null) { + selection.fgColor = toColor(event); + fAppearanceList.update(selection, null); + } + }); + + SWTFactory.createLabel(stylesComposite, DebugUIMessages.JavaStackFramesPreferencePage_bg_color, 1); + + fBgColorSelector = createColorSelector(stylesComposite); + fBgColorSelector.addListener(event -> { + var selection = getSelected(); + if (selection != null) { + selection.bgColor = toColor(event); + fAppearanceList.update(selection, null); + } + }); + } + + private CategoryColors getSelected() { + var selection = fAppearanceList.getStructuredSelection().getFirstElement(); + if (selection instanceof CategoryColors) { + return (CategoryColors) selection; + } + return null; + } + + private Color toColor(PropertyChangeEvent event) { + return new Color((RGB) event.getNewValue()); + } + + private ColorSelector createColorSelector(Composite stylesComposite) { + var colorSelector = new ColorSelector(stylesComposite); + Button button = colorSelector.getButton(); + var gd = new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalAlignment = GridData.BEGINNING; + button.setLayoutData(gd); + return colorSelector; + } + + private void initList() { + colors = List.of( + new CategoryColors(IJavaStackFrame.Category.CUSTOM_FILTERED, DebugUIMessages.JavaStackFramesPreferencePage_category_custom_filter), // + new CategoryColors(IJavaStackFrame.Category.SYNTHETIC, DebugUIMessages.JavaStackFramesPreferencePage_category_synthetic), // + new CategoryColors(IJavaStackFrame.Category.PLATFORM, DebugUIMessages.JavaStackFramesPreferencePage_category_platform), // + new CategoryColors(IJavaStackFrame.Category.TEST, DebugUIMessages.JavaStackFramesPreferencePage_category_test), // + new CategoryColors(IJavaStackFrame.Category.PRODUCTION, DebugUIMessages.JavaStackFramesPreferencePage_category_production), // + new CategoryColors(IJavaStackFrame.Category.LIBRARY, DebugUIMessages.JavaStackFramesPreferencePage_category_library) // + ); + fAppearanceList.setInput(colors); + fAppearanceList.setSelection(new StructuredSelection(colors.get(0))); + } + + /** + * Enables or disables the widgets on the page, with the + * exception of fUseStepFiltersButton according + * to the passed boolean + * @param enabled the new enablement status of the page's widgets + * @since 3.2 + */ + protected void setPageEnablement(boolean enabled) { + fPlatformStackFilterTable.setEnabled(enabled && fEnablePlatformButton.isSelected()); + fCustomStackFilterTable.setEnabled(enabled && fEnableCustomButton.isSelected()); + for (var categoryButton : categoryButtons) { + categoryButton.setEnabled(enabled); + } + fAppearanceList.getControl().setEnabled(enabled); + fFgColorSelector.getButton().setEnabled(enabled); + fBgColorSelector.getButton().setEnabled(enabled); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.preference.PreferencePage#performOk() + */ + @Override + public boolean performOk() { + IPreferenceStore store = getPreferenceStore(); + fPlatformStackFilterTable.performOk(store); + fCustomStackFilterTable.performOk(store); + fColorizeStackFrames.performOk(store); + for (var categoryButton : categoryButtons) { + categoryButton.performOk(store); + } + for (var color : colors) { + if (color.fgColor != null) { + stackFramePresentationProvider.setForegroundColor(color.category, color.fgColor.getRGB()); + } + if (color.bgColor != null) { + stackFramePresentationProvider.setBackgroundColor(color.category, color.bgColor.getRGB()); + } + } + return super.performOk(); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.preference.PreferencePage#performDefaults() + */ + @Override + protected void performDefaults() { + var store = getPreferenceStore(); + boolean enabled = fColorizeStackFrames.performDefault(store); + + for (var categoryButton : categoryButtons) { + categoryButton.performDefault(store); + } + for (var color : colors) { + color.setToDefault(); + } + fAppearanceList.update(colors.toArray(), null); + fAppearanceList.setSelection(new StructuredSelection(colors.get(0))); + + setPageEnablement(enabled); + + fPlatformStackFilterTable.performDefaults(); + fCustomStackFilterTable.performDefaults(); + super.performDefaults(); + } + +} diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/StackFramePresentationProvider.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/StackFramePresentationProvider.java new file mode 100644 index 0000000000..8408f57604 --- /dev/null +++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/StackFramePresentationProvider.java @@ -0,0 +1,290 @@ +/******************************************************************************* + * Copyright (c) 2021 Zsombor Gegesy. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Zsombor Gegesy - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.debug.ui; + +import java.util.EnumMap; +import java.util.Map; + +import org.eclipse.core.resources.IFile; +import org.eclipse.debug.core.DebugException; +import org.eclipse.jdt.core.IClassFile; +import org.eclipse.jdt.core.JavaCore; +import org.eclipse.jdt.debug.core.IJavaStackFrame; +import org.eclipse.jdt.debug.core.IJavaStackFrame.Category; +import org.eclipse.jdt.internal.ui.JavaPluginImages; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.resource.ColorRegistry; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.PropertyChangeEvent; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.ui.PlatformUI; + +/** + * Provides foreground and background colors for stack frames in a debug view. After usage, it needs to be closed, so it could unregister itself from + * preference storage. + * + */ +public class StackFramePresentationProvider implements IPropertyChangeListener, AutoCloseable { + + private final static EnumMap fgKeyMap = new EnumMap<>(Map.of( + Category.CUSTOM_FILTERED, IJDIPreferencesConstants.PREF_CUSTOM_FILTERED_STACK_FRAME_FG_COLOR, + Category.SYNTHETIC, IJDIPreferencesConstants.PREF_SYNT_STACK_FRAME_FG_COLOR, + Category.PLATFORM, IJDIPreferencesConstants.PREF_PLATFORM_STACK_FRAME_FG_COLOR, + Category.TEST, IJDIPreferencesConstants.PREF_TEST_STACK_FRAME_FG_COLOR, + Category.PRODUCTION, IJDIPreferencesConstants.PREF_PRODUCTION_STACK_FRAME_FG_COLOR, + Category.LIBRARY, IJDIPreferencesConstants.PREF_LIB_STACK_FRAME_FG_COLOR + )); + + private final static EnumMap bgKeyMap = new EnumMap<>(Map.of( + Category.CUSTOM_FILTERED, IJDIPreferencesConstants.PREF_CUSTOM_FILTERED_STACK_FRAME_BG_COLOR, // + Category.SYNTHETIC, IJDIPreferencesConstants.PREF_SYNT_STACK_FRAME_BG_COLOR, + Category.PLATFORM, IJDIPreferencesConstants.PREF_PLATFORM_STACK_FRAME_BG_COLOR, + Category.TEST, IJDIPreferencesConstants.PREF_TEST_STACK_FRAME_BG_COLOR, + Category.PRODUCTION, IJDIPreferencesConstants.PREF_PRODUCTION_STACK_FRAME_BG_COLOR, + Category.LIBRARY, IJDIPreferencesConstants.PREF_LIB_STACK_FRAME_BG_COLOR + )); + + private final static Map prefConst = Map.of( + IJDIPreferencesConstants.PREF_COLORIZE_CUSTOM_METHODS, Category.CUSTOM_FILTERED, + IJDIPreferencesConstants.PREF_COLORIZE_SYNTHETIC_METHODS, Category.SYNTHETIC, + IJDIPreferencesConstants.PREF_COLORIZE_PLATFORM_METHODS, Category.PLATFORM, + IJDIPreferencesConstants.PREF_COLORIZE_TEST_METHODS, Category.TEST, // + IJDIPreferencesConstants.PREF_COLORIZE_PRODUCTION_METHODS, Category.PRODUCTION, + IJDIPreferencesConstants.PREF_COLORIZE_LIBRARY_METHODS, Category.LIBRARY + ); + + class Filters { + private final String[] filters; + + Filters(String[] filters) { + this.filters = filters; + } + + public boolean match(String fqcName) { + for (String filter : filters) { + if (filter.endsWith("*")) { //$NON-NLS-1$ + if (fqcName.startsWith(filter.substring(0, filter.length() - 1))) { + return true; + } + } else { + if (filter.equals(fqcName)) { + return true; + } + } + } + return false; + } + } + + private Filters platform; + private Filters custom; + private final IPreferenceStore store; + private final EnumMap enabledCategories; + private boolean colorizeStackFrames; + + public StackFramePresentationProvider(IPreferenceStore store) { + this.store = store; + platform = getActivePlatformFilters(store); + custom = getActiveCustomFilters(store); + store.addPropertyChangeListener(this); + enabledCategories = new EnumMap<>(Category.class); + for (var kv : prefConst.entrySet()) { + boolean enabled = store.getBoolean(kv.getKey()); + enabledCategories.put(kv.getValue(), enabled); + } + colorizeStackFrames = store.getBoolean(IJDIPreferencesConstants.PREF_COLORIZE_STACK_FRAMES); + } + + private Filters getActivePlatformFilters(IPreferenceStore store) { + return new Filters(JavaStackFramePreferencePage.PLATFORM_STACK_FRAMES.getActiveList(store)); + } + + private Filters getActiveCustomFilters(IPreferenceStore store) { + return new Filters(JavaStackFramePreferencePage.CUSTOM_STACK_FRAMES.getActiveList(store)); + } + + public StackFramePresentationProvider() { + this(JDIDebugUIPlugin.getDefault().getPreferenceStore()); + } + + /** + * @return the foreground color of the stack frame's category, or null, if not defined. + */ + public Color getForeground(IJavaStackFrame frame) { + Category cat = getCategory(frame); + if (cat == null) { + return null; + } + return getForegroundColor(cat); + } + + /** + * @return the foreground color of the category, or null, if it's not defined. + */ + Color getForegroundColor(Category cat) { + var key = fgKeyMap.get(cat); + if (key != null) { + return getColorRegistry().get(key); + } + return null; + } + + private ColorRegistry getColorRegistry() { + return PlatformUI.getWorkbench().getThemeManager().getCurrentTheme().getColorRegistry(); + } + + void setForegroundColor(Category cat, RGB color) { + var key = fgKeyMap.get(cat); + if (key != null) { + getColorRegistry().put(key, color); + } + } + + void setBackgroundColor(Category cat, RGB color) { + var key = bgKeyMap.get(cat); + if (key != null) { + getColorRegistry().put(key, color); + } + } + + /** + * @return the category specific image for the stack frame, or null, if there is no one defined. + */ + public ImageDescriptor getStackFrameImage(IJavaStackFrame frame) { + var category = getCategory(frame); + if (category != null) { + switch (category) { + case LIBRARY: + return JavaPluginImages.DESC_OBJS_JAR; + case TEST: + return JavaPluginImages.DESC_OBJS_TEST_ATTRIB; + case PRODUCTION: + return JavaPluginImages.DESC_OBJS_CFILE; + default: + break; + } + } + return null; + } + + /** + * @return the background color assigned to the stack frame's category, or null, if there is no category matching. + */ + public Color getBackground(IJavaStackFrame frame) { + Category cat = getCategory(frame); + if (cat == null) { + return null; + } + return getBackgroundColor(cat); + } + + Color getBackgroundColor(Category cat) { + var key = bgKeyMap.get(cat); + if (key != null) { + return getColorRegistry().get(key); + } + return null; + } + + private IJavaStackFrame.Category getCategory(IJavaStackFrame frame) { + if (frame.getCategory() != null) { + return frame.getCategory(); + } + IJavaStackFrame.Category result = Category.UNKNOWN; + try { + result = categorize(frame); + } catch (DebugException e) { + JDIDebugUIPlugin.log(e); + } + frame.setCategory(result); + return result; + } + + private boolean isEnabled(Category category) { + return Boolean.TRUE.equals(enabledCategories.get(category)); + } + + /** + * Visible for testing! + */ + public IJavaStackFrame.Category categorize(IJavaStackFrame frame) throws DebugException { + var refTypeName = frame.getReferenceType().getName(); + if (isEnabled(Category.CUSTOM_FILTERED) && custom.match(refTypeName)) { + return Category.CUSTOM_FILTERED; + } + if (isEnabled(Category.SYNTHETIC) && frame.isSynthetic()) { + return Category.SYNTHETIC; + } + if (isEnabled(Category.PLATFORM) && platform.match(refTypeName)) { + return Category.PLATFORM; + } + + return categorizeSourceElement(frame); + } + + private Category categorizeSourceElement(IJavaStackFrame frame) { + var sourceLocator = frame.getLaunch().getSourceLocator(); + if (sourceLocator == null) { + return Category.UNKNOWN; + } + var source = sourceLocator.getSourceElement(frame); + if (source == null) { + return Category.UNKNOWN; + } + if (source instanceof IFile) { + if (isEnabled(Category.TEST)) { + var file = (IFile) source; + var jproj = JavaCore.create(file.getProject()); + var cp = jproj.findContainingClasspathEntry(file); + if (cp != null && cp.isTest()) { + return Category.TEST; + } + } + if (isEnabled(Category.PRODUCTION)) { + return Category.PRODUCTION; + } + } else if (source instanceof IClassFile && isEnabled(Category.LIBRARY)) { + return Category.LIBRARY; + } + return Category.UNKNOWN; + } + + @Override + public void close() { + store.removePropertyChangeListener(this); + } + + @Override + public void propertyChange(PropertyChangeEvent event) { + String prop = event.getProperty(); + if (IJDIPreferencesConstants.PREF_ACTIVE_PLATFORM_FRAME_FILTER_LIST.equals(prop)) { + platform = getActivePlatformFilters(store); + } else if (IJDIPreferencesConstants.PREF_ACTIVE_CUSTOM_FRAME_FILTER_LIST.equals(prop)) { + custom = getActiveCustomFilters(store); + } else if (IJDIPreferencesConstants.PREF_COLORIZE_STACK_FRAMES.equals(prop)) { + colorizeStackFrames = (Boolean) event.getNewValue(); + } else { + var category = prefConst.get(prop); + if (category != null) { + enabledCategories.put(category, (Boolean) event.getNewValue()); + } + } + } + + public boolean isColorizeStackFrames() { + return colorizeStackFrames; + } +} diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/ColorizeStackFramesAction.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/ColorizeStackFramesAction.java new file mode 100644 index 0000000000..792b0f520c --- /dev/null +++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/ColorizeStackFramesAction.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) 2022 Zsombor Gegesy and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Zsombor Gegesy - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.debug.ui.actions; + +import org.eclipse.jdt.internal.debug.ui.IJDIPreferencesConstants; + +/** + * Enable/disable the coloring of the stack frames in debug views. + * + */ +public class ColorizeStackFramesAction extends ToggleBooleanPreferenceAction { + + /* + * (non-Javadoc) + * + * @see org.eclipse.jdt.internal.debug.ui.actions.ViewFilterAction#getPreferenceKey() + */ + @Override + protected String getPreferenceKey() { + return IJDIPreferencesConstants.PREF_COLORIZE_STACK_FRAMES; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jdt.internal.debug.ui.actions.ViewFilterAction#getCompositeKey() + */ + @Override + protected String getCompositeKey() { + return getPreferenceKey(); + } + +} diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/variables/JavaVariableLabelProvider.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/variables/JavaVariableLabelProvider.java index ab6e930bbc..509f6a3a5b 100644 --- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/variables/JavaVariableLabelProvider.java +++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/variables/JavaVariableLabelProvider.java @@ -55,7 +55,7 @@ */ public class JavaVariableLabelProvider extends VariableLabelProvider implements IPreferenceChangeListener { - public static JDIModelPresentation fLabelProvider = new JDIModelPresentation(); + private final static JDIModelPresentation fLabelProvider = new JDIModelPresentation(); /** * Map of view id to qualified name setting */ diff --git a/org.eclipse.jdt.debug/META-INF/MANIFEST.MF b/org.eclipse.jdt.debug/META-INF/MANIFEST.MF index cd01783bc5..57b59e3b26 100644 --- a/org.eclipse.jdt.debug/META-INF/MANIFEST.MF +++ b/org.eclipse.jdt.debug/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.jdt.debug; singleton:=true -Bundle-Version: 3.19.300.qualifier +Bundle-Version: 3.20.0.qualifier Bundle-ClassPath: jdimodel.jar Bundle-Activator: org.eclipse.jdt.internal.debug.core.JDIDebugPlugin Bundle-Vendor: %providerName diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/debug/core/IJavaStackFrame.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/debug/core/IJavaStackFrame.java index a77f2e3ebf..a2fd46a568 100644 --- a/org.eclipse.jdt.debug/model/org/eclipse/jdt/debug/core/IJavaStackFrame.java +++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/debug/core/IJavaStackFrame.java @@ -35,6 +35,16 @@ public interface IJavaStackFrame extends IStackFrame, IJavaModifiers, IFilteredStep, IDropToFrame { + /** + * Categorization of the stack frame. + * + * @since 3.20 + * + */ + enum Category { + CUSTOM_FILTERED, SYNTHETIC, PLATFORM, TEST, PRODUCTION, LIBRARY, UNKNOWN + } + /** * Status code indicating a stack frame is invalid. A stack frame becomes * invalid when the thread containing the stack frame resumes. A stack frame @@ -533,4 +543,19 @@ public IJavaVariable findVariable(String variableName) * @since 3.3 */ public void forceReturn(IJavaValue value) throws DebugException; + + /** + * @since 3.20 + * @param category + * the new category of the stack frame. + */ + public void setCategory(Category category); + + /** + * + * @since 3.20 + * @return the category of the stack frame, null if it's not yet categorized. + */ + public Category getCategory(); + } diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIStackFrame.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIStackFrame.java index d16573f4ef..7d3f995134 100644 --- a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIStackFrame.java +++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIStackFrame.java @@ -139,6 +139,8 @@ public class JDIStackFrame extends JDIDebugElement implements IJavaStackFrame { */ private boolean fIsTop; + private Category fCategory; + @SuppressWarnings("restriction") private static final String SYNTHETIC_OUTER_LOCAL_PREFIX = new String(org.eclipse.jdt.internal.compiler.lookup.TypeConstants.SYNTHETIC_OUTER_LOCAL_PREFIX); @@ -1735,4 +1737,14 @@ public void forceReturn(IJavaValue value) throws DebugException { public void setIsTop(boolean isTop) { this.fIsTop = isTop; } + + @Override + public Category getCategory() { + return fCategory; + } + + @Override + public void setCategory(Category fCategory) { + this.fCategory = fCategory; + } } diff --git a/org.eclipse.jdt.debug/pom.xml b/org.eclipse.jdt.debug/pom.xml index 62cbed014d..7070b0a8da 100644 --- a/org.eclipse.jdt.debug/pom.xml +++ b/org.eclipse.jdt.debug/pom.xml @@ -18,6 +18,6 @@ org.eclipse.jdt org.eclipse.jdt.debug - 3.19.300-SNAPSHOT + 3.20.0-SNAPSHOT eclipse-plugin diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/JavaSourceLookupDirector.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/JavaSourceLookupDirector.java index 64c403a1a3..46425e690d 100644 --- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/JavaSourceLookupDirector.java +++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/JavaSourceLookupDirector.java @@ -32,7 +32,7 @@ */ public class JavaSourceLookupDirector extends AbstractSourceLookupDirector { - private static Set fFilteredTypes; + private static final Set fFilteredTypes; static { fFilteredTypes = new HashSet<>();