diff options
author | eutarass | 2011-06-30 20:54:27 +0000 |
---|---|---|
committer | eutarass | 2011-06-30 20:54:27 +0000 |
commit | 5b11c386f9cfa5dccf566cfc2229a29da07ba4b9 (patch) | |
tree | 1f46b2bcbdc9b211aa5e8fb8fc57d71eec1d8cb9 /plugins | |
parent | c1034860084e94449896dc6097edcc64e1438fc3 (diff) | |
download | org.eclipse.tcf-5b11c386f9cfa5dccf566cfc2229a29da07ba4b9.tar.gz org.eclipse.tcf-5b11c386f9cfa5dccf566cfc2229a29da07ba4b9.tar.xz org.eclipse.tcf-5b11c386f9cfa5dccf566cfc2229a29da07ba4b9.zip |
TCF Debugger: implemented editor markers that show breakpoints status for current selection in the Debug view.
Diffstat (limited to 'plugins')
9 files changed, 380 insertions, 184 deletions
diff --git a/plugins/org.eclipse.tm.tcf.debug.ui/plugin.properties b/plugins/org.eclipse.tm.tcf.debug.ui/plugin.properties index 5e5f22e79..a246bf272 100644 --- a/plugins/org.eclipse.tm.tcf.debug.ui/plugin.properties +++ b/plugins/org.eclipse.tm.tcf.debug.ui/plugin.properties @@ -15,6 +15,7 @@ preferencePage.name = Target Communication debugCurrentInstructionPointer = Debug Current Instruction Pointer debugCallStack = Debug Call Stack +debugBreakpointInstance = Breakpoint DebuggerActionSet.label = TCF Debugger diff --git a/plugins/org.eclipse.tm.tcf.debug.ui/plugin.xml b/plugins/org.eclipse.tm.tcf.debug.ui/plugin.xml index 08c01f973..571483967 100644 --- a/plugins/org.eclipse.tm.tcf.debug.ui/plugin.xml +++ b/plugins/org.eclipse.tm.tcf.debug.ui/plugin.xml @@ -146,6 +146,9 @@ <type name="org.eclipse.tm.tcf.debug.stack_frame"> </type> + <type + name="org.eclipse.tm.tcf.debug.breakpoint_instance"> + </type> </extension> <extension point="org.eclipse.ui.editors.markerAnnotationSpecification"> @@ -181,6 +184,22 @@ verticalRulerPreferenceKey="secondaryIPVerticalRuler" verticalRulerPreferenceValue="true"> </specification> + <specification + annotationImageProvider="org.eclipse.tm.internal.tcf.debug.ui.model.TCFAnnotationImageProvider" + annotationType="org.eclipse.tm.tcf.debug.breakpoint_instance" + colorPreferenceKey="breakpointInstanceColor" + colorPreferenceValue="100,200,204" + highlightPreferenceKey="breakpointInstanceHighlight" + highlightPreferenceValue="false" + label="%debugBreakpointInstance" + overviewRulerPreferenceKey="breakpointInstanceRuler" + overviewRulerPreferenceValue="true" + presentationLayer="5" + textPreferenceKey="breakpointInstanceIndication" + textPreferenceValue="false" + verticalRulerPreferenceKey="breakpointInstanceVerticalRuler" + verticalRulerPreferenceValue="true"> + </specification> </extension> <extension point="org.eclipse.debug.ui.detailPaneFactories"> 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 9f3becfcf..ae58135e7 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 @@ -40,9 +40,6 @@ public class Activator extends AbstractUIPlugin { if (model_manager == null) { model_manager = new TCFModelManager(); } - if (annotation_manager == null) { - annotation_manager = new TCFAnnotationManager(); - } } }); } diff --git a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/ImageCache.java b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/ImageCache.java index 9ea786aee..42ac06899 100644 --- a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/ImageCache.java +++ b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/ImageCache.java @@ -63,7 +63,8 @@ public class ImageCache { IMG_BREAKPOINT_DISABLED = "icons/full/obj16/brkpd_obj.gif", IMG_BREAKPOINT_INSTALLED = "icons/ovr16/installed_ovr.gif", IMG_BREAKPOINT_CONDITIONAL = "icons/ovr16/conditional_ovr.gif", - IMG_BREAKPOINT_WARNING = "icons/ovr16/warning_ovr.gif"; + IMG_BREAKPOINT_WARNING = "icons/ovr16/warning_ovr.gif", + IMG_BREAKPOINT_ERROR = "icons/ovr16/error_ovr.gif"; private static final Map<String,ImageDescriptor> desc_cache = new HashMap<String,ImageDescriptor>(); private static final Map<ImageDescriptor,Image> image_cache = new HashMap<ImageDescriptor,Image>(); 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 index 1bd5d35d6..3e81bb7dd 100644 --- 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008, 2010 Wind River Systems, Inc. and others. + * Copyright (c) 2008, 2011 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 @@ -10,36 +10,56 @@ *******************************************************************************/ package org.eclipse.tm.internal.tcf.debug.ui.model; +import java.math.BigInteger; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; import java.util.Map; -import java.util.Set; +import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.debug.core.ILaunch; +import org.eclipse.debug.core.model.ISourceLocator; +import org.eclipse.debug.core.sourcelookup.ISourceLookupDirector; import org.eclipse.debug.ui.DebugUITools; import org.eclipse.debug.ui.IDebugUIConstants; -import org.eclipse.debug.ui.IDebugView; +import org.eclipse.debug.ui.ISourcePresentation; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; 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.jface.viewers.IStructuredSelection; import org.eclipse.swt.graphics.Device; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Display; +import org.eclipse.tm.internal.tcf.debug.launch.TCFSourceLookupDirector; +import org.eclipse.tm.internal.tcf.debug.launch.TCFSourceLookupParticipant; 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.internal.tcf.debug.model.TCFSourceRef; +import org.eclipse.tm.internal.tcf.debug.ui.Activator; +import org.eclipse.tm.internal.tcf.debug.ui.ImageCache; 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.ILineNumbers; +import org.eclipse.tm.tcf.services.IRunControl; +import org.eclipse.tm.tcf.util.TCFDataCache; +import org.eclipse.tm.tcf.util.TCFTask; import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IEditorReference; 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; @@ -50,18 +70,19 @@ public class TCFAnnotationManager { class TCFAnnotation extends Annotation { - final TCFModel model; - final String exe_id; - final ITextEditor editor; + final ILineNumbers.CodeArea area; final Image image; - final Position position; + final String text; + final int hash_code; - TCFAnnotation(TCFModel model, String exe_id, ITextEditor editor, Image image, Position position) { - this.model = model; - this.exe_id = exe_id; - this.editor = editor; + IAnnotationModel model; + + TCFAnnotation(ILineNumbers.CodeArea area, Image image, String text) { + this.area = area; this.image = image; - this.position = position; + this.text = text; + hash_code = area.hashCode() + image.hashCode() + text.hashCode(); + setText(text); } protected Image getImage() { @@ -70,17 +91,30 @@ public class TCFAnnotationManager { 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); + if (model != null) { + model.removeAnnotation(this); + model = null; } } + + @Override + public boolean equals(Object o) { + if (!(o instanceof TCFAnnotation)) return false; + TCFAnnotation a = (TCFAnnotation)o; + if (!area.equals(a.area)) return false; + if (!image.equals(a.image)) return false; + if (!text.equals(a.text)) return false; + return true; + } + + @Override + public int hashCode() { + return hash_code; + } } private class WorkbenchWindowInfo { - final ArrayList<TCFAnnotation> annotations = new ArrayList<TCFAnnotation>(); + final LinkedList<TCFAnnotation> annotations = new LinkedList<TCFAnnotation>(); void dispose() { for (TCFAnnotation a : annotations) a.dispose(); @@ -92,6 +126,9 @@ public class TCFAnnotationManager { private final HashMap<IWorkbenchWindow,WorkbenchWindowInfo> windows = new HashMap<IWorkbenchWindow,WorkbenchWindowInfo>(); + private final HashSet<IWorkbenchWindow> dirty_windows = new HashSet<IWorkbenchWindow>(); + private final HashSet<TCFLaunch> dirty_launches = new HashSet<TCFLaunch>(); + private final TCFLaunch.LaunchListener launch_listener = new TCFLaunch.LaunchListener() { public void onCreated(TCFLaunch launch) { @@ -99,26 +136,17 @@ public class TCFAnnotationManager { public void onConnected(final TCFLaunch launch) { updateActiveLaunch(); + updateAnnotations(null, launch); TCFBreakpointsStatus bps = launch.getBreakpointsStatus(); if (bps == null) return; bps.addListener(new ITCFBreakpointListener() { public void breakpointStatusChanged(String id) { - displayExec(new Runnable() { - public void run() { - if (active_launch != launch) return; - refreshBreakpointView(); - } - }); + updateAnnotations(null, launch); } public void breakpointRemoved(String id) { - displayExec(new Runnable() { - public void run() { - if (active_launch != launch) return; - refreshBreakpointView(); - } - }); + updateAnnotations(null, launch); } public void breakpointChanged(String id) { @@ -128,22 +156,8 @@ public class TCFAnnotationManager { public void onDisconnected(final TCFLaunch launch) { assert Protocol.isDispatchThread(); - synchronized (Device.class) { - displayExec(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(); + updateAnnotations(null, launch); } public void onProcessOutput(TCFLaunch launch, String process_id, int stream_id, byte[] data) { @@ -158,6 +172,7 @@ public class TCFAnnotationManager { public void selectionChanged(IWorkbenchPart part, ISelection selection) { updateActiveLaunch(); + updateAnnotations(part.getSite().getWorkbenchWindow(), (TCFLaunch)null); } }; @@ -185,12 +200,13 @@ public class TCFAnnotationManager { IDebugUIConstants.ID_DEBUG_VIEW, selection_listener); windows.put(window, new WorkbenchWindowInfo()); updateActiveLaunch(); + updateAnnotations(window, (TCFLaunch)null); } }; private final Display display = Display.getDefault(); - private int refresh_breakpoint_view_cnt = 0; private int update_active_launch_cnt = 0; + private int update_unnotations_cnt = 0; private boolean started; private boolean disposed; @@ -253,35 +269,12 @@ public class TCFAnnotationManager { 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; + TCFLaunch l = (TCFLaunch)x; + IChannel channel = l.getChannel(); + if (channel != null && channel.getState() == IChannel.STATE_OPEN) launch = l; } } - if (active_launch != launch) { - active_launch = launch; - refreshBreakpointView(); - } - } - }); - } - - private void refreshBreakpointView() { - assert !disposed; - final int cnt = ++refresh_breakpoint_view_cnt; - displayExec(new Runnable() { - public void run() { - if (cnt != refresh_breakpoint_view_cnt) return; - for (IWorkbenchWindow window : windows.keySet()) { - IDebugView view = (IDebugView)window.getActivePage().findView(IDebugUIConstants.ID_BREAKPOINT_VIEW); - if (view != null) view.getViewer().refresh(); - } + active_launch = launch; } }); } @@ -290,7 +283,7 @@ public class TCFAnnotationManager { assert Protocol.isDispatchThread(); if (disposed) return null; final TCFLaunch launch = active_launch; - if (launch != null && launch.getBreakpointsStatus() != null) { + if (launch != null) { TCFBreakpointsStatus bs = launch.getBreakpointsStatus(); if (bs != null) { Map<String,Object> map = bs.getStatus(breakpoint); @@ -307,74 +300,273 @@ public class TCFAnnotationManager { return null; } - 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; + @SuppressWarnings("unchecked") + private Object[] toObjectArray(Object o) { + if (o == null) return null; + Collection<Object> c = (Collection<Object>)o; + return (Object[])c.toArray(new Object[c.size()]); + } - 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, - new Position(region.getOffset(), region.getLength())); - annotation.setType(type); - annotation.setText(text); + @SuppressWarnings("unchecked") + private Map<String,Object> toObjectMap(Object o) { + return (Map<String,Object>)o; + } + + private BigInteger toBigInteger(Number n) { + if (n == null) return null; + if (n instanceof BigInteger) return (BigInteger)n; + return new BigInteger(n.toString()); + } + + private void addBreakpointErrorAnnotation(List<TCFAnnotation> set, TCFLaunch launch, String id, String error) { + Map<String,Object> props = launch.getBreakpointsStatus().getProperties(id); + if (props != null) { + String file = (String)props.get(IBreakpoints.PROP_FILE); + Number line = (Number)props.get(IBreakpoints.PROP_LINE); + if (file != null && line != null) { + ILineNumbers.CodeArea area = new ILineNumbers.CodeArea(null, file, + line.intValue(), 0, line.intValue() + 1, 0, + null, null, 0, false, false, false, false); + TCFAnnotation a = new TCFAnnotation(area, + ImageCache.getImage(ImageCache.IMG_BREAKPOINT_ERROR), + "Cannot plant breakpoint: " + error); + a.setType("org.eclipse.tm.tcf.debug.breakpoint_instance"); //$NON-NLS-1$ + set.add(a); } } + } - if (page != null) { - WorkbenchWindowInfo info = windows.get(page.getWorkbenchWindow()); - if (info != null) { - if (annotation != null && info.annotations.size() == 1) { - for (TCFAnnotation a : info.annotations) { - if (a.model != annotation.model) continue; - if (a.editor != annotation.editor) continue; - if (a.image != annotation.image) continue; - if (!a.exe_id.equals(annotation.exe_id)) continue; - if (!a.position.equals(annotation.position)) continue; - if (!a.getType().equals(annotation.getType())) continue; - if (!a.getText().equals(annotation.getText())) continue; + private void updateAnnotations(IWorkbenchWindow window, final TCFNode node) { + if (disposed) return; + assert Thread.currentThread() == display.getThread(); + final WorkbenchWindowInfo win_info = windows.get(window); + if (win_info == null) return; + List<TCFAnnotation> set = null; + if (node != null) { + set = new TCFTask<List<TCFAnnotation>>(node.getChannel()) { + public void run() { + if (node.isDisposed()) { + done(null); return; } + TCFNodeExecContext thread = null; + TCFNodeExecContext memory = null; + TCFNodeStackFrame frame = null; + String bp_group = null; + if (node instanceof TCFNodeStackFrame) { + thread = (TCFNodeExecContext)node.getParent(); + frame = (TCFNodeStackFrame)node; + } + else if (node instanceof TCFNodeExecContext) { + thread = (TCFNodeExecContext)node; + TCFChildrenStackTrace trace = thread.getStackTrace(); + if (!trace.validate(this)) return; + frame = trace.getTopFrame(); + } + if (thread != null) { + TCFDataCache<IRunControl.RunControlContext> rc_ctx_cache = thread.getRunContext(); + if (!rc_ctx_cache.validate(this)) return; + IRunControl.RunControlContext rc_ctx_data = rc_ctx_cache.getData(); + if (rc_ctx_data != null) bp_group = rc_ctx_data.getBPGroup(); + TCFDataCache<TCFNodeExecContext> mem_cache = thread.getMemoryNode(); + if (!mem_cache.validate(this)) return; + memory = mem_cache.getData(); + } + List<TCFAnnotation> set = new ArrayList<TCFAnnotation>(); + if (memory != null) { + TCFLaunch launch = node.getModel().getLaunch(); + TCFBreakpointsStatus bs = launch.getBreakpointsStatus(); + if (bs != null) { + for (String id : bs.getStatusIDs()) { + Map<String,Object> map = bs.getStatus(id); + if (map == null) continue; + String error = (String)map.get(IBreakpoints.STATUS_ERROR); + if (error != null) addBreakpointErrorAnnotation(set, launch, id, error); + Object[] arr = toObjectArray(map.get(IBreakpoints.STATUS_INSTANCES)); + if (arr == null) continue; + for (Object o : arr) { + Map<String,Object> m = toObjectMap(o); + String ctx_id = (String)m.get(IBreakpoints.INSTANCE_CONTEXT); + if (ctx_id == null) continue; + if (!ctx_id.equals(node.getID()) && !ctx_id.equals(bp_group)) continue; + error = (String)m.get(IBreakpoints.INSTANCE_ERROR); + BigInteger addr = toBigInteger((Number)m.get(IBreakpoints.INSTANCE_ADDRESS)); + if (addr != null) { + ILineNumbers.CodeArea area = null; + TCFDataCache<TCFSourceRef> line_cache = memory.getLineInfo(addr); + if (line_cache != null) { + if (!line_cache.validate(this)) return; + TCFSourceRef line_data = line_cache.getData(); + if (line_data != null && line_data.area != null) area = line_data.area; + } + if (area == null) { + Map<String,Object> props = launch.getBreakpointsStatus().getProperties(id); + if (props != null) { + String file = (String)props.get(IBreakpoints.PROP_FILE); + Number line = (Number)props.get(IBreakpoints.PROP_LINE); + if (file != null && line != null) { + area = new ILineNumbers.CodeArea(null, file, + line.intValue(), 0, line.intValue() + 1, 0, + null, null, 0, false, false, false, false); + } + } + } + if (area != null) { + if (error != null) { + TCFAnnotation a = new TCFAnnotation(area, + ImageCache.getImage(ImageCache.IMG_BREAKPOINT_ERROR), + "Cannot plant breakpoint at 0x" + addr.toString(16) + ": " + error); + a.setType("org.eclipse.tm.tcf.debug.breakpoint_instance"); //$NON-NLS-1$ + set.add(a); + error = null; + } + else { + TCFAnnotation a = new TCFAnnotation(area, + ImageCache.getImage(ImageCache.IMG_BREAKPOINT_INSTALLED), + "Breakpoint planted at 0x" + addr.toString(16)); + a.setType("org.eclipse.tm.tcf.debug.breakpoint_instance"); //$NON-NLS-1$ + set.add(a); + } + } + } + if (error != null) addBreakpointErrorAnnotation(set, launch, id, error); + } + } + } + } + if (frame != null && frame.getFrameNo() >= 0) { + TCFDataCache<TCFSourceRef> line_cache = frame.getLineInfo(); + if (!line_cache.validate(this)) return; + TCFSourceRef line_data = line_cache.getData(); + if (line_data != null && line_data.area != null) { + TCFAnnotation a = null; + if (frame.getFrameNo() == 0) { + a = new TCFAnnotation(line_data.area, + DebugUITools.getImage(IDebugUIConstants.IMG_OBJS_INSTRUCTION_POINTER_TOP), + "Current Instruction Pointer"); + a.setType("org.eclipse.tm.tcf.debug.top_frame"); //$NON-NLS-1$ + } + else { + a = new TCFAnnotation(line_data.area, + DebugUITools.getImage(IDebugUIConstants.IMG_OBJS_INSTRUCTION_POINTER), + "Stack Frame"); + a.setType("org.eclipse.tm.tcf.debug.stack_frame"); //$NON-NLS-1$ + } + set.add(a); + } + } + done(set); } - for (TCFAnnotation a : info.annotations) a.dispose(); - info.annotations.clear(); - if (annotation != null) { - ann_model.addAnnotation(annotation, annotation.position); - info.annotations.add(annotation); + }.getE(); + } + Iterator<TCFAnnotation> i = win_info.annotations.iterator(); + while (i.hasNext()) { + TCFAnnotation a = i.next(); + if (set != null && set.remove(a)) continue; + a.dispose(); + i.remove(); + } + if (set == null || set.size() == 0) return; + Map<IEditorInput,ITextEditor> editors = new HashMap<IEditorInput,ITextEditor>(); + for (IEditorReference ref : window.getActivePage().getEditorReferences()) { + IEditorPart part = ref.getEditor(false); + if (!(part instanceof ITextEditor)) continue; + ITextEditor editor = (ITextEditor)part; + editors.put(editor.getEditorInput(), editor); + } + ISourceLocator locator = node.getModel().getLaunch().getSourceLocator(); + ISourcePresentation presentation = TCFModelPresentation.getDefault(); + for (TCFAnnotation a : set) { + Object source_element = null; + if (locator instanceof TCFSourceLookupDirector) { + source_element = ((TCFSourceLookupDirector)locator).getSourceElement(a.area); + } + else if (locator instanceof ISourceLookupDirector) { + // support for foreign (CDT) source locator + String filename = TCFSourceLookupParticipant.toFileName(a.area); + if (filename != null) { + source_element = ((ISourceLookupDirector)locator).getSourceElement(filename); + if (source_element == null && !filename.equals(a.area.file)) { + // retry with relative path + source_element = ((ISourceLookupDirector)locator).getSourceElement(a.area.file); + } } } + if (source_element == null) continue; + IEditorInput editor_input = presentation.getEditorInput(source_element); + ITextEditor editor = editors.get(editor_input); + if (editor == null) continue; + IDocumentProvider doc_provider = editor.getDocumentProvider(); + IAnnotationModel ann_model = doc_provider.getAnnotationModel(editor_input); + if (ann_model == null) continue; + IRegion region = null; + try { + doc_provider.connect(editor_input); + } + catch (CoreException e) { + } + try { + IDocument document = doc_provider.getDocument(editor_input); + if (document != null) region = document.getLineInformation(a.area.start_line - 1); + } + catch (BadLocationException e) { + } + finally { + doc_provider.disconnect(editor_input); + } + if (region == null) continue; + ann_model.addAnnotation(a, new Position(region.getOffset(), region.getLength())); + a.model = ann_model; + win_info.annotations.add(a); } } - void removeStackFrameAnnotation(TCFModel model, Set<String> ids) { - 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 && ids.contains(a.exe_id)) { - i.remove(); - a.dispose(); + private void updateAnnotations() { + final int cnt = ++update_unnotations_cnt; + displayExec(new Runnable() { + public void run() { + TCFNode node = null; + if (cnt != update_unnotations_cnt) return; + for (IWorkbenchWindow window : windows.keySet()) { + if (dirty_windows.contains(null) || dirty_windows.contains(window)) { + try { + ISelection active_context = DebugUITools.getDebugContextManager() + .getContextService(window).getActiveContext(); + if (active_context instanceof IStructuredSelection) { + IStructuredSelection selection = (IStructuredSelection)active_context; + if (!selection.isEmpty()) { + Object first_element = selection.getFirstElement(); + if (first_element instanceof IAdaptable) { + node = (TCFNode)((IAdaptable)first_element).getAdapter(TCFNode.class); + } + } + } + if (dirty_launches.contains(null) || node != null && dirty_launches.contains(node.getModel().getLaunch())) { + updateAnnotations(window, node); + } + } + catch (Throwable x) { + if (node != null && node.isDisposed()) return; + Activator.log("Cannot update editor annotations", x); + } + } + } + for (TCFLaunch launch : dirty_launches) { + if (launch != null) launch.removePendingClient(TCFAnnotationManager.this); } + dirty_windows.clear(); + dirty_launches.clear(); } - } + }); + } + + void updateAnnotations(final IWorkbenchWindow window, final TCFLaunch launch) { + displayExec(new Runnable() { + public void run() { + dirty_windows.add(window); + dirty_launches.add(launch); + updateAnnotations(); + } + }); } } 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 3cfeffdf2..c2af3b391 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 @@ -275,22 +275,6 @@ public class TCFModel implements IElementContentProvider, IElementLabelProvider, private final IModelSelectionPolicy selection_policy; - private final HashSet<String> removed_annotations = new HashSet<String>(); - private boolean removed_annotations_posted; - private final Runnable removed_annotations_runnable = new Runnable() { - public void run() { - HashSet<String> set = null; - synchronized (removed_annotations) { - assert removed_annotations_posted; - removed_annotations_posted = false; - if (removed_annotations.size() == 0) return; - set = new HashSet<String>(removed_annotations); - removed_annotations.clear(); - } - annotation_manager.removeStackFrameAnnotation(TCFModel.this, set); - } - }; - private IChannel channel; private TCFNodeLaunch launch_node; private boolean disposed; @@ -345,7 +329,7 @@ public class TCFModel implements IElementContentProvider, IElementLabelProvider, ((TCFNodeExecContext)node).onContainerResumed(); } } - for (String id : context_ids) removeAnnotation(id); + annotation_manager.updateAnnotations(null, launch); } public void containerSuspended(String context, String pc, String reason, @@ -415,7 +399,7 @@ public class TCFModel implements IElementContentProvider, IElementLabelProvider, if (node instanceof TCFNodeExecContext) { ((TCFNodeExecContext)node).onContextResumed(); } - removeAnnotation(id); + annotation_manager.updateAnnotations(null, launch); } public void contextSuspended(String id, String pc, String reason, Map<String,Object> params) { @@ -520,7 +504,7 @@ public class TCFModel implements IElementContentProvider, IElementLabelProvider, public void onContextActionStart(TCFAction action) { final String id = action.getContextID(); active_actions.put(id, action); - removeAnnotation(id); + annotation_manager.updateAnnotations(null, launch); } public void onContextActionResult(String id, String reason) { @@ -801,7 +785,7 @@ public class TCFModel implements IElementContentProvider, IElementLabelProvider, launch_node.onAnyContextAddedOrRemoved(); // Close debug session if the last context is removed: onContextOrProcessRemoved(); - for (String id : context_ids) removeAnnotation(id); + annotation_manager.updateAnnotations(null, launch); } private void onContextOrProcessRemoved() { @@ -1240,12 +1224,8 @@ public class TCFModel implements IElementContentProvider, IElementLabelProvider, } if (source_element != null) { 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); - } + editor_input = presentation.getEditorInput(source_element); + if (editor_input != null) editor_id = presentation.getEditorId(editor_input, source_element); line = area.start_line; } } @@ -1289,8 +1269,8 @@ public class TCFModel implements IElementContentProvider, IElementLabelProvider, region = getLineInformation(text_editor, line); if (region != null) text_editor.selectAndReveal(region.getOffset(), 0); } - annotation_manager.addStackFrameAnnotation(TCFModel.this, - exe_id, top_frame, page, text_editor, region); + if (wait_for_pc_update_after_step) launch.addPendingClient(annotation_manager); + annotation_manager.updateAnnotations(page.getWorkbenchWindow(), launch); } finally { if (cnt == display_source_generation) launch.removePendingClient(TCFModel.this); @@ -1299,17 +1279,6 @@ public class TCFModel implements IElementContentProvider, IElementLabelProvider, }); } - /* Remove editor annotations for given executable context ID */ - private void removeAnnotation(String id) { - synchronized (removed_annotations) { - removed_annotations.add(id); - if (!removed_annotations_posted) { - display.asyncExec(removed_annotations_runnable); - removed_annotations_posted = true; - } - } - } - /* * Refresh Launch View. * Normally the view is updated by sending deltas through model proxy. @@ -1426,7 +1395,7 @@ public class TCFModel implements IElementContentProvider, IElementLabelProvider, /* * Returns the line information for the given line in the given editor */ - private IRegion getLineInformation(ITextEditor editor, int lineNumber) { + private IRegion getLineInformation(ITextEditor editor, int line) { IDocumentProvider provider = editor.getDocumentProvider(); IEditorInput input = editor.getEditorInput(); try { @@ -1437,8 +1406,7 @@ public class TCFModel implements IElementContentProvider, IElementLabelProvider, } try { IDocument document = provider.getDocument(input); - if (document != null) - return document.getLineInformation(lineNumber - 1); + if (document != null) return document.getLineInformation(line - 1); } catch (BadLocationException e) { } 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 f2b51b29d..c0cd8c27a 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 @@ -168,6 +168,11 @@ public class TCFNodeStackFrame extends TCFNode { }; } + /** + * Get frame position in the parent's stack trace. + * Top frame position is 0. + * @return frame position or -1 if the frame is not part of the trace. + */ public int getFrameNo() { assert Protocol.isDispatchThread(); return frame_no; diff --git a/plugins/org.eclipse.tm.tcf.debug/src/org/eclipse/tm/internal/tcf/debug/launch/TCFSourceLookupParticipant.java b/plugins/org.eclipse.tm.tcf.debug/src/org/eclipse/tm/internal/tcf/debug/launch/TCFSourceLookupParticipant.java index b6125ae5e..3e3d289c1 100644 --- a/plugins/org.eclipse.tm.tcf.debug/src/org/eclipse/tm/internal/tcf/debug/launch/TCFSourceLookupParticipant.java +++ b/plugins/org.eclipse.tm.tcf.debug/src/org/eclipse/tm/internal/tcf/debug/launch/TCFSourceLookupParticipant.java @@ -125,7 +125,7 @@ public class TCFSourceLookupParticipant extends AbstractSourceLookupParticipant int j = name.lastIndexOf('\\'); if (i > j) base = name.substring(i + 1); if (j > i) base = name.substring(j + 1); - res = super.findSourceElements(base); + if (!base.equals(name)) res = super.findSourceElements(base); } } ArrayList<Object> list = new ArrayList<Object>(); diff --git a/plugins/org.eclipse.tm.tcf.debug/src/org/eclipse/tm/internal/tcf/debug/model/TCFBreakpointsStatus.java b/plugins/org.eclipse.tm.tcf.debug/src/org/eclipse/tm/internal/tcf/debug/model/TCFBreakpointsStatus.java index a41b1d9fe..bf73c1938 100644 --- a/plugins/org.eclipse.tm.tcf.debug/src/org/eclipse/tm/internal/tcf/debug/model/TCFBreakpointsStatus.java +++ b/plugins/org.eclipse.tm.tcf.debug/src/org/eclipse/tm/internal/tcf/debug/model/TCFBreakpointsStatus.java @@ -26,6 +26,7 @@ import org.eclipse.tm.tcf.services.IBreakpoints; public class TCFBreakpointsStatus { private final IBreakpoints service; + private final Map<String,Map<String,Object>> breakpoints = new HashMap<String,Map<String,Object>>(); private final Map<String,Map<String,Object>> status = new HashMap<String,Map<String,Object>>(); private final Set<ITCFBreakpointListener> listeners = new HashSet<ITCFBreakpointListener>(); @@ -53,6 +54,7 @@ public class TCFBreakpointsStatus { public void contextAdded(Map<String,Object>[] bps) { for (Map<String,Object> bp : bps) { String id = (String)bp.get(IBreakpoints.PROP_ID); + breakpoints.put(id, bp); if (status.get(id) != null) continue; status.put(id, new HashMap<String,Object>()); for (Iterator<ITCFBreakpointListener> i = listeners.iterator(); i.hasNext();) { @@ -64,6 +66,7 @@ public class TCFBreakpointsStatus { public void contextChanged(Map<String,Object>[] bps) { for (Map<String,Object> bp : bps) { String id = (String)bp.get(IBreakpoints.PROP_ID); + breakpoints.put(id, bp); if (!status.containsKey(id)) continue; for (Iterator<ITCFBreakpointListener> i = listeners.iterator(); i.hasNext();) { i.next().breakpointChanged(id); @@ -73,6 +76,7 @@ public class TCFBreakpointsStatus { public void contextRemoved(String[] ids) { for (String id : ids) { + breakpoints.remove(id); if (!status.containsKey(id)) continue; for (Iterator<ITCFBreakpointListener> i = listeners.iterator(); i.hasNext();) { i.next().breakpointRemoved(id); @@ -89,13 +93,16 @@ public class TCFBreakpointsStatus { public void doneGetIDs(IToken token, Exception error, String[] ids) { if (error != null) return; for (final String id : ids) { - // fake properties - only ID is required for contextAdded - Map<String, Object> bpProps = new HashMap<String, Object>(); - bpProps.put(IBreakpoints.PROP_ID, id); - listener.contextAdded((Map<String, Object>[]) new Map[] { bpProps }); - service.getStatus(id, new IBreakpoints.DoneGetStatus() { - public void doneGetStatus(IToken token, Exception error, Map<String, Object> status) { - if (error == null) listener.breakpointStatusChanged(id, status); + service.getProperties(id, new IBreakpoints.DoneGetProperties() { + public void doneGetProperties(IToken token, Exception error, Map<String, Object> props) { + if (error == null) { + listener.contextAdded((Map<String, Object>[]) new Map[] { props }); + service.getStatus(id, new IBreakpoints.DoneGetStatus() { + public void doneGetStatus(IToken token, Exception error, Map<String, Object> status) { + if (error == null) listener.breakpointStatusChanged(id, status); + } + }); + } } }); } @@ -115,6 +122,12 @@ public class TCFBreakpointsStatus { return status.get(id); } + public Map<String,Object> getProperties(String id) { + assert id != null; + assert Protocol.isDispatchThread(); + return breakpoints.get(id); + } + public Map<String,Object> getStatus(IBreakpoint bp) { try { String id = TCFBreakpointsModel.getBreakpointsModel().getBreakpointID(bp); |