summaryrefslogtreecommitdiffstatsabout
diff options
context:
space:
mode:
authorPawel Piech2012-06-08 23:22:58 (EDT)
committer Eugene Tarassov2012-06-11 20:05:48 (EDT)
commitd4fce15928897a3cb0c9757ea5abf50a93c49051 (patch)
tree0de839247ccb3985f9513dc3268b145836e77cc6
parent10793bd1adb4c2e5f52df3d99515b153dce63bfb (diff)
downloadorg.eclipse.tcf-d4fce15928897a3cb0c9757ea5abf50a93c49051.zip
org.eclipse.tcf-d4fce15928897a3cb0c9757ea5abf50a93c49051.tar.gz
org.eclipse.tcf-d4fce15928897a3cb0c9757ea5abf50a93c49051.tar.bz2
Bug 381993 - [breakpoints] Add a detail pane in breakpoints view to show breakpoints' scope setting
Completed implementaiton.
-rw-r--r--plugins/org.eclipse.tcf.cdt.ui/plugin.xml27
-rw-r--r--plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/breakpoints/TCFBreakpointScopeDetailPane.java443
-rw-r--r--plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/breakpoints/TCFBreakpointScopeDetailPaneFactory.java48
-rw-r--r--plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/adapters/TCFLaunchLabelProvider.java149
-rw-r--r--plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFChildrenContextQuery.java4
-rw-r--r--plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFContextQueryDescendants.java85
-rw-r--r--plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFModel.java56
-rw-r--r--plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFNodeExecContext.java142
-rw-r--r--plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFNodeLaunch.java15
-rw-r--r--plugins/org.eclipse.tcf.debug/src/org/eclipse/tcf/internal/debug/model/TCFLaunch.java22
-rw-r--r--tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/BreakpointDetailPaneTest.java90
11 files changed, 1023 insertions, 58 deletions
diff --git a/plugins/org.eclipse.tcf.cdt.ui/plugin.xml b/plugins/org.eclipse.tcf.cdt.ui/plugin.xml
index ac6d4f5..cb2668b 100644
--- a/plugins/org.eclipse.tcf.cdt.ui/plugin.xml
+++ b/plugins/org.eclipse.tcf.cdt.ui/plugin.xml
@@ -451,5 +451,32 @@
</visibleWhen>
</command>
</menuContribution>
+
</extension>
+ <extension point="org.eclipse.debug.ui.detailPaneFactories">
+ <detailFactories
+ class="org.eclipse.tcf.internal.cdt.ui.breakpoints.TCFBreakpointScopeDetailPaneFactory"
+ id="org.eclipse.tcf.debug.BreakpointScopeDetailPaneFactory">
+ <enablement>
+ <and>
+ <with variable="selection">
+ <iterate>
+ <or>
+ <instanceof value=" org.eclipse.cdt.debug.core.model.ICBreakpoint"/>
+ </or>
+ </iterate>
+ </with>
+ <with variable="debugContext">
+ <iterate
+ ifEmpty="false">
+ <or>
+ <instanceof value="org.eclipse.tcf.internal.debug.ui.model.TCFNode"/>
+ </or>
+ </iterate>
+ </with>
+ </and>
+ </enablement>
+ </detailFactories>
+ </extension>
+
</plugin>
diff --git a/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/breakpoints/TCFBreakpointScopeDetailPane.java b/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/breakpoints/TCFBreakpointScopeDetailPane.java
new file mode 100644
index 0000000..6f20109
--- /dev/null
+++ b/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/breakpoints/TCFBreakpointScopeDetailPane.java
@@ -0,0 +1,443 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2012 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.tcf.internal.cdt.ui.breakpoints;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.eclipse.cdt.debug.core.model.ICBreakpoint;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.PlatformObject;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.core.ILaunchManager;
+import org.eclipse.debug.core.ILaunchesListener2;
+import org.eclipse.debug.internal.ui.SWTFactory;
+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.IElementContentProvider;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
+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.internal.ui.viewers.model.provisional.ITreeModelViewer;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.PresentationContext;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.TreeModelViewer;
+import org.eclipse.debug.internal.ui.viewers.provisional.AbstractModelProxy;
+import org.eclipse.debug.ui.IDetailPane;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.tcf.debug.ui.ITCFDebugUIConstants;
+import org.eclipse.tcf.internal.cdt.ui.ImageCache;
+import org.eclipse.tcf.internal.debug.model.ITCFConstants;
+import org.eclipse.tcf.internal.debug.model.TCFLaunch;
+import org.eclipse.tcf.internal.debug.ui.model.TCFContextQueryDescendants;
+import org.eclipse.tcf.internal.debug.ui.model.TCFModel;
+import org.eclipse.tcf.internal.debug.ui.model.TCFModelManager;
+import org.eclipse.tcf.protocol.Protocol;
+import org.eclipse.ui.IWorkbenchPartSite;
+
+/**
+ * This detail pane uses a tree viewer to show which contexts a given breakpoint
+ * can potentially trigger.
+ */
+@SuppressWarnings("restriction")
+public class TCFBreakpointScopeDetailPane implements IDetailPane {
+
+ public static final String ID = "org.eclipse.tcf.debug.DetailPaneFactory";
+ public static final String NAME = "TCF Detail Pane";
+ public static final String DESC = "TCF Detail Pane";
+
+ private Composite fComposite;
+ private Label fFilterName;
+ private TreeModelViewer fTreeViewer;
+
+ public static class ScopeDetailInputObject extends PlatformObject implements IElementContentProvider, IModelProxyFactory {
+
+ private final ContextQueryElement fContextQueryElement;
+
+ public ScopeDetailInputObject(ContextQueryElement query) {
+ fContextQueryElement = query;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other instanceof ScopeDetailInputObject) {
+ return fContextQueryElement.equals( ((ScopeDetailInputObject)other).fContextQueryElement );
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return fContextQueryElement.hashCode();
+ }
+
+ public void update(IChildrenCountUpdate[] updates) {
+ for (IChildrenCountUpdate update : updates) {
+ update.setChildCount(1);
+ update.done();
+ }
+ }
+
+ public void update(IChildrenUpdate[] updates) {
+ for (IChildrenUpdate update : updates) {
+ if (update.getOffset() == 0) {
+ update.setChild(fContextQueryElement, 0);
+ update.done();
+ }
+ }
+ }
+
+ public void update(IHasChildrenUpdate[] updates) {
+ for (IHasChildrenUpdate update : updates) {
+ update.setHasChilren(true);
+ update.done();
+ }
+ }
+
+ public IModelProxy createModelProxy(Object element, IPresentationContext context) {
+ return new AbstractModelProxy() {
+ @Override
+ public void initialize(ITreeModelViewer viewer) {
+ super.initialize(viewer);
+ ModelDelta delta = new ModelDelta(this, IModelDelta.NO_CHANGE);
+ delta.addNode(fContextQueryElement, 0, IModelDelta.INSTALL);
+ fireModelChanged(delta);
+ }
+ };
+ }
+ }
+
+ public static class ContextQueryElement extends PlatformObject
+ implements IElementContentProvider, IElementLabelProvider, IModelProxyFactory
+ {
+ private final String fQuery;
+ private Set<String> fContexts;
+
+ public ContextQueryElement(String query, Set<String> contexts) {
+ fQuery = query;
+ fContexts = contexts;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other instanceof ContextQueryElement) {
+ ContextQueryElement element = (ContextQueryElement)other;
+ return ((fQuery == null && element.fQuery == null) ||
+ (fQuery != null && fQuery.equals(element.fQuery))) &&
+ ((fContexts == null && element.fContexts == null) ||
+ (fContexts != null && fContexts.equals(element.fContexts)));
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return (fQuery != null ? fQuery.hashCode() : 0) + (fContexts != null ? fContexts.hashCode() : 0);
+ }
+
+ public void update(IChildrenCountUpdate[] updates) {
+ for (IViewerUpdate update : updates) {
+ getFilteredLaunches(update);
+ }
+ }
+
+ public void update(IChildrenUpdate[] updates) {
+ for (IViewerUpdate update : updates) {
+ getFilteredLaunches(update);
+ }
+ }
+
+ public void update(IHasChildrenUpdate[] updates) {
+ for (IViewerUpdate update : updates) {
+ getFilteredLaunches(update);
+ }
+ }
+
+ public void update(ILabelUpdate[] updates) {
+ for (ILabelUpdate update : updates) {
+ getQueryFilteredContexts(update);
+ }
+ }
+
+ private List<TCFLaunch> getTCFLaunches() {
+ List<TCFLaunch> tcfLaunches = new ArrayList<TCFLaunch>();
+ for (ILaunch launch : DebugPlugin.getDefault().getLaunchManager().getLaunches()) {
+ if (launch instanceof TCFLaunch) {
+ tcfLaunches.add((TCFLaunch)launch);
+ }
+ }
+ return tcfLaunches;
+ }
+
+
+ private void getFilteredLaunches (final IViewerUpdate update) {
+ Protocol.invokeLater( new Runnable() {
+ public void run() {
+ final List<TCFLaunch> filteredLaunches = new ArrayList<TCFLaunch>();
+ TCFModelManager modelManager = TCFModelManager.getModelManager();
+ for (TCFLaunch launch : getTCFLaunches()) {
+ TCFModel model = modelManager.getModel(launch);
+ if (model != null && model.getRootNode() != null) {
+ TCFContextQueryDescendants query_descendants = model.getRootNode().getContextQueryDescendants();
+ if (!query_descendants.setQuery(fQuery, launch.getModelContexts(fContexts), this)) return;
+ if (!query_descendants.validate(this)) return;
+ if (query_descendants.getData() != null && !query_descendants.getData().isEmpty()) {
+ filteredLaunches.add(launch);
+ }
+ }
+ }
+
+ done(filteredLaunches, update);
+ }
+ });
+ }
+
+ private void getQueryFilteredContexts (final ILabelUpdate update) {
+ Protocol.invokeLater( new Runnable() {
+ public void run() {
+ TCFModelManager modelManager = TCFModelManager.getModelManager();
+ Set<String> set = new TreeSet<String>();
+ for (TCFLaunch launch : getTCFLaunches()) {
+ TCFModel model = modelManager.getModel(launch);
+ if (model != null && model.getRootNode() != null) {
+ TCFContextQueryDescendants query_descendants = model.getRootNode().getContextQueryDescendants();
+ if (!query_descendants.setQuery(fQuery, launch.getModelContexts(fContexts), this)) return;
+ if (!query_descendants.validate(this)) return;
+ if (query_descendants.getData() != null) {
+ set.addAll(query_descendants.getData());
+ }
+ }
+ }
+
+ StringBuffer label = new StringBuffer();
+ label.append("(");
+ label.append(set.size());
+ label.append(") ");
+
+ if (fQuery != null) {
+ label.append("Filter: ");
+ label.append(fQuery);
+ if (fContexts != null) {
+ label.append(", ");
+ }
+ }
+ if (fContexts != null) {
+ label.append("Contexts: ");
+ label.append(fContexts);
+ }
+ update.setLabel(label.toString(), 0);
+ update.setImageDescriptor(ImageCache.getImageDescriptor(ImageCache.IMG_BREAKPOINT_SCOPE), 0);
+ update.done();
+ }
+ });
+ }
+
+ private void done(List<TCFLaunch> launches, IViewerUpdate update) {
+ if (update instanceof IHasChildrenUpdate) {
+ ((IHasChildrenUpdate)update).setHasChilren(!launches.isEmpty());
+ } else if (update instanceof IChildrenCountUpdate) {
+ ((IChildrenCountUpdate)update).setChildCount(launches.size());
+ } else if (update instanceof IChildrenUpdate) {
+ IChildrenUpdate childrenUpdate = (IChildrenUpdate)update;
+ int updateStart = childrenUpdate.getOffset();
+ int updateEnd = childrenUpdate.getOffset() + childrenUpdate.getLength();
+ for (int i = updateStart; i < updateEnd && i < launches.size(); i++) {
+ childrenUpdate.setChild(launches.get(i), i);
+ }
+ }
+ update.done();
+ }
+
+ public IModelProxy createModelProxy(Object element, IPresentationContext context) {
+ return new QueryInputObjectProxy();
+ }
+ }
+
+ public static class QueryInputObjectProxy extends AbstractModelProxy implements ILaunchesListener2 {
+
+ private ILaunchManager fLaunchManager;
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.internal.ui.viewers.AbstractModelProxy#init(org.eclipse.debug.internal.ui.viewers.IPresentationContext)
+ */
+ public synchronized void init(IPresentationContext context) {
+ super.init(context);
+ fLaunchManager = DebugPlugin.getDefault().getLaunchManager();
+ fLaunchManager.addLaunchListener(this);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.internal.ui.viewers.provisional.AbstractModelProxy#installed(org.eclipse.jface.viewers.Viewer)
+ */
+ public void installed(Viewer viewer) {
+ // expand existing launches
+ ILaunch[] launches = fLaunchManager.getLaunches();
+ if (launches.length > 0) {
+ launchesAdded(launches);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.internal.ui.viewers.AbstractModelProxy#dispose()
+ */
+ public synchronized void dispose() {
+ super.dispose();
+ if (fLaunchManager != null) {
+ fLaunchManager.removeLaunchListener(this);
+ fLaunchManager = null;
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.ILaunchesListener2#launchesTerminated(org.eclipse.debug.core.ILaunch[])
+ */
+ public void launchesTerminated(ILaunch[] launches) {
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.ILaunchesListener#launchesRemoved(org.eclipse.debug.core.ILaunch[])
+ */
+ public void launchesRemoved(ILaunch[] launches) {
+ fireDelta(launches, IModelDelta.REMOVED);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.ILaunchesListener#launchesAdded(org.eclipse.debug.core.ILaunch[])
+ */
+ public void launchesAdded(ILaunch[] launches) {
+ fireDelta(launches, IModelDelta.ADDED | IModelDelta.INSTALL);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.ILaunchesListener#launchesChanged(org.eclipse.debug.core.ILaunch[])
+ */
+ public void launchesChanged(ILaunch[] launches) {
+ }
+
+ /**
+ * Convenience method for firing a delta
+ * @param launches the launches to set in the delta
+ * @param launchFlags the flags for the delta
+ */
+ protected void fireDelta(ILaunch[] launches, int launchFlags) {
+ ModelDelta delta = new ModelDelta(fLaunchManager, IModelDelta.NO_CHANGE);
+ for (int i = 0; i < launches.length; i++) {
+ if (launches[i] instanceof TCFLaunch) {
+ delta.addNode(launches[i], launchFlags);
+ }
+ }
+ fireModelChanged(delta);
+ }
+
+}
+
+ public Control createControl(Composite parent) {
+ fComposite = SWTFactory.createComposite(parent, 1, 1, GridData.FILL_BOTH);
+ fFilterName = SWTFactory.createLabel(fComposite, "Scope", 1);
+ fTreeViewer = new TreeModelViewer(fComposite, SWT.VIRTUAL, new PresentationContext(ITCFDebugUIConstants.ID_CONTEXT_QUERY_VIEW));
+ Control control = fTreeViewer.getControl();
+ GridData treeLayoutData = new GridData(GridData.FILL_BOTH);
+ treeLayoutData.horizontalIndent = 10;
+ control.setLayoutData(treeLayoutData);
+ GridData gd = new GridData(GridData.FILL_BOTH);
+ control.setLayoutData(gd);
+
+ return fComposite;
+ }
+
+ public void display(IStructuredSelection selection) {
+ if (fTreeViewer == null) return;
+
+ TCFBreakpointScopeExtension extension = getTCFBreakpointScopeExtension((ICBreakpoint)selection.getFirstElement());
+ if (extension != null) {
+ String filter = extension.getPropertiesFilter();
+ if (filter != null && filter.trim().isEmpty()) {
+ filter = null;
+ }
+ String[] contexts = extension.getThreadFilters();
+
+ if (filter != null || contexts != null) {
+ fFilterName.setText("Scope");
+ Set<String> contextsSet = contexts != null ? new TreeSet<String>(Arrays.asList(contexts)) : null;
+ fTreeViewer.setInput( new ScopeDetailInputObject(
+ new ContextQueryElement(filter, contextsSet)) );
+ fTreeViewer.getPresentationContext().setProperty(ITCFDebugUIConstants.PROP_CONTEXT_QUERY, filter);
+ fTreeViewer.getPresentationContext().setProperty(ITCFDebugUIConstants.PROP_FILTER_CONTEXTS, contextsSet);
+ fTreeViewer.refresh();
+ return;
+ }
+ }
+ fFilterName.setText("No scope specified.");
+ fTreeViewer.setInput(null);
+ fTreeViewer.getPresentationContext().setProperty(ITCFDebugUIConstants.PROP_CONTEXT_QUERY, null);
+ fTreeViewer.getPresentationContext().setProperty(ITCFDebugUIConstants.PROP_FILTER_CONTEXTS, null);
+ }
+
+ private TCFBreakpointScopeExtension getTCFBreakpointScopeExtension(ICBreakpoint bp) {
+ if (bp == null) return null;
+ try {
+ return (TCFBreakpointScopeExtension) bp.getExtension(
+ ITCFConstants.ID_TCF_DEBUG_MODEL, TCFBreakpointScopeExtension.class);
+ } catch (CoreException e) {}
+ return null;
+ }
+
+ public void dispose() {
+ if (fTreeViewer != null) {
+ fTreeViewer.getControl().dispose();
+ fTreeViewer = null;
+ }
+ if (fFilterName != null) {
+ fFilterName.dispose();
+ fFilterName = null;
+ }
+ if (fComposite != null) {
+ fComposite.dispose();
+ fComposite = null;
+ }
+ }
+
+ public String getDescription() {
+ return DESC;
+ }
+
+ public String getID() {
+ return ID;
+ }
+
+ public String getName() {
+ return NAME;
+ }
+
+ public void init(IWorkbenchPartSite part_site) {
+ }
+
+ public boolean setFocus() {
+ if (fTreeViewer == null) return false;
+ fTreeViewer.getControl().setFocus();
+ return true;
+ }
+}
diff --git a/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/breakpoints/TCFBreakpointScopeDetailPaneFactory.java b/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/breakpoints/TCFBreakpointScopeDetailPaneFactory.java
new file mode 100644
index 0000000..6605871
--- /dev/null
+++ b/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/breakpoints/TCFBreakpointScopeDetailPaneFactory.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tcf.internal.cdt.ui.breakpoints;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.eclipse.debug.ui.IDetailPane;
+import org.eclipse.debug.ui.IDetailPaneFactory;
+import org.eclipse.jface.viewers.IStructuredSelection;
+
+/**
+ *
+ */
+public class TCFBreakpointScopeDetailPaneFactory implements IDetailPaneFactory {
+
+ public IDetailPane createDetailPane(String paneID) {
+ assert paneID.equals(TCFBreakpointScopeDetailPane.ID);
+ return new TCFBreakpointScopeDetailPane();
+ }
+
+ public String getDefaultDetailPane(IStructuredSelection selection) {
+ return TCFBreakpointScopeDetailPane.ID;
+ }
+
+ public String getDetailPaneDescription(String paneID) {
+ return TCFBreakpointScopeDetailPane.NAME;
+ }
+
+ public String getDetailPaneName(String paneID) {
+ return TCFBreakpointScopeDetailPane.DESC;
+ }
+
+ @SuppressWarnings("rawtypes")
+ public Set getDetailPaneTypes(IStructuredSelection selection) {
+ HashSet<String> set = new HashSet<String>();
+ set.add(TCFBreakpointScopeDetailPane.ID);
+ return set;
+ }
+}
diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/adapters/TCFLaunchLabelProvider.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/adapters/TCFLaunchLabelProvider.java
index 047bfc5..4a28eab 100644
--- a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/adapters/TCFLaunchLabelProvider.java
+++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/adapters/TCFLaunchLabelProvider.java
@@ -12,6 +12,7 @@ package org.eclipse.tcf.internal.debug.ui.adapters;
import java.util.Collection;
import java.util.Map;
+import java.util.Set;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider;
@@ -19,63 +20,125 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate;
import org.eclipse.debug.ui.DebugUITools;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.graphics.RGB;
+import org.eclipse.tcf.debug.ui.ITCFDebugUIConstants;
import org.eclipse.tcf.internal.debug.model.TCFLaunch;
import org.eclipse.tcf.internal.debug.ui.ImageCache;
+import org.eclipse.tcf.internal.debug.ui.model.TCFContextQueryDescendants;
import org.eclipse.tcf.internal.debug.ui.model.TCFModel;
+import org.eclipse.tcf.internal.debug.ui.model.TCFModelManager;
+import org.eclipse.tcf.protocol.Protocol;
import org.eclipse.tcf.services.IProcesses;
class TCFLaunchLabelProvider implements IElementLabelProvider {
public void update(ILabelUpdate[] updates) {
for (int i = 0; i < updates.length; i++) {
- ILabelUpdate result = updates[i];
- final TCFLaunch launch = (TCFLaunch)result.getElement();
- ImageDescriptor image = DebugUITools.getDefaultImageDescriptor(launch);
- if (image == null) image = ImageCache.getImageDescriptor(ImageCache.IMG_TCF);
- result.setImageDescriptor(image, 0);
- String status = "";
- if (launch.isConnecting()) {
- status = "Connecting";
+ String view_id = updates[i].getPresentationContext().getId();
+ if (ITCFDebugUIConstants.ID_CONTEXT_QUERY_VIEW.equals(view_id)) {
+ updateContextQueryViewLabel(updates[i]);
+ } else {
+ updateDebugViewLabel(updates[i]);
}
- else if (launch.isDisconnected()) {
- status = "Disconnected";
- }
- String peer_name = launch.getPeerName();
- if (peer_name != null) {
- if (status.length() == 0) status = peer_name;
- else status = peer_name + ": " + status;
- }
- if (status.length() > 0) status = " (" + status + ")";
- Throwable error = launch.getError();
- if (error != null) {
- status += ": " + TCFModel.getErrorMessage(error, false);
- result.setForeground(new RGB(255, 0, 0), 0);
+ }
+ }
+
+ private void updateDebugViewLabel(ILabelUpdate result) {
+ final TCFLaunch launch = (TCFLaunch)result.getElement();
+ ImageDescriptor image = DebugUITools.getDefaultImageDescriptor(launch);
+ if (image == null) image = ImageCache.getImageDescriptor(ImageCache.IMG_TCF);
+ result.setImageDescriptor(image, 0);
+ String status = "";
+ if (launch.isConnecting()) {
+ status = "Connecting";
+ }
+ else if (launch.isDisconnected()) {
+ status = "Disconnected";
+ }
+ String peer_name = launch.getPeerName();
+ if (peer_name != null) {
+ if (status.length() == 0) status = peer_name;
+ else status = peer_name + ": " + status;
+ }
+ if (status.length() > 0) status = " (" + status + ")";
+ Throwable error = launch.getError();
+ if (error != null) {
+ status += ": " + TCFModel.getErrorMessage(error, false);
+ result.setForeground(new RGB(255, 0, 0), 0);
+ }
+ else if (launch.isExited()) {
+ status += ": All exited or detached";
+ int code = launch.getExitCode();
+ if (code > 0) status += ", exit code " + code;
+ if (code < 0) {
+ status += ", signal " + (-code);
+ Collection<Map<String,Object>> sigs = launch.getSignalList();
+ if (sigs != null) {
+ for (Map<String,Object> m : sigs) {
+ Number num = (Number)m.get(IProcesses.SIG_CODE);
+ if (num == null) continue;
+ if (num.intValue() != -code) continue;
+ String s = (String)m.get(IProcesses.SIG_NAME);
+ if (s == null) continue;
+ status += " (" + s + ")";
+ break;
+ }
+ }
}
- else if (launch.isExited()) {
- status += ": All exited or detached";
- int code = launch.getExitCode();
- if (code > 0) status += ", exit code " + code;
- if (code < 0) {
- status += ", signal " + (-code);
- Collection<Map<String,Object>> sigs = launch.getSignalList();
- if (sigs != null) {
- for (Map<String,Object> m : sigs) {
- Number num = (Number)m.get(IProcesses.SIG_CODE);
- if (num == null) continue;
- if (num.intValue() != -code) continue;
- String s = (String)m.get(IProcesses.SIG_NAME);
- if (s == null) continue;
- status += " (" + s + ")";
- break;
+ }
+ String name = "?";
+ ILaunchConfiguration cfg = launch.getLaunchConfiguration();
+ if (cfg != null) name = cfg.getName();
+ result.setLabel(name + status, 0);
+ result.done();
+ }
+
+ private void updateContextQueryViewLabel(final ILabelUpdate result) {
+ Protocol.invokeLater(new Runnable() {
+ public void run() {
+ TCFLaunch launch = (TCFLaunch)result.getElement();
+ ImageDescriptor image = DebugUITools.getDefaultImageDescriptor(launch);
+ if (image == null) image = ImageCache.getImageDescriptor(ImageCache.IMG_TCF);
+ result.setImageDescriptor(image, 0);
+
+ StringBuffer label = new StringBuffer();
+ TCFModel model = TCFModelManager.getModelManager().getModel(launch);
+
+ if (model != null && model.getRootNode() != null) {
+ String query = (String)result.getPresentationContext().getProperty(ITCFDebugUIConstants.PROP_CONTEXT_QUERY);
+ @SuppressWarnings("unchecked")
+ Set<String> contexts = (Set<String>)result.getPresentationContext().getProperty(ITCFDebugUIConstants.PROP_FILTER_CONTEXTS);
+ TCFContextQueryDescendants query_descendents = model.getRootNode().getContextQueryDescendants();
+ if (!query_descendents.setQuery(query, model.getLaunch().getModelContexts(contexts), this)) return;
+ if (!query_descendents.validate(this)) return;
+ if (query_descendents.getError() == null) {
+ Set<String> descendants = query_descendents.getData();
+ if (descendants != null && !descendants.isEmpty()) {
+ label.append("(");
+ label.append(descendants.size());
+ label.append(") ");
}
}
+ }
+
+ ILaunchConfiguration cfg = launch.getLaunchConfiguration();
+ if (cfg != null) {
+ label.append( cfg.getName() );
+ } else {
+ label.append("?");
}
+
+ String peer_name = launch.getPeerName();
+ if (peer_name != null) {
+ label.append(" (");
+ label.append(peer_name);
+ label.append(")");
+ }
+
+ result.setLabel(label.toString(), 0);
+ result.done();
}
- String name = "?";
- ILaunchConfiguration cfg = launch.getLaunchConfiguration();
- if (cfg != null) name = cfg.getName();
- result.setLabel(name + status, 0);
- result.done();
- }
+ });
+
}
+
}
diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFChildrenContextQuery.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFChildrenContextQuery.java
index 4e3a65e..506266f 100644
--- a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFChildrenContextQuery.java
+++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFChildrenContextQuery.java
@@ -66,8 +66,8 @@ public class TCFChildrenContextQuery extends TCFChildren {
if (isValid()) return true; // error creating a node
TCFNode n = model.getNode(id);
while (n != null) {
- if (n.parent == node) {
- set.add(id);
+ if (n.parent == node || (n.parent == null && !(node instanceof TCFNodeExecContext))) {
+ set.add(n.getID());
break;
}
n = n.parent;
diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFContextQueryDescendants.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFContextQueryDescendants.java
new file mode 100644
index 0000000..6a28389
--- /dev/null
+++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFContextQueryDescendants.java
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * Copyright (c) 2012 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.tcf.internal.debug.ui.model;
+
+import java.util.Arrays;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.eclipse.tcf.util.TCFDataCache;
+
+/**
+ * Cache item that contains children of the node.
+ * The list of children is filtered according to the context query and context filter.
+ * An element in the list either matches both query and filter,
+ * or it is an ancestor of a matching node.
+ */
+public class TCFContextQueryDescendants extends TCFDataCache<Set<String>> {
+
+ private final TCFNode node;
+
+ private String[] query_data;
+ private Set<String> filter;
+
+ TCFContextQueryDescendants(TCFNode node) {
+ super(node.getChannel());
+ this.node = node;
+ }
+
+ public boolean setQuery(String query, Set<String> filter, Runnable done) {
+ String[] query_data = null;
+ TCFDataCache<String[]> query_cache = node.getModel().getLaunch().getContextQuery(query);
+ if (query_cache != null) {
+ if (!query_cache.validate(done)) return false;
+ query_data = query_cache.getData();
+ }
+ if (!Arrays.equals(query_data, this.query_data)) reset();
+ this.query_data = query_data;
+ if (this.filter == filter) return true;
+ if (filter != null && filter.equals(this.filter)) return true;
+ this.filter = filter;
+ reset();
+ return true;
+ }
+
+ private boolean getDescendants(Set<String> descendants, String[] ids) {
+ TCFModel model = node.getModel();
+ for (String id : ids) {
+ if (!model.createNode(id, this)) return false;
+ if (isValid()) return true; // error creating a node
+ TCFNode n = model.getNode(id);
+ while (n != null) {
+ if ( n.parent == node || (n.parent == null && !(node instanceof TCFNodeExecContext)) ) {
+ descendants.add(id);
+ break;
+ }
+ n = n.parent;
+ }
+ }
+ return true;
+ }
+
+
+ @Override
+ protected boolean startDataRetrieval() {
+ Set<String> set = new TreeSet<String>();
+ if (query_data != null && !getDescendants(set, query_data)) return false;
+ if (isValid()) return true; // error creating a node
+ if (filter != null) {
+ Set<String> filtered = new TreeSet<String>();
+ if (!getDescendants(filtered, filter.toArray(new String[filter.size()]))) return false;
+ set.retainAll(filtered);
+ }
+ if (isValid()) return true; // error creating a node
+ set(null, null, set);
+ return true;
+ }
+}
diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFModel.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFModel.java
index 4fc7d41..7afef67 100644
--- a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFModel.java
+++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFModel.java
@@ -11,6 +11,7 @@
package org.eclipse.tcf.internal.debug.ui.model;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
@@ -18,6 +19,8 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.DebugPlugin;
@@ -84,6 +87,8 @@ import org.eclipse.swt.graphics.Device;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;
+import org.eclipse.tcf.core.Command;
+import org.eclipse.tcf.debug.ui.ITCFSourceDisplay;
import org.eclipse.tcf.internal.debug.actions.TCFAction;
import org.eclipse.tcf.internal.debug.launch.TCFSourceLookupDirector;
import org.eclipse.tcf.internal.debug.launch.TCFSourceLookupParticipant;
@@ -106,13 +111,12 @@ import org.eclipse.tcf.internal.debug.ui.commands.StepReturnCommand;
import org.eclipse.tcf.internal.debug.ui.commands.SuspendCommand;
import org.eclipse.tcf.internal.debug.ui.commands.TerminateCommand;
import org.eclipse.tcf.internal.debug.ui.preferences.TCFPreferences;
-import org.eclipse.tcf.core.Command;
-import org.eclipse.tcf.debug.ui.ITCFSourceDisplay;
import org.eclipse.tcf.protocol.IChannel;
import org.eclipse.tcf.protocol.IErrorReport;
import org.eclipse.tcf.protocol.IService;
import org.eclipse.tcf.protocol.IToken;
import org.eclipse.tcf.protocol.Protocol;
+import org.eclipse.tcf.services.IContextQuery;
import org.eclipse.tcf.services.IDisassembly;
import org.eclipse.tcf.services.ILineNumbers;
import org.eclipse.tcf.services.IMemory;
@@ -304,7 +308,6 @@ public class TCFModel implements IElementContentProvider, IElementLabelProvider,
new HashMap<ILaunchConfiguration,IEditorInput>();
private final IModelSelectionPolicyFactory model_selection_factory = new IModelSelectionPolicyFactory() {
-
public IModelSelectionPolicy createModelSelectionPolicyAdapter(
Object element, IPresentationContext context) {
return selection_policy;
@@ -317,6 +320,34 @@ public class TCFModel implements IElementContentProvider, IElementLabelProvider,
private TCFNodeLaunch launch_node;
private boolean disposed;
+ private Map<String, TCFDataCache<Set<String>>> context_queries = new TreeMap<String, TCFDataCache<Set<String>>>();
+
+ public TCFDataCache<Set<String>> getContextQuery(final String query) {
+ TCFDataCache<Set<String>> data = context_queries.get(query);
+ if (data == null) {
+ data = new TCFDataCache<Set<String>>(channel) {
+ @Override
+ protected boolean startDataRetrieval() {
+ assert command == null;
+ IContextQuery service = channel.getRemoteService(IContextQuery.class);
+ if (service == null) {
+ set(null, null, null);
+ return true;
+ }
+
+ command = service.query(query, new IContextQuery.DoneQuery() {
+ public void doneQuery (IToken token, Exception error, String[] contexts) {
+ set( token, error, new TreeSet<String>(Arrays.asList(contexts)) );
+ }
+ });
+ return false;
+ }
+ };
+ context_queries.put(query, data);
+ }
+ return data;
+ }
+
private final IMemory.MemoryListener mem_listener = new IMemory.MemoryListener() {
public void contextAdded(IMemory.MemoryContext[] contexts) {
@@ -402,6 +433,7 @@ public class TCFModel implements IElementContentProvider, IElementLabelProvider,
}
public void contextAdded(IRunControl.RunControlContext[] contexts) {
+ onContextAdded();
for (IRunControl.RunControlContext ctx : contexts) {
String id = ctx.getParentID();
if (id == null) {
@@ -891,6 +923,13 @@ public class TCFModel implements IElementContentProvider, IElementLabelProvider,
model_proxies.remove(ctx);
}
+ private void onContextAdded() {
+ for (TCFDataCache<?> query : context_queries.values()) {
+ query.reset();
+ }
+ context_queries.clear();
+ }
+
private void onContextRemoved(String[] context_ids) {
for (String id : context_ids) {
TCFNode node = getNode(id);
@@ -904,6 +943,17 @@ public class TCFModel implements IElementContentProvider, IElementLabelProvider,
expanded_nodes.remove(id);
if (mem_blocks_update != null) mem_blocks_update.changeset.remove(id);
}
+
+ List<String> context_ids_list = Arrays.asList(context_ids);
+ for (TCFDataCache<Set<String>> query : context_queries.values()) {
+ if (query.isValid() && query.getError() == null) {
+ Set<String> query_contexts = query.getData();
+ query_contexts.removeAll(context_ids_list);
+ query.reset(query_contexts);
+ }
+ }
+ context_queries.clear();
+
launch_node.onAnyContextAddedOrRemoved();
// Close debug session if the last context is removed:
onContextOrProcessRemoved();
diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFNodeExecContext.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFNodeExecContext.java
index 257d134..bc3b6c3 100644
--- a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFNodeExecContext.java
+++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFNodeExecContext.java
@@ -12,6 +12,7 @@ package org.eclipse.tcf.internal.debug.ui.model;
import java.math.BigInteger;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
@@ -52,6 +53,7 @@ import org.eclipse.ui.IWorkbenchPart;
public class TCFNodeExecContext extends TCFNode implements ISymbolOwner {
private final TCFChildrenExecContext children_exec;
+ private final TCFContextQueryDescendants query_descendants;
private final TCFChildrenStackTrace children_stack;
private final TCFChildrenRegisters children_regs;
private final TCFChildrenExpressions children_exps;
@@ -240,6 +242,7 @@ public class TCFNodeExecContext extends TCFNode implements ISymbolOwner {
children_log_exps = new TCFChildrenLogExpressions(this);
children_modules = new TCFChildrenModules(this);
children_query = new TCFChildrenContextQuery(this, children_exec);
+ query_descendants = new TCFContextQueryDescendants(this);
mem_context = new TCFData<IMemory.MemoryContext>(channel) {
@Override
protected boolean startDataRetrieval() {
@@ -782,6 +785,44 @@ public class TCFNodeExecContext extends TCFNode implements ISymbolOwner {
public TCFChildren getChildren() {
return children_exec;
}
+
+// public TCFQueryChildrenExecContext getQueryChildren(String query, Set<String> contexts) {
+// class QueryChildrenKey {
+// private final String fQuery;
+// private Set<String> fContexts;
+//
+// QueryChildrenKey(String query, Set<String> contexts) {
+// fQuery = query;
+// fContexts = contexts;
+// }
+//
+// @Override
+// public boolean equals(Object other) {
+// if (other instanceof QueryChildrenKey) {
+// QueryChildrenKey element = (QueryChildrenKey)other;
+// return ((fQuery == null && element.fQuery == null) ||
+// (fQuery != null && fQuery.equals(element.fQuery))) &&
+// ((fContexts == null && element.fContexts == null) ||
+// (fContexts != null && fContexts.equals(element.fContexts)));
+// }
+// return false;
+// }
+//
+// @Override
+// public int hashCode() {
+// return (fQuery != null ? fQuery.hashCode() : 0) + (fContexts != null ? fContexts.hashCode() : 0);
+// }
+//
+// }
+//
+// QueryChildrenKey key = new QueryChildrenKey(query, contexts);
+// TCFQueryChildrenExecContext children = query_children_exec_map.get(key);
+// if (children ==null) {
+// children = new TCFQueryChildrenExecContext(this, children_exec, query, contexts);
+// query_children_exec_map.put(key, children);
+// }
+// return children;
+// }
public TCFNodeStackFrame getLastTopFrame() {
if (!resume_pending) return null;
@@ -842,7 +883,7 @@ public class TCFNodeExecContext extends TCFNode implements ISymbolOwner {
IPresentationContext context = result.getPresentationContext();
String query = (String)context.getProperty(ITCFDebugUIConstants.PROP_CONTEXT_QUERY);
Set<String> filter = (Set<String>)context.getProperty(ITCFDebugUIConstants.PROP_FILTER_CONTEXTS);
- return children_query.setQuery(query, filter, done);
+ return children_query.setQuery(query, model.getLaunch().getModelContexts(filter), done);
}
@Override
@@ -1053,7 +1094,14 @@ public class TCFNodeExecContext extends TCFNode implements ISymbolOwner {
@Override
protected boolean getData(ILabelUpdate result, Runnable done) {
- result.getViewerInput();
+ if ( ITCFDebugUIConstants.ID_CONTEXT_QUERY_VIEW.equals(result.getPresentationContext().getId()) ) {
+ return getContextQueryViewData(result, done);
+ } else {
+ return getDebugViewData(result, done);
+ }
+ }
+
+ private boolean getDebugViewData(ILabelUpdate result, Runnable done) {
if (!run_context.validate(done)) return false;
String image_name = null;
boolean suspended_by_bp = false;
@@ -1093,7 +1141,7 @@ public class TCFNodeExecContext extends TCFNode implements ISymbolOwner {
if (state_data.isReversing()) {
image_name = ImageCache.IMG_THREAD_REVERSING;
label.append(" (Reversing)");
- }
+ }
else {
image_name = ImageCache.IMG_THREAD_RUNNNIG;
label.append(" (Running)");
@@ -1187,6 +1235,74 @@ public class TCFNodeExecContext extends TCFNode implements ISymbolOwner {
return true;
}
+ private boolean getContextQueryViewData(ILabelUpdate result, Runnable done) {
+ if (!run_context.validate(done)) return false;
+ String image_name = null;
+ StringBuffer label = new StringBuffer();
+ Throwable error = run_context.getError();
+ if (error != null) {
+ result.setForeground(new RGB(255, 0, 0), 0);
+ label.append(id);
+ label.append(": ");
+ label.append(TCFModel.getErrorMessage(error, false));
+ }
+ else {
+ String query = (String)result.getPresentationContext().getProperty(ITCFDebugUIConstants.PROP_CONTEXT_QUERY);
+ @SuppressWarnings("unchecked")
+ Set<String> contexts = (Set<String>)result.getPresentationContext().getProperty(ITCFDebugUIConstants.PROP_FILTER_CONTEXTS);
+ if (contexts != null) contexts = model.getLaunch().getModelContexts(contexts);
+ if (!query_descendants.setQuery(query, contexts, done)) return false;
+ if (!query_descendants.validate(done)) return false;
+ if (query_descendants.getError() == null) {
+ Set<String> descendants = query_descendants.getData();
+ if (descendants != null && !descendants.isEmpty()) {
+ label.append("(");
+ label.append(descendants.size());
+ label.append(") ");
+ }
+ }
+
+ TCFDataCache<String[]> query_data = model.getLaunch().getContextQuery(query);
+ if (!query_data.validate(done)) return false;
+ if ( (query_data.getData() != null && !Arrays.asList(query_data.getData()).contains(getID())) ||
+ (contexts != null && !contexts.contains(getID())) )
+ {
+ result.setForeground(new RGB(128, 128, 128), 0);
+ }
+
+ IRunControl.RunControlContext ctx = run_context.getData();
+ if (ctx == null) {
+ label.append(id);
+ }
+ else {
+ String nm = ctx.getName();
+ if (nm == null && !ctx.hasState()) {
+ String prs = ctx.getProcessID();
+ if (prs != null) {
+ if (!prs_context.validate(done)) return false;
+ IProcesses.ProcessContext pctx = prs_context.getData();
+ if (pctx != null) nm = pctx.getName();
+ }
+ }
+ label.append(nm != null ? nm : id);
+ Object info = ctx.getProperties().get("AdditionalInfo");
+ if (info != null) label.append(info.toString());
+ if (ctx.hasState()) {
+ image_name = ImageCache.IMG_THREAD_UNKNOWN_STATE;
+ }
+ else {
+ // Thread container (process)
+ image_name = ImageCache.IMG_PROCESS_RUNNING;
+
+ }
+ }
+ }
+
+ result.setImageDescriptor(ImageCache.getImageDescriptor(image_name), 0);
+ result.setLabel(label.toString(), 0);
+ return true;
+ }
+
@Override
protected boolean getData(IViewerInputUpdate result, Runnable done) {
result.setInputElement(this);
@@ -1244,9 +1360,12 @@ public class TCFNodeExecContext extends TCFNode implements ISymbolOwner {
}
}
for (TCFModelProxy p : model.getModelProxies()) {
- if (IDebugUIConstants.ID_DEBUG_VIEW.equals(p.getPresentationContext().getId())) {
+ String view_id = p.getPresentationContext().getId();
+ if (IDebugUIConstants.ID_DEBUG_VIEW.equals(view_id)) {
/* Note: should use IModelDelta.INSERTED but it is broken in Eclipse 3.6 */
p.addDelta(this, IModelDelta.ADDED);
+ } else if (ITCFDebugUIConstants.ID_CONTEXT_QUERY_VIEW.equals(view_id)) {
+ p.addDelta(parent, IModelDelta.CONTENT);
}
}
}
@@ -1268,8 +1387,11 @@ public class TCFNodeExecContext extends TCFNode implements ISymbolOwner {
}
}
for (TCFModelProxy p : model.getModelProxies()) {
- if (IDebugUIConstants.ID_DEBUG_VIEW.equals(p.getPresentationContext().getId())) {
+ String view_id = p.getPresentationContext().getId();
+ if (IDebugUIConstants.ID_DEBUG_VIEW.equals(view_id)) {
p.addDelta(this, IModelDelta.REMOVED);
+ } else if (ITCFDebugUIConstants.ID_CONTEXT_QUERY_VIEW.equals(view_id)) {
+ p.addDelta(parent, IModelDelta.CONTENT);
}
}
}
@@ -1279,9 +1401,10 @@ public class TCFNodeExecContext extends TCFNode implements ISymbolOwner {
for (TCFModelProxy p : model.getModelProxies()) {
int flags = 0;
String view_id = p.getPresentationContext().getId();
- if (IDebugUIConstants.ID_DEBUG_VIEW.equals(view_id) &&
- (launch.getContextActionsCount(id) == 0 ||
- !model.getDelayStackUpdateUtilLastStep())) {
+ if ( (IDebugUIConstants.ID_DEBUG_VIEW.equals(view_id) ||
+ ITCFDebugUIConstants.ID_CONTEXT_QUERY_VIEW.equals(view_id)) &&
+ (launch.getContextActionsCount(id) == 0 || !model.getDelayStackUpdateUtilLastStep()))
+ {
flags |= IModelDelta.CONTENT;
}
if (IDebugUIConstants.ID_REGISTER_VIEW.equals(view_id) ||
@@ -1331,6 +1454,7 @@ public class TCFNodeExecContext extends TCFNode implements ISymbolOwner {
void onContextAdded(IRunControl.RunControlContext context) {
children_exec.onContextAdded(context);
+ children_query.reset();
}
void onContextChanged(IRunControl.RunControlContext context) {
@@ -1348,6 +1472,7 @@ public class TCFNodeExecContext extends TCFNode implements ISymbolOwner {
children_stack.onSourceMappingChange();
children_regs.reset();
children_exec.onAncestorContextChanged();
+ children_query.reset();
for (TCFNodeSymbol s : symbols.values()) s.onMemoryMapChanged();
postAllChangedDelta();
}
@@ -1376,6 +1501,7 @@ public class TCFNodeExecContext extends TCFNode implements ISymbolOwner {
dispose();
postContextRemovedDelta();
launch.removeContextActions(id);
+ children_query.reset();
}
void onExpressionAddedOrRemoved() {
diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFNodeLaunch.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFNodeLaunch.java
index 66448f6..1f7da09 100644
--- a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFNodeLaunch.java
+++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFNodeLaunch.java
@@ -29,13 +29,16 @@ import org.eclipse.tcf.services.IRunControl;
public class TCFNodeLaunch extends TCFNode implements ISymbolOwner {
private final TCFChildrenExecContext children;
+
private final TCFChildren filtered_children;
private final TCFChildrenContextQuery children_query;
+ private final TCFContextQueryDescendants query_descendants_count;
private final Map<String,TCFNodeSymbol> symbols = new HashMap<String,TCFNodeSymbol>();
TCFNodeLaunch(final TCFModel model) {
super(model);
children = new TCFChildrenExecContext(this);
+ query_descendants_count = new TCFContextQueryDescendants(this);
filtered_children = new TCFChildren(this) {
@Override
protected boolean startDataRetrieval() {
@@ -65,7 +68,7 @@ public class TCFNodeLaunch extends TCFNode implements ISymbolOwner {
super.dispose();
}
};
- children_query = new TCFChildrenContextQuery(this, filtered_children);
+ children_query = new TCFChildrenContextQuery(this, children);
}
@Override
@@ -81,7 +84,8 @@ public class TCFNodeLaunch extends TCFNode implements ISymbolOwner {
IPresentationContext context = result.getPresentationContext();
String query = (String)context.getProperty(ITCFDebugUIConstants.PROP_CONTEXT_QUERY);
Set<String> filter = (Set<String>)context.getProperty(ITCFDebugUIConstants.PROP_FILTER_CONTEXTS);
- return children_query.setQuery(query, filter, done);
+ return children_query.setQuery(query, model.getLaunch().getModelContexts(filter), done) &&
+ children_query.validate(done);
}
@Override
@@ -162,6 +166,8 @@ public class TCFNodeLaunch extends TCFNode implements ISymbolOwner {
void onAnyContextAddedOrRemoved() {
filtered_children.reset();
+ children_query.reset();
+ query_descendants_count.reset();
}
public void addSymbol(TCFNodeSymbol s) {
@@ -181,4 +187,9 @@ public class TCFNodeLaunch extends TCFNode implements ISymbolOwner {
public TCFChildren getFilteredChildren() {
return filtered_children;
}
+
+ public TCFContextQueryDescendants getContextQueryDescendants() {
+ return query_descendants_count;
+ }
+
}
diff --git a/plugins/org.eclipse.tcf.debug/src/org/eclipse/tcf/internal/debug/model/TCFLaunch.java b/plugins/org.eclipse.tcf.debug/src/org/eclipse/tcf/internal/debug/model/TCFLaunch.java
index 958c8fb..31e4e3a 100644
--- a/plugins/org.eclipse.tcf.debug/src/org/eclipse/tcf/internal/debug/model/TCFLaunch.java
+++ b/plugins/org.eclipse.tcf.debug/src/org/eclipse/tcf/internal/debug/model/TCFLaunch.java
@@ -22,6 +22,7 @@ import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;
+import java.util.TreeSet;
import org.eclipse.core.resources.IStorage;
import org.eclipse.core.runtime.CoreException;
@@ -1229,6 +1230,27 @@ public class TCFLaunch extends Launch {
return cache;
}
+ public Set<String> getModelContexts(Set<String> contexts) {
+ if (contexts != null) {
+ ILaunchConfiguration launchConfig = getLaunchConfiguration();
+ if (launchConfig != null) {
+ Set<String> modelContexts = new TreeSet<String>();
+ String sessionId = launchConfig.getName();
+ for (String context : contexts) {
+ int slashPos = context.indexOf('/');
+ if (slashPos > 0 && context.length() > slashPos + 1) {
+ if ( sessionId.equals(context.substring(0, slashPos)) ) {
+ modelContexts.add(context.substring(slashPos + 1));
+ }
+ }
+ }
+ return modelContexts;
+ }
+ }
+ return null;
+ }
+
+
/**
* Activate TCF launch: open communication channel and perform all necessary launch steps.
* @param mode - on of launch mode constants defined in ILaunchManager.
diff --git a/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/BreakpointDetailPaneTest.java b/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/BreakpointDetailPaneTest.java
new file mode 100644
index 0000000..b27dd96
--- /dev/null
+++ b/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/BreakpointDetailPaneTest.java
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * Copyright (c) 2012 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.tcf.debug.test;
+
+import java.util.regex.Pattern;
+
+import org.eclipse.debug.internal.ui.viewers.model.provisional.PresentationContext;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.VirtualItem;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.VirtualTreeModelViewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.tcf.debug.ui.ITCFDebugUIConstants;
+import org.eclipse.tcf.internal.cdt.ui.breakpoints.TCFBreakpointScopeDetailPane.ContextQueryElement;
+import org.eclipse.tcf.internal.cdt.ui.breakpoints.TCFBreakpointScopeDetailPane.ScopeDetailInputObject;
+import org.eclipse.tcf.internal.debug.ui.launch.TCFLaunchContext;
+import org.junit.Assert;
+
+@SuppressWarnings("restriction")
+public class BreakpointDetailPaneTest extends AbstractTcfUITest
+{
+ private BreakpointsListener fBpListener;
+
+ protected VirtualTreeModelViewer fContextQueryViewViewer;
+ protected VirtualViewerUpdatesListener fContextQueryViewListener;
+
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ fBpListener = new BreakpointsListener();
+
+ // CDT Breakpoint integration depends on the TCF-CDT breakpoint
+ // integration to be active. This is normally triggered by selecting
+ // a stack frame in the UI. Here force activation of the plugin
+ // artificially. None of the cdt integration packages are exported, so
+ // use the TCF Launch Context extension point indirectly to force the
+ // plugin to load.
+ TCFLaunchContext.getLaunchContext(null);
+
+ final Display display = Display.getDefault();
+ display.syncExec(new Runnable() {
+ public void run() {
+ fContextQueryViewViewer = new VirtualTreeModelViewer(
+ display, SWT.NONE, new PresentationContext(ITCFDebugUIConstants.ID_CONTEXT_QUERY_VIEW));
+ fContextQueryViewListener = new VirtualViewerUpdatesListener(fContextQueryViewViewer);
+ }
+ });
+
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ final Display display = Display.getDefault();
+ display.syncExec(new Runnable() {
+ public void run() {
+ fContextQueryViewListener.dispose();
+ fContextQueryViewViewer.dispose();
+ }
+ });
+ fBpListener.dispose();
+ super.tearDown();
+ }
+
+ public void testContextAddedOnLineBrakpointCreate() throws Exception {
+ initProcessModel("tcf_test_func0");
+
+ final String query = "pid="+fProcessId;
+
+ fContextQueryViewListener.reset();
+ Display.getDefault().syncExec(new Runnable() { public void run() {
+ fContextQueryViewViewer.setAutoExpandLevel(-1);
+ fContextQueryViewViewer.setInput(new ScopeDetailInputObject(new ContextQueryElement(query, null)));
+ }});
+ fContextQueryViewListener.waitTillFinished(CONTENT_SEQUENCE_COMPLETE | LABEL_UPDATES_RUNNING);
+
+ VirtualItem scopeItem = fContextQueryViewListener.findElement(new Pattern[] { Pattern.compile(".*pid\\="+fProcessId+"*.") });
+ if (scopeItem == null) {
+ Assert.fail("Scope item not found. \n\nContext query view dump: \n:" + fContextQueryViewViewer.toString());
+ }
+
+ }
+
+}