diff --git a/debug/org.eclipse.cdt.debug.core/META-INF/MANIFEST.MF b/debug/org.eclipse.cdt.debug.core/META-INF/MANIFEST.MF
index b7fb53ca013..1da89911883 100644
--- a/debug/org.eclipse.cdt.debug.core/META-INF/MANIFEST.MF
+++ b/debug/org.eclipse.cdt.debug.core/META-INF/MANIFEST.MF
@@ -16,7 +16,7 @@ Export-Package: org.eclipse.cdt.debug.core,
org.eclipse.cdt.debug.core.executables,
org.eclipse.cdt.debug.core.model,
org.eclipse.cdt.debug.core.sourcelookup,
- org.eclipse.cdt.debug.internal.core;x-internal:=true,
+ org.eclipse.cdt.debug.internal.core;x-friends:="org.eclipse.cdt.dsf.gdb.ui",
org.eclipse.cdt.debug.internal.core.breakpoints;x-friends:="org.eclipse.cdt.debug.edc",
org.eclipse.cdt.debug.internal.core.executables;x-internal:=true,
org.eclipse.cdt.debug.internal.core.model;x-internal:=true,
diff --git a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/CRequest.java b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/CRequest.java
new file mode 100644
index 00000000000..7b5c299743a
--- /dev/null
+++ b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/CRequest.java
@@ -0,0 +1,48 @@
+package org.eclipse.cdt.debug.internal.core;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.debug.core.IRequest;
+
+/**
+ * Base class for request objects used in asynchronous calls in base CDT
+ * (non-DSF). This is used in base features that delegate a task to a backend
+ * that is either DSF or CDI. Since DSF is highly asynchronous, the base logic
+ * has to use asynchronous APIs.
+ */
+public class CRequest implements IRequest {
+ private IStatus fStatus;
+ private boolean fCanceled;
+ /*
+ * @see org.eclipse.debug.core.IRequest#cancel()
+ */
+ public void cancel() {
+ fCanceled= true;
+ }
+
+ /*
+ * @see org.eclipse.debug.core.IRequest#done()
+ */
+ public void done() {
+ }
+
+ /*
+ * @see org.eclipse.debug.core.IRequest#getStatus()
+ */
+ public IStatus getStatus() {
+ return fStatus;
+ }
+
+ /*
+ * @see org.eclipse.debug.core.IRequest#isCanceled()
+ */
+ public boolean isCanceled() {
+ return fCanceled;
+ }
+
+ /*
+ * @see org.eclipse.debug.core.IRequest#setStatus(org.eclipse.core.runtime.IStatus)
+ */
+ public void setStatus(IStatus status) {
+ fStatus= status;
+ }
+}
diff --git a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/ICWatchpointTarget.java b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/ICWatchpointTarget.java
new file mode 100644
index 00000000000..2f62f3e6fbe
--- /dev/null
+++ b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/ICWatchpointTarget.java
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * Copyright (c) 2010 Freescale Semiconductor 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:
+ * Freescale Semiconductor - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.debug.internal.core;
+
+import org.eclipse.debug.core.IRequest;
+
+/**
+ * View model types for which the "Add Watchpoint (C/C++)" action is applicable
+ * should implement this interface. The action is a popupMenu/objectContribution
+ * that targets this type.
+ *
+ *
+ * Note that the action is particular to CBreakpoint, and not all CDT debugger
+ * solutions use CBreakpoint.
+ */
+public interface ICWatchpointTarget {
+
+ /** IRequest object used in the asynchronous method {@link ICWatchpointTarget#getSize()} */
+ interface GetSizeRequest extends IRequest {
+ int getSize();
+ void setSize(int size);
+ };
+
+ interface CanCreateWatchpointRequest extends IRequest {
+ boolean getCanCreate();
+ void setCanCreate(boolean value);
+ };
+
+ /**
+ * Determine if a watchpoint can be set on the element. The result does not
+ * guarantee an attempt to set such a watchpoint will succeed. This is
+ * merely a way to find out whether it makes sense to even attempt it. For
+ * example, an expression that's not an l-value should return false. The
+ * implementation may choose to go even further and check that the target
+ * supports watchpoints (at all or at that particular location).
+ */
+ void canSetWatchpoint(CanCreateWatchpointRequest request);
+
+ /**
+ * Get the expression or the name of the variable
+ */
+ String getExpression();
+
+ /**
+ * Asynchronous method to retrieve the size of the variable/expression, in
+ * bytes.
+ *
+ * @param request
+ * the async request object
+ */
+ void getSize(GetSizeRequest request);
+}
diff --git a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/model/CVariable.java b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/model/CVariable.java
index 08782f074e8..13a80a1773b 100644
--- a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/model/CVariable.java
+++ b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/model/CVariable.java
@@ -33,6 +33,7 @@ import org.eclipse.cdt.debug.core.model.ICDebugElementStatus;
import org.eclipse.cdt.debug.core.model.ICType;
import org.eclipse.cdt.debug.core.model.ICValue;
import org.eclipse.cdt.debug.internal.core.CSettingsManager;
+import org.eclipse.cdt.debug.internal.core.ICWatchpointTarget;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.DebugEvent;
import org.eclipse.debug.core.DebugException;
@@ -72,7 +73,7 @@ class VariableEventListener implements ICDIEventListener {
/**
* Represents a variable in the CDI model.
*/
-public abstract class CVariable extends AbstractCVariable implements ICDIEventListener {
+public abstract class CVariable extends AbstractCVariable implements ICDIEventListener, ICWatchpointTarget {
interface IInternalVariable {
IInternalVariable createShadow( int start, int length ) throws DebugException;
@@ -878,4 +879,33 @@ public abstract class CVariable extends AbstractCVariable implements ICDIEventLi
// even if the initial setup fails, we still want the complete creation to be successful
}
}
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.debug.internal.core.IWatchpointTarget#getExpression()
+ */
+ public String getExpression() {
+ try {
+ return getExpressionString();
+ } catch (DebugException e) {
+ return ""; //$NON-NLS-1$
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.debug.internal.core.IWatchpointTarget#getSize()
+ */
+ public void getSize(ICWatchpointTarget.GetSizeRequest request) {
+ // CDI has synchronous APIs, so this is easy...
+ request.setSize(sizeof());
+ request.done();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.debug.internal.core.IWatchpointTarget#canCreateWatchpoint(org.eclipse.cdt.debug.internal.core.IWatchpointTarget.CanCreateWatchpointRequest)
+ */
+ public void canSetWatchpoint(ICWatchpointTarget.CanCreateWatchpointRequest request) {
+ // CDI has synchronous APIs, so this is easy...
+ request.setCanCreate(sizeof() > 0);
+ request.done();
+ }
}
diff --git a/debug/org.eclipse.cdt.debug.ui/plugin.xml b/debug/org.eclipse.cdt.debug.ui/plugin.xml
index e04bbcae7e5..34e421d8d2b 100644
--- a/debug/org.eclipse.cdt.debug.ui/plugin.xml
+++ b/debug/org.eclipse.cdt.debug.ui/plugin.xml
@@ -723,6 +723,19 @@
id="org.eclipse.cdt.debug.ui.actions.method.ToggleMethodBreakpointAction">
+
+
+
+
@@ -808,20 +821,6 @@
class="org.eclipse.cdt.debug.core.model.ICVariable">
-
-
-
-
-
0 : "unexpected variale/expression size"; //$NON-NLS-1$
+ WorkbenchJob job = new WorkbenchJob("open watchpoint dialog") { //$NON-NLS-1$
+ @Override
+ public IStatus runInUIThread(IProgressMonitor monitor) {
+ AddWatchpointDialog dlg = new AddWatchpointDialog(CDebugUIPlugin.getActiveWorkbenchShell(),
+ getMemorySpaceManagement());
+ dlg.setExpression(expr);
+ dlg.initializeRange(false, Integer.toString(size));
+ if (dlg.open() == Window.OK) {
+ addWatchpoint(dlg.getWriteAccess(), dlg.getReadAccess(), dlg.getExpression(), dlg.getMemorySpace(), dlg.getRange());
+ }
+ return Status.OK_STATUS;
+ }
+ };
+ job.setSystem(true);
+ job.schedule();
+ }
+
+ };
+ fVar.getSize(request);
}
+ private class CanCreateWatchpointRequest extends CRequest implements ICWatchpointTarget.CanCreateWatchpointRequest {
+ boolean fCanCreate;
+ public boolean getCanCreate() {
+ return fCanCreate;
+ }
+ public void setCanCreate(boolean value) {
+ fCanCreate = value;
+ }
+ };
+
/**
- * @see IActionDelegate#selectionChanged(IAction, ISelection)
+ * Record the target variable/expression
+ *
+ * @see org.eclipse.ui.actions.ActionDelegate#selectionChanged(org.eclipse.jface.action.IAction,
+ * org.eclipse.jface.viewers.ISelection)
*/
- public void selectionChanged(IAction action, ISelection selection) {
+ public void selectionChanged(final IAction action, ISelection selection) {
if (selection == null || selection.isEmpty()) {
action.setEnabled(false);
return;
}
if (selection instanceof TreeSelection) {
Object obj = ((TreeSelection)selection).getFirstElement();
- if (obj != null && obj instanceof CVariable) {
- action.setEnabled(true);
- } else {
- action.setEnabled(false);
+ fVar = (ICWatchpointTarget)DebugPlugin.getAdapter(obj, ICWatchpointTarget.class);
+ if (fVar != null) {
+ final ICWatchpointTarget.CanCreateWatchpointRequest request = new CanCreateWatchpointRequest() {
+ public void done() {
+ action.setEnabled(getCanCreate());
+ }
+ };
+ fVar.canSetWatchpoint(request);
+ return;
}
+ assert false : "action should not have been available for object " + obj; //$NON-NLS-1$
}
+ else if (selection instanceof StructuredSelection) {
+ // Not sure why, but sometimes we get an extraneous empty StructuredSelection. Seems harmless enough
+ assert ((StructuredSelection)selection).getFirstElement() == null : "action installed in unexpected type of view/part"; //$NON-NLS-1$
+ }
+ else {
+ assert false : "action installed in unexpected type of view/part"; //$NON-NLS-1$
+ }
+ action.setEnabled(false);
}
-
- private IStructuredSelection getSelection() {
- return (IStructuredSelection)getView().getViewSite().getSelectionProvider().getSelection();
- }
-
}
diff --git a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/disassembly/dsf/DisassemblyBackendCdi.java b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/disassembly/dsf/DisassemblyBackendCdi.java
index d29506d830d..dd7c1504bf1 100644
--- a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/disassembly/dsf/DisassemblyBackendCdi.java
+++ b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/disassembly/dsf/DisassemblyBackendCdi.java
@@ -25,6 +25,7 @@ import org.eclipse.cdt.debug.core.model.ICThread;
import org.eclipse.cdt.debug.core.model.ICType;
import org.eclipse.cdt.debug.core.model.ICValue;
import org.eclipse.cdt.debug.core.model.IDisassemblyBlock;
+import org.eclipse.cdt.debug.internal.core.CRequest;
import org.eclipse.cdt.debug.internal.core.model.CDebugTarget;
import org.eclipse.cdt.debug.internal.core.model.CExpression;
import org.eclipse.cdt.debug.internal.core.model.CStackFrame;
@@ -179,6 +180,12 @@ public class DisassemblyBackendCdi implements IDisassemblyBackend, IDebugEventSe
fFrameLevel = 0;
}
+ private class AddressRequest extends CRequest implements IDisassemblyRetrieval.AddressRequest {
+ private BigInteger fAddress;
+ public BigInteger getAddress() { return fAddress; }
+ public void setAddress(BigInteger address) { fAddress = address; }
+ };
+
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.internal.ui.disassembly.dsf.IDisassemblyBackend#retrieveFrameAddress(int)
*/
@@ -190,7 +197,7 @@ public class DisassemblyBackendCdi implements IDisassemblyBackend, IDebugEventSe
return;
}
IStackFrame stackFrame= stackFrames[targetFrame];
- fDisassemblyRetrieval.asyncGetFrameAddress(stackFrame, new IDisassemblyRetrieval.AddressRequest() {
+ fDisassemblyRetrieval.asyncGetFrameAddress(stackFrame, new AddressRequest() {
@Override
public void done() {
fCallback.setUpdatePending(false);
@@ -238,6 +245,12 @@ public class DisassemblyBackendCdi implements IDisassemblyBackend, IDebugEventSe
return fTargetFrameContext.getFrameLineNumber();
}
+ private class DisassemblyRequest extends CRequest implements IDisassemblyRetrieval.DisassemblyRequest {
+ private IDisassemblyBlock fBlock;
+ public IDisassemblyBlock getDisassemblyBlock() { return fBlock; }
+ public void setDisassemblyBlock(IDisassemblyBlock block) { fBlock = block; }
+ };
+
/* (non-Javadoc)
* @see org.eclipse.cdt.dsf.debug.internal.ui.disassembly.IDisassemblyBackend#retrieveDisassembly(java.math.BigInteger, java.math.BigInteger, java.lang.String, boolean, boolean, boolean, int, int, int)
*/
@@ -253,7 +266,7 @@ public class DisassemblyBackendCdi implements IDisassemblyBackend, IDebugEventSe
endAddress= startAddress.add(addressLength);
}
final BigInteger finalEndAddress= endAddress;
- final IDisassemblyRetrieval.DisassemblyRequest disassemblyRequest= new IDisassemblyRetrieval.DisassemblyRequest() {
+ final IDisassemblyRetrieval.DisassemblyRequest disassemblyRequest= new DisassemblyRequest() {
@Override
public void done() {
if (!isCanceled() && getDisassemblyBlock() != null) {
@@ -365,7 +378,7 @@ public class DisassemblyBackendCdi implements IDisassemblyBackend, IDebugEventSe
public void retrieveDisassembly(String file, int lines,
BigInteger endAddress, final boolean mixed, final boolean showSymbols,
final boolean showDisassembly) {
- final IDisassemblyRetrieval.DisassemblyRequest disassemblyRequest= new IDisassemblyRetrieval.DisassemblyRequest() {
+ final IDisassemblyRetrieval.DisassemblyRequest disassemblyRequest= new DisassemblyRequest() {
@Override
public void done() {
if (!isCanceled() && getDisassemblyBlock() != null) {
diff --git a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/disassembly/dsf/IDisassemblyRetrieval.java b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/disassembly/dsf/IDisassemblyRetrieval.java
index 82eaa04689c..4508c9b39e4 100644
--- a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/disassembly/dsf/IDisassemblyRetrieval.java
+++ b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/disassembly/dsf/IDisassemblyRetrieval.java
@@ -14,89 +14,21 @@ package org.eclipse.cdt.debug.internal.ui.disassembly.dsf;
import java.math.BigInteger;
import org.eclipse.cdt.debug.core.model.IDisassemblyBlock;
-import org.eclipse.core.runtime.IStatus;
import org.eclipse.debug.core.IRequest;
import org.eclipse.debug.core.model.IStackFrame;
/**
*/
public interface IDisassemblyRetrieval {
- /**
- */
- public static class Request implements IRequest {
- private IStatus fStatus;
- private boolean fCanceled;
- /*
- * @see org.eclipse.debug.core.IRequest#cancel()
- */
- public void cancel() {
- fCanceled= true;
- }
-
- /*
- * @see org.eclipse.debug.core.IRequest#done()
- */
- public void done() {
- }
-
- /*
- * @see org.eclipse.debug.core.IRequest#getStatus()
- */
- public IStatus getStatus() {
- return fStatus;
- }
-
- /*
- * @see org.eclipse.debug.core.IRequest#isCanceled()
- */
- public boolean isCanceled() {
- return fCanceled;
- }
-
- /*
- * @see org.eclipse.debug.core.IRequest#setStatus(org.eclipse.core.runtime.IStatus)
- */
- public void setStatus(IStatus status) {
- fStatus= status;
- }
+ interface AddressRequest extends IRequest {
+ BigInteger getAddress();
+ void setAddress(BigInteger address);
}
- /**
- */
- public static class AddressRequest extends Request {
- private BigInteger fAddress;
- /**
- * @return the address
- */
- public BigInteger getAddress() {
- return fAddress;
- }
-
- /**
- * @param address the address to set
- */
- public void setAddress(BigInteger address) {
- fAddress= address;
- }
- }
-
- public static class DisassemblyRequest extends Request {
- IDisassemblyBlock fDisassemblyBlock;
-
- /**
- * @return the disassemblyBlock
- */
- public IDisassemblyBlock getDisassemblyBlock() {
- return fDisassemblyBlock;
- }
-
- /**
- * @param disassemblyBlock the disassemblyBlock to set
- */
- public void setDisassemblyBlock(IDisassemblyBlock disassemblyBlock) {
- fDisassemblyBlock= disassemblyBlock;
- }
+ interface DisassemblyRequest extends IRequest {
+ IDisassemblyBlock getDisassemblyBlock();
+ void setDisassemblyBlock(IDisassemblyBlock disassemblyBlock);
}
/**
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/GdbExpressionVMProvider.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/GdbExpressionVMProvider.java
new file mode 100644
index 00000000000..89de45a24ce
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/GdbExpressionVMProvider.java
@@ -0,0 +1,115 @@
+/*******************************************************************************
+ * Copyright (c) 2010 Freescale Semiconductor. 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:
+ * Freescale Semiconductor - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.internal.ui.viewmodel;
+
+import org.eclipse.cdt.dsf.debug.ui.IDsfDebugUIConstants;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.expression.ExpressionManagerVMNode;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.expression.ExpressionVMProvider;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.expression.IExpressionVMNode;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.expression.SingleExpressionVMNode;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.register.RegisterBitFieldVMNode;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.register.RegisterGroupVMNode;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.register.RegisterVMNode;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.register.SyncRegisterDataAccess;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.variable.SyncVariableDataAccess;
+import org.eclipse.cdt.dsf.service.DsfSession;
+import org.eclipse.cdt.dsf.ui.viewmodel.AbstractVMAdapter;
+import org.eclipse.cdt.dsf.ui.viewmodel.IRootVMNode;
+import org.eclipse.cdt.dsf.ui.viewmodel.IVMNode;
+import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.RootDMVMNode;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
+
+/**
+ * A specialization of ExpressionVMProvider that uses a GDB-specific variable VM
+ * node. To understand why this is necessary, see GdbVariableVMNode.
+ */
+public class GdbExpressionVMProvider extends ExpressionVMProvider {
+
+ /**
+ * Constructor (passthru)
+ */
+ public GdbExpressionVMProvider(AbstractVMAdapter adapter,
+ IPresentationContext context, DsfSession session) {
+ super(adapter, context, session);
+ }
+
+ /**
+ * The only difference between this and our super implementation is that we
+ * create a GdbVariableVMNode instead of a VariableVMNode.
+ *
+ * @see org.eclipse.cdt.dsf.debug.ui.viewmodel.expression.ExpressionVMProvider#configureLayout()
+ */
+ @Override
+ protected void configureLayout() {
+
+ /*
+ * Allocate the synchronous data providers.
+ */
+ SyncRegisterDataAccess syncRegDataAccess = new SyncRegisterDataAccess(getSession());
+ SyncVariableDataAccess syncvarDataAccess = new SyncVariableDataAccess(getSession()) ;
+
+ /*
+ * Create the top level node which provides the anchor starting point.
+ */
+ IRootVMNode rootNode = new RootDMVMNode(this);
+
+ /*
+ * Now the Over-arching management node.
+ */
+ if (IDsfDebugUIConstants.ID_EXPRESSION_HOVER.equals(getPresentationContext().getId())) {
+ SingleExpressionVMNode expressionManagerNode = new SingleExpressionVMNode(this);
+ addChildNodes(rootNode, new IVMNode[] { expressionManagerNode });
+ } else {
+ ExpressionManagerVMNode expressionManagerNode = new ExpressionManagerVMNode(this);
+ addChildNodes(rootNode, new IVMNode[] {expressionManagerNode});
+ }
+
+ /*
+ * The expression view wants to support fully all of the components of the register view.
+ */
+ IExpressionVMNode registerGroupNode = new RegisterGroupVMNode(this, getSession(), syncRegDataAccess);
+
+ IExpressionVMNode registerNode = new RegisterVMNode(this, getSession(), syncRegDataAccess);
+ addChildNodes(registerGroupNode, new IExpressionVMNode[] {registerNode});
+
+ /*
+ * Create the next level which is the bit-field level.
+ */
+ IVMNode bitFieldNode = new RegisterBitFieldVMNode(this, getSession(), syncRegDataAccess);
+ addChildNodes(registerNode, new IVMNode[] { bitFieldNode });
+
+ /*
+ * Create the support for the SubExpressions. Anything which is brought into the expressions
+ * view comes in as a fully qualified expression so we go directly to the SubExpression layout
+ * node.
+ */
+ IExpressionVMNode variableNode = new GdbVariableVMNode(this, getSession(), syncvarDataAccess);
+ addChildNodes(variableNode, new IExpressionVMNode[] {variableNode});
+
+ /*
+ * Tell the expression node which sub-nodes it will directly support. It is very important
+ * that the variables node be the last in this chain. The model assumes that there is some
+ * form of metalanguage expression syntax which each of the nodes evaluates and decides if
+ * they are dealing with it or not. The variables node assumes that the expression is fully
+ * qualified and there is no analysis or subdivision of the expression it will parse. So it
+ * it currently the case that the location of the nodes within the array being passed in is
+ * the order of search/evaluation. Thus variables wants to be last. Otherwise it would just
+ * assume what it was passed was for it and the real node which wants to handle it would be
+ * left out in the cold.
+ */
+ setExpressionNodes(new IExpressionVMNode[] {registerGroupNode, variableNode});
+
+ /*
+ * Let the work know which is the top level node.
+ */
+ setRootNode(rootNode);
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/GdbVariableVMNode.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/GdbVariableVMNode.java
new file mode 100644
index 00000000000..b05de8a1d2c
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/GdbVariableVMNode.java
@@ -0,0 +1,148 @@
+/*******************************************************************************
+ * Copyright (c) 2010 Freescale Semiconductor. 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:
+ * Freescale Semiconductor - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.internal.ui.viewmodel;
+
+import org.eclipse.cdt.debug.internal.core.ICWatchpointTarget;
+import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
+import org.eclipse.cdt.dsf.datamodel.DMContexts;
+import org.eclipse.cdt.dsf.datamodel.IDMContext;
+import org.eclipse.cdt.dsf.debug.service.IExpressions;
+import org.eclipse.cdt.dsf.debug.service.IExpressions.IExpressionDMAddress;
+import org.eclipse.cdt.dsf.debug.service.IExpressions.IExpressionDMContext;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.variable.SyncVariableDataAccess;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.variable.VariableVMNode;
+import org.eclipse.cdt.dsf.service.DsfSession;
+import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider;
+import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext;
+
+/**
+ * Specialization of DSF's VariableVMNode. See
+ * {@link GdbVariableVMNode#createVMContext(IDMContext)} for why this is needed.
+ */
+public class GdbVariableVMNode extends VariableVMNode {
+
+ /**
+ * Specialization of VariableVMNode.VariableExpressionVMC that participates
+ * in the "Add Watchpoint" object contribution action.
+ */
+ public class GdbVariableExpressionVMC extends VariableVMNode.VariableExpressionVMC implements ICWatchpointTarget {
+
+ /**
+ * Constructor (passthru)
+ */
+ public GdbVariableExpressionVMC(IDMContext dmc) {
+ super(dmc);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.debug.internal.core.IWatchpointTarget#getExpression()
+ */
+ public String getExpression() {
+ final IExpressionDMContext exprDmc = DMContexts.getAncestorOfType(getDMContext(), IExpressionDMContext.class);
+ if (exprDmc != null) {
+ return exprDmc.getExpression();
+ }
+
+ return ""; //$NON-NLS-1$
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.debug.internal.core.IWatchpointTarget#getSize()
+ */
+ public void getSize(final ICWatchpointTarget.GetSizeRequest request) {
+ final IExpressionDMContext exprDmc = DMContexts.getAncestorOfType(getDMContext(), IExpressionDMContext.class);
+ if (exprDmc != null) {
+ getSession().getExecutor().execute(new Runnable() {
+ public void run() {
+ final IExpressions expressionService = getServicesTracker().getService(IExpressions.class);
+ if (expressionService != null) {
+ final DataRequestMonitor drm = new DataRequestMonitor(getSession().getExecutor(), null) {
+ @Override
+ public void handleSuccess() {
+ request.setSize(getData().getSize());
+ request.done();
+ }
+ };
+
+ expressionService.getExpressionAddressData(exprDmc, drm);
+ }
+ }
+ });
+ }
+ else {
+ request.setSize(-1);
+ request.done();
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.debug.internal.core.IWatchpointTarget#canCreateWatchpoint(org.eclipse.cdt.debug.internal.core.IWatchpointTarget.CanCreateWatchpointRequest)
+ */
+ public void canSetWatchpoint(final ICWatchpointTarget.CanCreateWatchpointRequest request) {
+ // If the expression is an l-value, then we say it supports a
+ // watchpoint. The logic here is basically the same as what's in
+ // getSize(), as the same DSF service method tells us (a) if it's an
+ // lvalue, and (b) its size.
+ final IExpressionDMContext exprDmc = DMContexts.getAncestorOfType(getDMContext(), IExpressionDMContext.class);
+ if (exprDmc != null) {
+ getSession().getExecutor().execute(new Runnable() {
+ public void run() {
+ final IExpressions expressionService = getServicesTracker().getService(IExpressions.class);
+ if (expressionService != null) {
+ final DataRequestMonitor drm = new DataRequestMonitor(getSession().getExecutor(), null) {
+ @Override
+ public void handleCompleted() {
+ if (isSuccess()) {
+ assert getData().getSize() > 0;
+ request.setCanCreate(true);
+ }
+ else {
+ request.setCanCreate(false);
+ }
+ request.done();
+ }
+ };
+
+ expressionService.getExpressionAddressData(exprDmc, drm);
+ }
+ }
+ });
+ }
+ else {
+ request.setCanCreate(false);
+ request.done();
+ }
+ }
+
+ };
+
+ /**
+ * Constructor (passthru)
+ */
+ public GdbVariableVMNode(AbstractDMVMProvider provider, DsfSession session,
+ SyncVariableDataAccess syncVariableDataAccess) {
+ super(provider, session, syncVariableDataAccess);
+ }
+
+ /**
+ * The primary reason for the specialization of VariableVMNode is to create
+ * a GDB-specific VM context that implements ICWatchpointTarget, so that the
+ * "Add Watchpoint" context menu appears for variables and expressions in
+ * GDB-DSF sessions but not necessarily other DSF-based sessions [bugzilla
+ * 248606]
+ *
+ * @see org.eclipse.cdt.dsf.debug.ui.viewmodel.variable.VariableVMNode#createVMContext(org.eclipse.cdt.dsf.datamodel.IDMContext)
+ */
+ @Override
+ protected IDMVMContext createVMContext(IDMContext dmc) {
+ return new GdbVariableExpressionVMC(dmc);
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/GdbVariableVMProvider.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/GdbVariableVMProvider.java
new file mode 100644
index 00000000000..ac3e063c233
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/GdbVariableVMProvider.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2010 Freescale Semiconductor. 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:
+ * Freescale Semiconductor - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.internal.ui.viewmodel;
+
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.variable.SyncVariableDataAccess;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.variable.VariableVMProvider;
+import org.eclipse.cdt.dsf.service.DsfSession;
+import org.eclipse.cdt.dsf.ui.viewmodel.AbstractVMAdapter;
+import org.eclipse.cdt.dsf.ui.viewmodel.IRootVMNode;
+import org.eclipse.cdt.dsf.ui.viewmodel.IVMNode;
+import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.RootDMVMNode;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
+
+/**
+ * A specialization of VariableVMProvider that uses a GDB-specific variable VM
+ * node. To understand why this is necessary, see GdbVariableVMNode.
+ */
+public class GdbVariableVMProvider extends VariableVMProvider {
+
+ /**
+ * Constructor (passthru)
+ */
+ public GdbVariableVMProvider(AbstractVMAdapter adapter,
+ IPresentationContext context, DsfSession session) {
+ super(adapter, context, session);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.dsf.debug.ui.viewmodel.variable.VariableVMProvider#configureLayout(org.eclipse.cdt.dsf.debug.ui.viewmodel.variable.SyncVariableDataAccess)
+ */
+ @Override
+ protected void configureLayout() {
+ // Create the variable data access routines.
+ SyncVariableDataAccess varAccess = new SyncVariableDataAccess(getSession()) ;
+
+ // Create the top level node to deal with the root selection.
+ IRootVMNode rootNode = new RootDMVMNode(this);
+ setRootNode(rootNode);
+
+ // Create the next level which represents members of structs/unions/enums and elements of arrays.
+ IVMNode subExpressioNode = new GdbVariableVMNode(this, getSession(), varAccess);
+ addChildNodes(rootNode, new IVMNode[] { subExpressioNode });
+
+ // Configure the sub-expression node to be a child of itself. This way the content
+ // provider will recursively drill-down the variable hierarchy.
+ addChildNodes(subExpressioNode, new IVMNode[] { subExpressioNode });
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/GdbViewModelAdapter.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/GdbViewModelAdapter.java
index 8b5a634b6d8..ecc15985b5b 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/GdbViewModelAdapter.java
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/GdbViewModelAdapter.java
@@ -13,10 +13,8 @@ package org.eclipse.cdt.dsf.gdb.internal.ui.viewmodel;
import org.eclipse.cdt.dsf.concurrent.ThreadSafe;
import org.eclipse.cdt.dsf.debug.ui.viewmodel.AbstractDebugVMAdapter;
import org.eclipse.cdt.dsf.debug.ui.viewmodel.SteppingController;
-import org.eclipse.cdt.dsf.debug.ui.viewmodel.expression.ExpressionVMProvider;
import org.eclipse.cdt.dsf.debug.ui.viewmodel.modules.ModulesVMProvider;
import org.eclipse.cdt.dsf.debug.ui.viewmodel.register.RegisterVMProvider;
-import org.eclipse.cdt.dsf.debug.ui.viewmodel.variable.VariableVMProvider;
import org.eclipse.cdt.dsf.gdb.internal.ui.viewmodel.breakpoints.GdbBreakpointVMProvider;
import org.eclipse.cdt.dsf.gdb.internal.ui.viewmodel.launch.LaunchVMProvider;
import org.eclipse.cdt.dsf.service.DsfSession;
@@ -47,11 +45,11 @@ public class GdbViewModelAdapter extends AbstractDebugVMAdapter
if ( IDebugUIConstants.ID_DEBUG_VIEW.equals(context.getId()) ) {
return new LaunchVMProvider(this, context, getSession());
} else if (IDebugUIConstants.ID_VARIABLE_VIEW.equals(context.getId()) ) {
- return new VariableVMProvider(this, context, getSession());
+ return new GdbVariableVMProvider(this, context, getSession());
} else if (IDebugUIConstants.ID_REGISTER_VIEW.equals(context.getId()) ) {
return new RegisterVMProvider(this, context, getSession());
} else if (IDebugUIConstants.ID_EXPRESSION_VIEW.equals(context.getId()) ) {
- return new ExpressionVMProvider(this, context, getSession());
+ return new GdbExpressionVMProvider(this, context, getSession());
} else if (IDebugUIConstants.ID_MODULE_VIEW.equals(context.getId()) ) {
return new ModulesVMProvider(this, context, getSession());
} else if (IDebugUIConstants.ID_BREAKPOINT_VIEW.equals(context.getId()) ) {
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/variable/VariableVMNode.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/variable/VariableVMNode.java
index afb15dad868..b1bdb4135af 100644
--- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/variable/VariableVMNode.java
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/variable/VariableVMNode.java
@@ -146,8 +146,8 @@ public class VariableVMNode extends AbstractExpressionVMNode
fExpression = expression;
}
- @Override
- @SuppressWarnings("rawtype")
+ @SuppressWarnings("rawtypes")
+ @Override
public Object getAdapter(Class adapter) {
if (fExpression != null && adapter.isAssignableFrom(fExpression.getClass())) {
return fExpression;
@@ -750,7 +750,7 @@ public class VariableVMNode extends AbstractExpressionVMNode
IExpressionDMContext expressionDMC = expressionService.createExpression(
createCompositeDMVMContext(update),
update.getExpression().getExpressionText());
- VariableExpressionVMC variableVmc = new VariableExpressionVMC(expressionDMC);
+ VariableExpressionVMC variableVmc = (VariableExpressionVMC)createVMContext(expressionDMC);
variableVmc.setExpression(update.getExpression());
update.setExpressionElement(variableVmc);
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/variable/VariableVMProvider.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/variable/VariableVMProvider.java
index 4935a08129e..37b4ca11ba5 100644
--- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/variable/VariableVMProvider.java
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/variable/VariableVMProvider.java
@@ -69,27 +69,8 @@ public class VariableVMProvider extends AbstractDMVMProvider
store.addPropertyChangeListener(fPreferencesListener);
setDelayEventHandleForViewUpdate(store.getBoolean(IDsfDebugUIConstants.PREF_WAIT_FOR_VIEW_UPDATE_AFTER_STEP_ENABLE));
- /*
- * Create the variable data access routines.
- */
- SyncVariableDataAccess varAccess = new SyncVariableDataAccess(session) ;
-
- /*
- * Create the top level node to deal with the root selection.
- */
- IRootVMNode rootNode = new RootDMVMNode(this);
- setRootNode(rootNode);
-
- /*
- * Create the next level which represents members of structs/unions/enums and elements of arrays.
- */
- IVMNode subExpressioNode = new VariableVMNode(this, getSession(), varAccess);
- addChildNodes(rootNode, new IVMNode[] { subExpressioNode });
-
- // Configure the sub-expression node to be a child of itself. This way the content
- // provider will recursively drill-down the variable hierarchy.
- addChildNodes(subExpressioNode, new IVMNode[] { subExpressioNode });
- }
+ configureLayout();
+ }
@Override
public void dispose() {
@@ -97,6 +78,30 @@ public class VariableVMProvider extends AbstractDMVMProvider
getPresentationContext().removePropertyChangeListener(fPresentationContextListener);
super.dispose();
}
+
+ /**
+ * Configures the nodes of this provider. This method may be over-ridden by
+ * sub classes to create an alternate configuration in this provider.
+ *
+ * @since 2.1
+ */
+ protected void configureLayout() {
+
+ // Create the variable data access routines.
+ SyncVariableDataAccess varAccess = new SyncVariableDataAccess(getSession()) ;
+
+ // Create the top level node to deal with the root selection.
+ IRootVMNode rootNode = new RootDMVMNode(this);
+ setRootNode(rootNode);
+
+ // Create the next level which represents members of structs/unions/enums and elements of arrays.
+ IVMNode subExpressioNode = new VariableVMNode(this, getSession(), varAccess);
+ addChildNodes(rootNode, new IVMNode[] { subExpressioNode });
+
+ // Configure the sub-expression node to be a child of itself. This way the content
+ // provider will recursively drill-down the variable hierarchy.
+ addChildNodes(subExpressioNode, new IVMNode[] { subExpressioNode });
+ }
@Override
public IColumnPresentation createColumnPresentation(IPresentationContext context, Object element) {