diff options
author | eutarass | 2008-05-22 18:55:32 +0000 |
---|---|---|
committer | eutarass | 2008-05-22 18:55:32 +0000 |
commit | 363e284ad7141758ab5c0183ca5af6285a86c34e (patch) | |
tree | 4a903dc7e9a04295e44931fde1298830d70c55be /plugins/org.eclipse.tm.tcf.debug.ui | |
parent | a14d5f1565f99ed710c8c65c24f2408519fe14eb (diff) | |
download | org.eclipse.tcf-363e284ad7141758ab5c0183ca5af6285a86c34e.tar.gz org.eclipse.tcf-363e284ad7141758ab5c0183ca5af6285a86c34e.tar.xz org.eclipse.tcf-363e284ad7141758ab5c0183ca5af6285a86c34e.zip |
1. TCF Debugger: implemented source code lookup and display.
2. TCF Debugger: implemented instruction pointer editor annotations.
3. TCF Agent: fixed Run Control and Diagnostics terminate commands.
4. Improved tests.
5. Various minor bug fixes.
Diffstat (limited to 'plugins/org.eclipse.tm.tcf.debug.ui')
14 files changed, 900 insertions, 208 deletions
diff --git a/plugins/org.eclipse.tm.tcf.debug.ui/META-INF/MANIFEST.MF b/plugins/org.eclipse.tm.tcf.debug.ui/META-INF/MANIFEST.MF index 6380463c6..db9d6e2a9 100644 --- a/plugins/org.eclipse.tm.tcf.debug.ui/META-INF/MANIFEST.MF +++ b/plugins/org.eclipse.tm.tcf.debug.ui/META-INF/MANIFEST.MF @@ -8,6 +8,9 @@ Bundle-Vendor: %providerName Bundle-Localization: plugin Require-Bundle: org.eclipse.ui, org.eclipse.core.runtime, + org.eclipse.ui.ide, + org.eclipse.ui.workbench.texteditor, + org.eclipse.text, org.eclipse.debug.core, org.eclipse.debug.ui, org.eclipse.tm.tcf.debug, diff --git a/plugins/org.eclipse.tm.tcf.debug.ui/plugin.properties b/plugins/org.eclipse.tm.tcf.debug.ui/plugin.properties index 0c99bf9d4..052dc5e6c 100644 --- a/plugins/org.eclipse.tm.tcf.debug.ui/plugin.properties +++ b/plugins/org.eclipse.tm.tcf.debug.ui/plugin.properties @@ -8,6 +8,9 @@ # Contributors: # Wind River Systems - initial implementation ############################################################################### -pluginName = TCF/Eclipse Debugger Integration UI -providerName = Eclipse.org +pluginName=TCF/Eclipse Debugger Integration UI +providerName=Eclipse.org + +debugCurrentInstructionPointer=Debug Current Instruction Pointer +debugCallStack=Debug Call Stack diff --git a/plugins/org.eclipse.tm.tcf.debug.ui/plugin.xml b/plugins/org.eclipse.tm.tcf.debug.ui/plugin.xml index 57d19127c..b593b7cfe 100644 --- a/plugins/org.eclipse.tm.tcf.debug.ui/plugin.xml +++ b/plugins/org.eclipse.tm.tcf.debug.ui/plugin.xml @@ -83,4 +83,48 @@ </perspectiveExtension> </extension> + <extension point="org.eclipse.ui.editors.annotationTypes"> + <type + name="org.eclipse.tm.tcf.debug.top_frame"> + </type> + <type + name="org.eclipse.tm.tcf.debug.stack_frame"> + </type> + </extension> + + <extension point="org.eclipse.ui.editors.markerAnnotationSpecification"> + <specification + annotationImageProvider="org.eclipse.tm.internal.tcf.debug.ui.model.TCFAnnotationImageProvider" + annotationType="org.eclipse.tm.tcf.debug.top_frame" + colorPreferenceKey="currentIPColor" + colorPreferenceValue="198,219,174" + highlightPreferenceKey="currentIPHighlight" + highlightPreferenceValue="true" + label="%debugCurrentInstructionPointer" + overviewRulerPreferenceKey="currentIPOverviewRuler" + overviewRulerPreferenceValue="true" + presentationLayer="6" + textPreferenceKey="currentIPIndication" + textPreferenceValue="false" + verticalRulerPreferenceKey="currentIPVerticalRuler" + verticalRulerPreferenceValue="true"> + </specification> + <specification + annotationImageProvider="org.eclipse.tm.internal.tcf.debug.ui.model.TCFAnnotationImageProvider" + annotationType="org.eclipse.tm.tcf.debug.stack_frame" + colorPreferenceKey="secondaryIPColor" + colorPreferenceValue="219,235,204" + highlightPreferenceKey="secondaryIPHighlight" + highlightPreferenceValue="true" + label="%debugCallStack" + overviewRulerPreferenceKey="secondaryIPOverviewRuler" + overviewRulerPreferenceValue="true" + presentationLayer="6" + textPreferenceKey="secondaryIPIndication" + textPreferenceValue="false" + verticalRulerPreferenceKey="secondaryIPVerticalRuler" + verticalRulerPreferenceValue="true"> + </specification> + </extension> + </plugin> diff --git a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/Activator.java b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/Activator.java index ff1ae2792..50697c1dd 100644 --- a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/Activator.java +++ b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/Activator.java @@ -10,6 +10,9 @@ *******************************************************************************/ package org.eclipse.tm.internal.tcf.debug.ui; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFAnnotationManager; import org.eclipse.tm.internal.tcf.debug.ui.model.TCFModelManager; import org.eclipse.ui.plugin.AbstractUIPlugin; import org.osgi.framework.Bundle; @@ -29,13 +32,20 @@ public class Activator extends AbstractUIPlugin { // The shared instance private static Activator plugin; private static TCFModelManager model_manager; + private static TCFAnnotationManager annotation_manager; private static final BundleListener bundle_listener = new BundleListener() { public void bundleChanged(BundleEvent event) { if (plugin != null && event.getBundle() == plugin.getBundle() && - plugin.getBundle().getState() != Bundle.ACTIVE && model_manager != null) { - model_manager.dispose(); - model_manager = null; + plugin.getBundle().getState() != Bundle.ACTIVE) { + if (model_manager != null) { + model_manager.dispose(); + model_manager = null; + } + if (annotation_manager != null) { + annotation_manager.dispose(); + annotation_manager = null; + } } } }; @@ -75,9 +85,9 @@ public class Activator extends AbstractUIPlugin { } /** - * Returns the shared TCFModel instance + * Returns the shared TCFModelManager instance * - * @return the shared TCFModel instance + * @return the shared TCFModelManager instance */ public static TCFModelManager getModelManager() { if (plugin != null && model_manager == null && plugin.getBundle().getState() == Bundle.ACTIVE) { @@ -85,4 +95,31 @@ public class Activator extends AbstractUIPlugin { } return model_manager; } + + /** + * Returns the shared TCFAnnotationManager instance + * + * @return the shared TCFAnnotationManager instance + */ + public static TCFAnnotationManager getAnnotationManager() { + if (plugin != null && annotation_manager == null && plugin.getBundle().getState() == Bundle.ACTIVE) { + annotation_manager = new TCFAnnotationManager(); + } + return annotation_manager; + } + + /** + * Send error message into Eclipse log. + * @param msg - error message test + * @param err - exception + */ + public static void log(String msg, Throwable err) { + if (plugin == null || plugin.getLog() == null) { + err.printStackTrace(); + } + else { + plugin.getLog().log(new Status(IStatus.ERROR, + plugin.getBundle().getSymbolicName(), IStatus.OK, msg, err)); + } + } } diff --git a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/adapters/TCFLaunchAdapterFactory.java b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/adapters/TCFLaunchAdapterFactory.java index c68394991..bf444c43b 100644 --- a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/adapters/TCFLaunchAdapterFactory.java +++ b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/adapters/TCFLaunchAdapterFactory.java @@ -28,7 +28,7 @@ public class TCFLaunchAdapterFactory implements IAdapterFactory { IElementContentProvider.class, IElementLabelProvider.class, IModelProxyFactory.class, - ITerminateHandler.class + ITerminateHandler.class, }; private final IElementLabelProvider launch_label_provider = new TCFLaunchLabelProvider(); diff --git a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/launch/TCFMainTab.java b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/launch/TCFMainTab.java index c6113dab6..ce3998550 100644 --- a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/launch/TCFMainTab.java +++ b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/launch/TCFMainTab.java @@ -757,6 +757,7 @@ public class TCFMainTab extends AbstractLaunchConfigurationTab { private int last_count = 0; private int last_total = 0; public void progress(final String label_text, final int count_done, final int count_total) { + assert test[0] != null; if ((label_text == null || last_text.equals(label_text)) && last_total == count_total && (count_done - last_count) / (float)count_total < 0.02f) return; @@ -773,7 +774,8 @@ public class TCFMainTab extends AbstractLaunchConfigurationTab { }); } public void done(final Collection<Throwable> errors) { - final boolean b = test[0] == null ? false : test[0].isCanceled(); + assert test[0] != null; + final boolean b = test[0].isCanceled(); test[0] = null; display.asyncExec(new Runnable() { public void run() { @@ -782,7 +784,7 @@ public class TCFMainTab extends AbstractLaunchConfigurationTab { new TestErrorsDialog(getControl().getShell(), getImage("icons/tcf.gif"), errors).open(); } - else if (loop && !b) { + else if (loop && !b && display != null) { runDiagnostics(item, true, test, shell, label, bar); } else { diff --git a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/launch/TCFSelfTest.java b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/launch/TCFSelfTest.java index 561e5924c..79efc47e1 100644 --- a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/launch/TCFSelfTest.java +++ b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/launch/TCFSelfTest.java @@ -81,7 +81,7 @@ class TCFSelfTest { private interface Test { } - TCFSelfTest(IPeer peer, TestListener listener) throws IOException { + TCFSelfTest(final IPeer peer, TestListener listener) throws IOException { this.listener = listener; pending_tests.add(new Runnable() { public void run() { @@ -90,6 +90,11 @@ class TCFSelfTest { }); pending_tests.add(new Runnable() { public void run() { + for (IChannel channel : channels) new TestAttachTerminate(channel); + } + }); + pending_tests.add(new Runnable() { + public void run() { int i = 0; for (IChannel channel : channels) new TestRCBP1(channel, i++); } @@ -102,16 +107,25 @@ class TCFSelfTest { pending_tests.add(new Runnable() { public void run() { for (int i = 0; i < channels.length; i++) { - switch (i % 3) { + switch (i % 4) { case 0: new TestEcho(channels[i]); break; - case 1: new TestRCBP1(channels[i], i); break; - case 2: new TestFileSystem(channels[i]); break; + case 1: new TestAttachTerminate(channels[i]); break; + case 2: new TestRCBP1(channels[i], i); break; + case 3: new TestFileSystem(channels[i]); break; } } } }); count_total = NUM_CHANNELS * pending_tests.size() * 2; channels = new IChannel[NUM_CHANNELS]; + Protocol.invokeLater(new Runnable() { + public void run() { + openChannels(peer); + } + }); + } + + private void openChannels(IPeer peer) { listener.progress("Openning communication channels...", count_done, count_total); for (int i = 0; i < channels.length; i++) { final IChannel channel = channels[i] = peer.openChannel(); @@ -239,6 +253,168 @@ class TCFSelfTest { } } + private class TestAttachTerminate implements Test, IRunControl.RunControlListener { + + private final IDiagnostics diag; + private final IRunControl rc; + + private final HashMap<String,IRunControl.RunControlContext> map = + new HashMap<String,IRunControl.RunControlContext>(); + private final HashSet<String> process_ids = new HashSet<String>(); + + private int cnt; + private int sync_cnt; + + TestAttachTerminate(IChannel channel) { + diag = channel.getRemoteService(IDiagnostics.class); + rc = channel.getRemoteService(IRunControl.class); + active_tests.put(this, channel); + listener.progress("Running Debugger Attach/Terminate Test...", ++count_done, count_total); + if (diag == null) { + done(this); + } + else { + if (rc != null) rc.addListener(this); + diag.getTestList(new IDiagnostics.DoneGetTestList() { + public void doneGetTestList(IToken token, Throwable error, String[] list) { + assert active_tests.get(TestAttachTerminate.this) != null; + if (error != null) { + exit(error); + } + else { + for (int i = 0; i < list.length; i++) { + if (list[i].equals("RCBP1")) { + startProcess(); + return; + } + } + } + exit(null); + } + }); + } + } + + private void startProcess() { + if (cancel || cnt == 4) { + if (!map.isEmpty()) { + Protocol.sync(new Runnable() { + public void run() { + sync_cnt++; + if (map.isEmpty()) { + exit(null); + } + else if (sync_cnt < 1000) { + Protocol.sync(this); + } + else { + exit(new Error("Missing 'contextRemoved' event for " + map.keySet())); + } + } + }); + } + else { + exit(null); + } + return; + } + cnt++; + diag.runTest("RCBP1", new IDiagnostics.DoneRunTest() { + public void doneRunTest(IToken token, Throwable error, String context_id) { + if (error != null) { + exit(error); + } + else { + assert context_id != null; + if (rc != null && map.get(context_id) == null) { + exit(new Error("Missing 'contextAdded' event for context " + context_id)); + } + process_ids.add(context_id); + diag.cancelTest(context_id, new IDiagnostics.DoneCancelTest() { + public void doneCancelTest(IToken token, Throwable error) { + if (error != null) { + exit(error); + } + else { + startProcess(); + } + } + }); + } + } + }); + } + + private void exit(Throwable x) { + if (active_tests.get(this) == null) return; + if (x != null) errors.add(x); + if (rc != null) rc.removeListener(this); + done(this); + } + + public void containerResumed(String[] context_ids) { + } + + public void containerSuspended(String main_context, String pc, + String reason, Map<String, Object> params, + String[] suspended_ids) { + for (String context : suspended_ids) { + assert context != null; + IRunControl.RunControlContext ctx = map.get(context); + if (ctx == null) exit(new Error("Invalid 'contextSuspended' event for " + context)); + if (process_ids.contains(context) || process_ids.contains(ctx.getParentID())) { + ctx.resume(IRunControl.RM_RESUME, 1, new IRunControl.DoneCommand() { + public void doneCommand(IToken token, Exception error) { + if (error != null) exit(error); + } + }); + } + } + } + + public void contextAdded(RunControlContext[] contexts) { + for (RunControlContext ctx : contexts) { + if (map.get(ctx.getID()) != null) exit(new Error("Invalid 'contextAdded' event")); + map.put(ctx.getID(), ctx); + } + } + + public void contextChanged(RunControlContext[] contexts) { + for (RunControlContext ctx : contexts) { + if (map.get(ctx.getID()) == null) exit(new Error("Invalid 'contextChanged' event")); + map.put(ctx.getID(), ctx); + } + } + + public void contextException(String context, String msg) { + exit(new Error("Unexpected 'contextException' event for " + context + ": " + msg)); + } + + public void contextRemoved(String[] context_ids) { + for (String id : context_ids) { + if (map.get(id) == null) exit(new Error("Invalid 'contextRemoved' event")); + map.remove(id); + } + } + + public void contextResumed(String context) { + } + + public void contextSuspended(String context, String pc, String reason, + Map<String, Object> params) { + assert context != null; + IRunControl.RunControlContext ctx = map.get(context); + if (ctx == null) exit(new Error("Invalid 'contextSuspended' event for " + context)); + if (process_ids.contains(context) || process_ids.contains(ctx.getParentID())) { + ctx.resume(IRunControl.RM_RESUME, 1, new IRunControl.DoneCommand() { + public void doneCommand(IToken token, Exception error) { + if (error != null) exit(error); + } + }); + } + } + } + private class TestRCBP1 implements Test, IDiagnostics.DoneGetTestList, IDiagnostics.DoneRunTest, IRunControl.DoneGetContext, IRunControl.DoneGetChildren, @@ -640,9 +816,8 @@ class TCFSelfTest { exit(new Exception("Invalid contextRemoved event")); return; } - threads.remove(id); running.remove(id); - if (threads.isEmpty()) { + if (threads.remove(id) != null && threads.isEmpty()) { if (bp_cnt != 30) { exit(new Exception("Test main thread breakpoint count = " + bp_cnt + ", expected 30")); } diff --git a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFAnnotationImageProvider.java b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFAnnotationImageProvider.java new file mode 100644 index 000000000..8d8acd0e4 --- /dev/null +++ b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFAnnotationImageProvider.java @@ -0,0 +1,21 @@ +package org.eclipse.tm.internal.tcf.debug.ui.model; + +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.text.source.Annotation; +import org.eclipse.swt.graphics.Image; +import org.eclipse.ui.texteditor.IAnnotationImageProvider; + +public class TCFAnnotationImageProvider implements IAnnotationImageProvider { + + public Image getManagedImage(Annotation annotation) { + return ((TCFAnnotationManager.TCFAnnotation)annotation).image; + } + + public String getImageDescriptorId(Annotation annotation) { + return null; + } + + public ImageDescriptor getImageDescriptor(String imageDescritporId) { + return null; + } +} diff --git a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFAnnotationManager.java b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFAnnotationManager.java new file mode 100644 index 000000000..a5e63d9d8 --- /dev/null +++ b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFAnnotationManager.java @@ -0,0 +1,381 @@ +/******************************************************************************* + * Copyright (c) 2008 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.model; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.debug.core.ILaunch; +import org.eclipse.debug.ui.DebugUITools; +import org.eclipse.debug.ui.IDebugUIConstants; +import org.eclipse.debug.ui.IDebugView; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.Position; +import org.eclipse.jface.text.source.Annotation; +import org.eclipse.jface.text.source.IAnnotationModel; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.tm.internal.tcf.debug.model.ITCFBreakpointListener; +import org.eclipse.tm.internal.tcf.debug.model.TCFBreakpoint; +import org.eclipse.tm.internal.tcf.debug.model.TCFBreakpointsStatus; +import org.eclipse.tm.internal.tcf.debug.model.TCFLaunch; +import org.eclipse.tm.tcf.protocol.IChannel; +import org.eclipse.tm.tcf.protocol.Protocol; +import org.eclipse.tm.tcf.services.IBreakpoints; +import org.eclipse.tm.tcf.services.IRunControl; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.ISelectionListener; +import org.eclipse.ui.IWindowListener; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.texteditor.IDocumentProvider; +import org.eclipse.ui.texteditor.ITextEditor; + +public class TCFAnnotationManager { + + class TCFAnnotation extends Annotation { + + final TCFModel model; + final String exe_id; + final ITextEditor editor; + final Image image; + + TCFAnnotation(TCFModel model, String exe_id, ITextEditor editor, Image image) { + this.model = model; + this.exe_id = exe_id; + this.editor = editor; + this.image = image; + } + + protected Image getImage() { + return image; + } + + void dispose() { + assert Thread.currentThread() == display.getThread(); + IDocumentProvider doc_provider = editor.getDocumentProvider(); + IEditorInput editor_input = editor.getEditorInput(); + if (doc_provider != null) { + IAnnotationModel ann_model = doc_provider.getAnnotationModel(editor_input); + if (ann_model != null) ann_model.removeAnnotation(this); + } + } + } + + private class WorkbenchWindowInfo { + final ArrayList<TCFAnnotation> annotations = new ArrayList<TCFAnnotation>(); + + void dispose() { + for (TCFAnnotation a : annotations) a.dispose(); + annotations.clear(); + } + } + + private TCFLaunch active_launch; + private final HashMap<IWorkbenchWindow,WorkbenchWindowInfo> windows = + new HashMap<IWorkbenchWindow,WorkbenchWindowInfo>(); + + private final TCFLaunch.Listener launch_listener = new TCFLaunch.Listener() { + + public void onConnected(final TCFLaunch launch) { + updateActiveLaunch(); + launch.getBreakpointsStatus().addListener(new ITCFBreakpointListener() { + + public void breakpointStatusChanged(String id) { + display.asyncExec(new Runnable() { + public void run() { + if (active_launch != launch) return; + refreshBreakpointView(); + } + }); + } + + public void breakpointRemoved(String id) { + display.asyncExec(new Runnable() { + public void run() { + if (active_launch != launch) return; + refreshBreakpointView(); + } + }); + } + }); + } + + public void onDisconnected(final TCFLaunch launch) { + assert Protocol.isDispatchThread(); + display.asyncExec(new Runnable() { + public void run() { + for (WorkbenchWindowInfo info : windows.values()) { + for (Iterator<TCFAnnotation> i = info.annotations.iterator(); i.hasNext();) { + TCFAnnotation a = i.next(); + if (a.model.getLaunch() == launch) { + i.remove(); + a.dispose(); + } + } + } + } + }); + updateActiveLaunch(); + } + }; + + private final ISelectionListener selection_listener = new ISelectionListener() { + + public void selectionChanged(IWorkbenchPart part, ISelection selection) { + updateActiveLaunch(); + } + }; + + private final IWindowListener window_listener = new IWindowListener() { + + public void windowActivated(IWorkbenchWindow window) { + updateActiveLaunch(); + } + + public void windowClosed(IWorkbenchWindow window) { + assert windows.get(window) != null; + window.getSelectionService().removeSelectionListener( + IDebugUIConstants.ID_DEBUG_VIEW, selection_listener); + windows.remove(window).dispose(); + updateActiveLaunch(); + } + + public void windowDeactivated(IWorkbenchWindow window) { + updateActiveLaunch(); + } + + public void windowOpened(IWorkbenchWindow window) { + if (windows.get(window) != null) return; + window.getSelectionService().addSelectionListener( + IDebugUIConstants.ID_DEBUG_VIEW, selection_listener); + windows.put(window, new WorkbenchWindowInfo()); + updateActiveLaunch(); + } + }; + + private final Display display = Display.getDefault(); + private int refresh_breakpoint_view_cnt = 0; + private int update_active_launch_cnt = 0; + private boolean disposed; + + public TCFAnnotationManager() { + assert Thread.currentThread() == display.getThread(); + Protocol.invokeLater(new Runnable() { + public void run() { + TCFLaunch.addListener(launch_listener); + } + }); + for (IWorkbenchWindow window : PlatformUI.getWorkbench().getWorkbenchWindows()) { + window_listener.windowOpened(window); + } + PlatformUI.getWorkbench().addWindowListener(window_listener); + IWorkbenchWindow w = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); + if (w != null) window_listener.windowActivated(w); + display.addListener(SWT.Dispose, new Listener() { + public void handleEvent(Event event) { + dispose(); + } + }); + } + + public void dispose() { + if (disposed) return; + assert Thread.currentThread() == display.getThread(); + disposed = true; + Protocol.invokeLater(new Runnable() { + public void run() { + TCFLaunch.removeListener(launch_listener); + } + }); + PlatformUI.getWorkbench().removeWindowListener(window_listener); + for (IWorkbenchWindow window : windows.keySet()) { + window.getSelectionService().removeSelectionListener( + IDebugUIConstants.ID_DEBUG_VIEW, selection_listener); + windows.get(window).dispose(); + } + windows.clear(); + } + + private void updateActiveLaunch() { + assert !disposed; + final int cnt = ++update_active_launch_cnt; + display.asyncExec(new Runnable() { + public void run() { + if (cnt != update_active_launch_cnt) return; + TCFLaunch launch = null; + IAdaptable adaptable = DebugUITools.getDebugContext(); + if (adaptable != null) { + ILaunch x = (ILaunch)adaptable.getAdapter(ILaunch.class); + if (x instanceof TCFLaunch) { + final TCFLaunch l = (TCFLaunch)x; + final boolean[] b = new boolean[1]; + Protocol.invokeAndWait(new Runnable() { + public void run() { + IChannel channel = l.getChannel(); + b[0] = channel != null && channel.getState() == IChannel.STATE_OPEN; + } + }); + if (b[0]) launch = l; + } + } + if (active_launch != launch) { + active_launch = launch; + refreshBreakpointView(); + } + } + }); + } + + private void refreshBreakpointView() { + assert !disposed; + final int cnt = ++refresh_breakpoint_view_cnt; + display.asyncExec(new Runnable() { + public void run() { + if (cnt != refresh_breakpoint_view_cnt) return; + for (IWorkbenchWindow window : PlatformUI.getWorkbench().getWorkbenchWindows()) { + IDebugView view = (IDebugView)window.getActivePage().findView(IDebugUIConstants.ID_BREAKPOINT_VIEW); + if (view != null) view.getViewer().refresh(); + } + } + }); + } + + String getBreakpointStatus(final TCFBreakpoint breakpoint) { + if (disposed) return ""; + assert Thread.currentThread() == display.getThread(); + final TCFLaunch launch = active_launch; + final String[] text = new String[1]; + text[0] = breakpoint.getText(); + if (launch != null) { + Protocol.invokeAndWait(new Runnable() { + public void run() { + TCFBreakpointsStatus bs = launch.getBreakpointsStatus(); + if (bs != null) { + Map<String,Object> map = bs.getStatus(breakpoint); + if (map != null) { + String status = null; + String error = (String)map.get(IBreakpoints.STATUS_ERROR); + Object planted = map.get(IBreakpoints.STATUS_PLANTED); + if (error != null) status = error; + else if (planted != null) status = "Planted"; + if (status != null) text[0] += " (" + status + ")"; + } + } + } + }); + } + return text[0]; + } + + void addStackFrameAnnotation(TCFModel model, String exe_id, boolean top_frame, + IWorkbenchPage page, ITextEditor editor, IRegion region) { + if (disposed) return; + assert Thread.currentThread() == display.getThread(); + TCFAnnotation annotation = null; + IAnnotationModel ann_model = null; + + if (editor != null && region != null) { + IDocumentProvider doc_provider = editor.getDocumentProvider(); + IEditorInput editor_input = editor.getEditorInput(); + ann_model = doc_provider.getAnnotationModel(editor_input); + if (ann_model != null) { + String type; + String text; + Image image; + if (top_frame) { + type = "org.eclipse.tm.tcf.debug.top_frame"; //$NON-NLS-1$ + text = "Debug Current Instruction Pointer"; //$NON-NLS-1$ + image = DebugUITools.getImage(IDebugUIConstants.IMG_OBJS_INSTRUCTION_POINTER_TOP); + } + else { + type = "org.eclipse.tm.tcf.debug.stack_frame"; //$NON-NLS-1$ + text = "Debug Stack Frame"; //$NON-NLS-1$ + image = DebugUITools.getImage(IDebugUIConstants.IMG_OBJS_INSTRUCTION_POINTER); + } + annotation = new TCFAnnotation(model, exe_id, editor, image); + annotation.setType(type); + annotation.setText(text); + } + } + + if (page != null) { + WorkbenchWindowInfo info = windows.get(page.getWorkbenchWindow()); + for (TCFAnnotation a : info.annotations) a.dispose(); + info.annotations.clear(); + if (annotation != null) { + ann_model.addAnnotation(annotation, new Position(region.getOffset(), region.getLength())); + info.annotations.add(annotation); + } + } + } + + void onContextResumed(final TCFModel model, String id) { + if (disposed) return; + assert Thread.currentThread() == display.getThread(); + for (WorkbenchWindowInfo info : windows.values()) { + for (Iterator<TCFAnnotation> i = info.annotations.iterator(); i.hasNext();) { + TCFAnnotation a = i.next(); + if (a.model == model && a.exe_id.equals(id)) { + i.remove(); + a.dispose(); + } + } + } + } + + void onContextSuspended(final TCFModel model, final String id) { + if (disposed) return; + assert Thread.currentThread() == display.getThread(); + final IAdaptable adaptable = DebugUITools.getDebugContext(); + if (adaptable instanceof TCFNode) { + Protocol.invokeLater(new Runnable() { + public void run() { + IRunControl.RunControlContext x = ((TCFNode)adaptable).getRunContext(); + if (x != null && id.equals(x.getID())) { + display.asyncExec(new Runnable() { + public void run() { + IWorkbenchWindow w = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); + if (w != null) { + IWorkbenchPage page = w.getActivePage(); + if (page != null) model.displaySource(adaptable, page, true); + } + } + }); + } + } + }); + } + } + + void onContextRemoved(final TCFModel model, String id) { + if (disposed) return; + assert Thread.currentThread() == display.getThread(); + for (WorkbenchWindowInfo info : windows.values()) { + for (Iterator<TCFAnnotation> i = info.annotations.iterator(); i.hasNext();) { + TCFAnnotation a = i.next(); + if (a.model == model && a.exe_id.equals(id)) { + i.remove(); + a.dispose(); + } + } + } + } +} diff --git a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFModel.java b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFModel.java index f48adea2b..402c10a38 100644 --- a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFModel.java +++ b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFModel.java @@ -15,6 +15,7 @@ import java.util.HashMap; import java.util.Map; import java.util.TreeSet; +import org.eclipse.core.runtime.CoreException; import org.eclipse.debug.core.commands.IDisconnectHandler; import org.eclipse.debug.core.commands.IResumeHandler; import org.eclipse.debug.core.commands.IStepIntoHandler; @@ -22,6 +23,8 @@ import org.eclipse.debug.core.commands.IStepOverHandler; import org.eclipse.debug.core.commands.IStepReturnHandler; import org.eclipse.debug.core.commands.ISuspendHandler; import org.eclipse.debug.core.commands.ITerminateHandler; +import org.eclipse.debug.core.model.ISourceLocator; +import org.eclipse.debug.core.sourcelookup.ISourceLookupDirector; import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenCountUpdate; import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate; import org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentation; @@ -35,8 +38,16 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxy; import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxyFactory; import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext; import org.eclipse.debug.ui.IDebugUIConstants; +import org.eclipse.debug.ui.ISourcePresentation; +import org.eclipse.debug.ui.sourcelookup.CommonSourceNotFoundEditorInput; +import org.eclipse.debug.ui.sourcelookup.ISourceDisplay; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IRegion; +import org.eclipse.swt.custom.BusyIndicator; import org.eclipse.swt.widgets.Display; import org.eclipse.tm.internal.tcf.debug.model.TCFLaunch; +import org.eclipse.tm.internal.tcf.debug.ui.Activator; import org.eclipse.tm.internal.tcf.debug.ui.commands.DisconnectCommand; import org.eclipse.tm.internal.tcf.debug.ui.commands.ResumeCommand; import org.eclipse.tm.internal.tcf.debug.ui.commands.StepIntoCommand; @@ -44,14 +55,22 @@ import org.eclipse.tm.internal.tcf.debug.ui.commands.StepOverCommand; import org.eclipse.tm.internal.tcf.debug.ui.commands.StepReturnCommand; import org.eclipse.tm.internal.tcf.debug.ui.commands.SuspendCommand; import org.eclipse.tm.internal.tcf.debug.ui.commands.TerminateCommand; +import org.eclipse.tm.tcf.protocol.IChannel; import org.eclipse.tm.tcf.protocol.Protocol; import org.eclipse.tm.tcf.services.IMemory; import org.eclipse.tm.tcf.services.IRegisters; import org.eclipse.tm.tcf.services.IRunControl; +import org.eclipse.tm.tcf.util.TCFDataCache; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.texteditor.IDocumentProvider; +import org.eclipse.ui.texteditor.ITextEditor; public class TCFModel implements IElementContentProvider, IElementLabelProvider, - IModelProxyFactory, IColumnPresentationFactory { + IModelProxyFactory, IColumnPresentationFactory, ISourceDisplay { private final Display display; private final TCFLaunch launch; @@ -66,6 +85,8 @@ public class TCFModel implements IElementContentProvider, IElementLabelProvider, private boolean disposed; private int future_task_cnt; + + private int display_source_cnt; private static class FutureTask implements Comparable<FutureTask>{ final int id; @@ -145,9 +166,9 @@ public class TCFModel implements IElementContentProvider, IElementLabelProvider, fireModelChanged(); } - public void contextRemoved(String[] context_ids) { - for (int i = 0; i < context_ids.length; i++) { - TCFNode node = getNode(context_ids[i]); + public void contextRemoved(final String[] context_ids) { + for (String id : context_ids) { + TCFNode node = getNode(id); if (node instanceof TCFNodeExecContext) { ((TCFNodeExecContext)node).onContextRemoved(); } @@ -225,30 +246,47 @@ public class TCFModel implements IElementContentProvider, IElementLabelProvider, fireModelChanged(); } - public void contextRemoved(String[] context_ids) { - for (int i = 0; i < context_ids.length; i++) { - TCFNode node = getNode(context_ids[i]); + public void contextRemoved(final String[] context_ids) { + for (String id : context_ids) { + TCFNode node = getNode(id); if (node instanceof TCFNodeExecContext) { ((TCFNodeExecContext)node).onContextRemoved(); } } fireModelChanged(); + display.asyncExec(new Runnable() { + public void run() { + for (String id : context_ids) { + Activator.getAnnotationManager().onContextRemoved(TCFModel.this, id); + } + } + }); } - public void contextResumed(String context) { + public void contextResumed(final String context) { TCFNode node = getNode(context); if (node instanceof TCFNodeExecContext) { ((TCFNodeExecContext)node).onContextResumed(); } fireModelChanged(); + display.asyncExec(new Runnable() { + public void run() { + Activator.getAnnotationManager().onContextResumed(TCFModel.this, context); + } + }); } - public void contextSuspended(String context, String pc, String reason, Map<String,Object> params) { + public void contextSuspended(final String context, String pc, String reason, Map<String,Object> params) { TCFNode node = getNode(context); if (node instanceof TCFNodeExecContext) { ((TCFNodeExecContext)node).onContextSuspended(pc, reason, params); } fireModelChanged(); + display.asyncExec(new Runnable() { + public void run() { + Activator.getAnnotationManager().onContextSuspended(TCFModel.this, context); + } + }); } }; @@ -478,4 +516,135 @@ public class TCFModel implements IElementContentProvider, IElementLabelProvider, } return null; } + + /** + * Reveal source code associated with given model element. + */ + public void displaySource(Object element, final IWorkbenchPage page, boolean forceSourceLookup) { + if (element instanceof TCFNodeStackFrame) { + final TCFNodeStackFrame stack_frame = (TCFNodeStackFrame)element; + final int cnt = ++display_source_cnt; + Protocol.invokeLater(new Runnable() { + public void run() { + if (cnt != display_source_cnt) return; + IChannel channel = getLaunch().getChannel(); + if (!disposed && channel.getState() == IChannel.STATE_OPEN && !stack_frame.disposed) { + TCFDataCache<TCFSourceRef> line_info = stack_frame.getLineInfo(); + if (!line_info.validate()) { + line_info.wait(this); + } + else { + String editor_id = null; + IEditorInput editor_input = null; + Throwable error = line_info.getError(); + TCFSourceRef src_ref = line_info.getData(); + int line = 0; + if (error == null && src_ref != null) error = src_ref.error; + if (error != null) Activator.log("Error retrieving source mapping for a stack frame", error); + if (src_ref != null && src_ref.area != null) { + ISourceLocator locator = getLaunch().getSourceLocator(); + Object source_element = null; + if (locator instanceof ISourceLookupDirector) { + source_element = ((ISourceLookupDirector)locator).getSourceElement(src_ref.area); + } + if (source_element == null) { + editor_input = new CommonSourceNotFoundEditorInput(src_ref.area); + editor_id = IDebugUIConstants.ID_COMMON_SOURCE_NOT_FOUND_EDITOR; + } + else { + ISourcePresentation presentation = TCFModelPresentation.getDefault(); + if (presentation != null) { + editor_input = presentation.getEditorInput(source_element); + } + if (editor_input != null) { + editor_id = presentation.getEditorId(editor_input, source_element); + } + line = src_ref.area.start_line; + } + } + displaySource(cnt, editor_id, editor_input, page, stack_frame.getRunContext().getID(), + stack_frame.getFrameNo() == 0, line); + } + } + } + }); + } + } + + private void displaySource(final int cnt, + final String id, final IEditorInput input, final IWorkbenchPage page, + final String exe_id, final boolean top_frame, final int line) { + display.asyncExec(new Runnable() { + public void run() { + if (cnt != display_source_cnt) return; + ITextEditor text_editor = null; + IRegion region = null; + if (input != null && id != null && page != null) { + IEditorPart editor = openEditor(input, id, page); + if (editor instanceof ITextEditor) { + text_editor = (ITextEditor)editor; + } + else { + text_editor = (ITextEditor)editor.getAdapter(ITextEditor.class); + } + } + if (text_editor != null) { + region = getLineInformation(text_editor, line); + if (region != null) text_editor.selectAndReveal(region.getOffset(), 0); + } + Activator.getAnnotationManager().addStackFrameAnnotation(TCFModel.this, + exe_id, top_frame, page, text_editor, region); + } + }); + } + + /** + * Open an editor for given editor input. + * @param input - IEditorInput representing a source file to be shown in the editor + * @param id - editor type ID + * @param page - workbench page that will contain the editor + * @return - IEditorPart if the editor was opened successfully, or null otherwise. + */ + private IEditorPart openEditor(final IEditorInput input, final String id, final IWorkbenchPage page) { + final IEditorPart[] editor = new IEditorPart[]{ null }; + Runnable r = new Runnable() { + public void run() { + if (!page.getWorkbenchWindow().getWorkbench().isClosing()) { + try { + editor[0] = page.openEditor(input, id, false, IWorkbenchPage.MATCH_ID|IWorkbenchPage.MATCH_INPUT); + } + catch (PartInitException e) { + Activator.log("Cannot open editor", e); + } + } + } + }; + BusyIndicator.showWhile(display, r); + return editor[0]; + } + + /** + * Returns the line information for the given line in the given editor + */ + private IRegion getLineInformation(ITextEditor editor, int lineNumber) { + IDocumentProvider provider = editor.getDocumentProvider(); + IEditorInput input = editor.getEditorInput(); + try { + provider.connect(input); + } + catch (CoreException e) { + return null; + } + try { + IDocument document = provider.getDocument(input); + if (document != null) + return document.getLineInformation(lineNumber); + } + catch (BadLocationException e) { + } + finally { + provider.disconnect(input); + } + return null; + } } diff --git a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFModelManager.java b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFModelManager.java index c337ff1cf..7a4960b90 100644 --- a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFModelManager.java +++ b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFModelManager.java @@ -99,6 +99,7 @@ public class TCFModelManager { } public TCFModel getModel(TCFLaunch launch) { + assert Protocol.isDispatchThread(); TCFModel model = models.get(launch); if (model == null) { model = new TCFModel(display, launch); diff --git a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFModelPresentation.java b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFModelPresentation.java index 5608f3b6f..b513350e3 100644 --- a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFModelPresentation.java +++ b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFModelPresentation.java @@ -12,164 +12,32 @@ package org.eclipse.tm.internal.tcf.debug.ui.model; import java.util.Collection; import java.util.HashSet; -import java.util.Map; -import org.eclipse.core.runtime.IAdaptable; -import org.eclipse.debug.core.ILaunch; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IMarker; +import org.eclipse.debug.core.model.ILineBreakpoint; import org.eclipse.debug.core.model.IValue; -import org.eclipse.debug.ui.DebugUITools; import org.eclipse.debug.ui.IDebugModelPresentation; -import org.eclipse.debug.ui.IDebugUIConstants; -import org.eclipse.debug.ui.IDebugView; import org.eclipse.debug.ui.IValueDetailListener; import org.eclipse.jface.viewers.ILabelProviderListener; -import org.eclipse.jface.viewers.ISelection; import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.widgets.Display; -import org.eclipse.tm.internal.tcf.debug.model.ITCFBreakpointListener; import org.eclipse.tm.internal.tcf.debug.model.TCFBreakpoint; -import org.eclipse.tm.internal.tcf.debug.model.TCFBreakpointsStatus; -import org.eclipse.tm.internal.tcf.debug.model.TCFLaunch; -import org.eclipse.tm.tcf.protocol.IChannel; -import org.eclipse.tm.tcf.protocol.Protocol; -import org.eclipse.tm.tcf.services.IBreakpoints; +import org.eclipse.tm.internal.tcf.debug.ui.Activator; +import org.eclipse.ui.IEditorDescriptor; import org.eclipse.ui.IEditorInput; -import org.eclipse.ui.ISelectionListener; -import org.eclipse.ui.IWindowListener; -import org.eclipse.ui.IWorkbenchPart; -import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.IEditorRegistry; import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.part.FileEditorInput; public class TCFModelPresentation implements IDebugModelPresentation { private final Collection<ILabelProviderListener> listeners = new HashSet<ILabelProviderListener>(); - private IWorkbenchWindow active_window; - private TCFLaunch launch_selection; + private static final TCFModelPresentation default_instance = new TCFModelPresentation(); - private final TCFLaunch.Listener launch_listener = new TCFLaunch.Listener() { - - public void onConnected(TCFLaunch launch) { - updateLaunchSelection(); - } - - public void onDisconnected(TCFLaunch launch) { - updateLaunchSelection(); - } - }; - - private final ISelectionListener selection_listener = new ISelectionListener() { - - public void selectionChanged(IWorkbenchPart part, ISelection selection) { - updateLaunchSelection(); - } - }; - - private final IWindowListener window_listener = new IWindowListener() { - - public void windowActivated(IWorkbenchWindow window) { - if (active_window != null) { - active_window.getSelectionService().removeSelectionListener( - IDebugUIConstants.ID_DEBUG_VIEW, selection_listener); - active_window = null; - } - window.getSelectionService().addSelectionListener( - IDebugUIConstants.ID_DEBUG_VIEW, selection_listener); - active_window = window; - updateLaunchSelection(); - } - - public void windowClosed(IWorkbenchWindow window) { - if (window == active_window) { - active_window.getSelectionService().removeSelectionListener( - IDebugUIConstants.ID_DEBUG_VIEW, selection_listener); - active_window = null; - } - } - - public void windowDeactivated(IWorkbenchWindow window) { - } - - public void windowOpened(IWorkbenchWindow window) { - } - }; - - private final ITCFBreakpointListener breakpoint_status_listener = new ITCFBreakpointListener() { - - public void breakpointStatusChanged(String id) { - refreshBreakpointView(); - } - - public void breakpointRemoved(String id) { - refreshBreakpointView(); - } - }; - - public TCFModelPresentation() { - Protocol.invokeAndWait(new Runnable() { - public void run() { - TCFLaunch.addListener(launch_listener); - } - }); - PlatformUI.getWorkbench().addWindowListener(window_listener); - IWorkbenchWindow w = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); - if (w != null) window_listener.windowActivated(w); - } - - private void updateLaunchSelection() { - Display.getDefault().asyncExec(new Runnable() { - public void run() { - TCFLaunch launch = null; - IAdaptable adaptable = DebugUITools.getDebugContext(); - if (adaptable != null) { - ILaunch x = (ILaunch)adaptable.getAdapter(ILaunch.class); - if (x instanceof TCFLaunch) { - final TCFLaunch l = (TCFLaunch)x; - final boolean[] b = new boolean[1]; - Protocol.invokeAndWait(new Runnable() { - public void run() { - IChannel channel = l.getChannel(); - b[0] = channel != null && channel.getState() == IChannel.STATE_OPEN; - } - }); - if (b[0]) launch = l; - } - } - if (launch_selection != launch) { - setBreakpointStatusListener(launch_selection, launch); - launch_selection = launch; - refreshBreakpointView(); - } - } - }); - } - - private void refreshBreakpointView() { - Display.getDefault().asyncExec(new Runnable() { - public void run() { - if (active_window != null) { - final IDebugView view = (IDebugView)active_window.getActivePage().findView( - IDebugUIConstants.ID_BREAKPOINT_VIEW); - if (view != null) { - view.getViewer().refresh(); - } - } - } - }); - } - - private void setBreakpointStatusListener(final TCFLaunch prev, final TCFLaunch next) { - Protocol.invokeAndWait(new Runnable() { - public void run() { - if (prev != null && prev.getBreakpointsStatus() != null) { - prev.getBreakpointsStatus().removeListener(breakpoint_status_listener); - } - if (next != null && next.getBreakpointsStatus() != null) { - next.getBreakpointsStatus().addListener(breakpoint_status_listener); - } - } - }); + public static TCFModelPresentation getDefault() { + return default_instance; } public void addListener(ILabelProviderListener listener) { @@ -181,21 +49,6 @@ public class TCFModelPresentation implements IDebugModelPresentation { } public void dispose() { - if (launch_selection != null) { - setBreakpointStatusListener(launch_selection, null); - launch_selection = null; - } - if (active_window != null) { - active_window.getSelectionService().removeSelectionListener( - IDebugUIConstants.ID_DEBUG_VIEW, selection_listener); - active_window = null; - } - PlatformUI.getWorkbench().removeWindowListener(window_listener); - Protocol.invokeAndWait(new Runnable() { - public void run() { - TCFLaunch.removeListener(launch_listener); - } - }); } public void computeDetail(IValue value, IValueDetailListener listener) { @@ -206,32 +59,14 @@ public class TCFModelPresentation implements IDebugModelPresentation { } public String getText(Object element) { + String text = null; if (element instanceof TCFBreakpoint) { - final TCFBreakpoint breakpoint = (TCFBreakpoint)element; - final TCFLaunch launch = launch_selection; - final String[] text = new String[1]; - text[0] = breakpoint.getText(); - if (launch != null) { - Protocol.invokeAndWait(new Runnable() { - public void run() { - TCFBreakpointsStatus bs = launch.getBreakpointsStatus(); - if (bs != null) { - Map<String,Object> map = bs.getStatus(breakpoint); - if (map != null) { - String status = null; - String error = (String)map.get(IBreakpoints.STATUS_ERROR); - Object planted = map.get(IBreakpoints.STATUS_PLANTED); - if (error != null) status = error; - else if (planted != null) status = "Planted"; - if (status != null) text[0] += " (" + status + ")"; - } - } - } - }); - } - return text[0]; + TCFBreakpoint breakpoint = (TCFBreakpoint)element; + text = breakpoint.getText(); + String status = Activator.getAnnotationManager().getBreakpointStatus(breakpoint); + if (status != null) text += " (" + status + ")"; } - return null; + return text; } public void setAttribute(String attribute, Object value) { @@ -242,10 +77,25 @@ public class TCFModelPresentation implements IDebugModelPresentation { } public String getEditorId(IEditorInput input, Object element) { - return null; + String id = null; + if (input != null) { + IEditorRegistry registry = PlatformUI.getWorkbench().getEditorRegistry(); + IEditorDescriptor descriptor = registry.getDefaultEditor(input.getName()); + if (descriptor != null) id = descriptor.getId(); + } + return id; } public IEditorInput getEditorInput(Object element) { + if (element instanceof ILineBreakpoint) { + element = ((ILineBreakpoint)element).getMarker(); + } + if (element instanceof IMarker) { + element = ((IMarker)element).getResource(); + } + if (element instanceof IFile) { + return new FileEditorInput((IFile)element); + } return null; } } diff --git a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFNode.java b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFNode.java index 3895affa7..10afd3ee6 100644 --- a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFNode.java +++ b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFNode.java @@ -26,6 +26,7 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta; import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxyFactory; import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext; import org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta; +import org.eclipse.debug.ui.sourcelookup.ISourceDisplay; import org.eclipse.tm.internal.tcf.debug.ui.ImageCache; import org.eclipse.tm.tcf.protocol.IChannel; import org.eclipse.tm.tcf.protocol.Protocol; @@ -104,9 +105,9 @@ public abstract class TCFNode extends PlatformObject implements Comparable<TCFNo if (adapter == IElementLabelProvider.class) return model; if (adapter == IElementContentProvider.class) return model; if (adapter == IColumnPresentationFactory.class) return model; + if (adapter == ISourceDisplay.class) return model; Object o = model.getCommand(adapter); if (o != null) return o; - //System.err.println(adapter.getName()); return super.getAdapter(adapter); } diff --git a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFNodeStackFrame.java b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFNodeStackFrame.java index 84efbc5d6..017735dec 100644 --- a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFNodeStackFrame.java +++ b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFNodeStackFrame.java @@ -126,6 +126,7 @@ public class TCFNodeStackFrame extends TCFNode { } int getFrameNo() { + assert Protocol.isDispatchThread(); return frame_no; } @@ -133,6 +134,10 @@ public class TCFNodeStackFrame extends TCFNode { assert this.frame_no != 0 && frame_no != 0; this.frame_no = frame_no; } + + TCFDataCache<TCFSourceRef> getLineInfo() { + return line_info; + } @Override void dispose() { |