1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-07 09:46:02 +02:00

[248606] Add support for toggling watchpoints in the variables and expressions views.

This commit is contained in:
John Cortell 2010-02-19 23:47:04 +00:00
parent 63934dce7a
commit adde620eaf
14 changed files with 627 additions and 165 deletions

View file

@ -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,

View file

@ -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;
}
}

View file

@ -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.
*
* <p>
* 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);
}

View file

@ -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();
}
}

View file

@ -723,6 +723,19 @@
id="org.eclipse.cdt.debug.ui.actions.method.ToggleMethodBreakpointAction">
</action>
</objectContribution>
<objectContribution
objectClass="org.eclipse.cdt.debug.internal.core.ICWatchpointTarget"
id="org.eclipse.cdt.debug.ui.WatchpointActions">
<action
class="org.eclipse.cdt.debug.internal.ui.actions.AddWatchpointOnVariableActionDelegate"
enablesFor="1"
icon="icons/elcl16/watchpoint_co.gif"
id="org.eclipse.cdt.debug.internal.ui.actions.AddWatchpointOnVariableActionDelegate"
label="%AddWatchpoint.label"
menubarPath="additions"
tooltip="%AddWatchpoint.tooltip">
</action>
</objectContribution>
<objectContribution
objectClass="org.eclipse.cdt.core.model.IVariable"
id="org.eclipse.cdt.debug.ui.WatchpointActions">
@ -808,20 +821,6 @@
class="org.eclipse.cdt.debug.core.model.ICVariable">
</selection>
</action>
<action
class="org.eclipse.cdt.debug.internal.ui.actions.AddWatchpointOnVariableActionDelegate"
enablesFor="1"
icon="icons/elcl16/watchpoint_co.gif"
id="org.eclipse.cdt.debug.internal.ui.actions.AddWatchpointOnVariableActionDelegate"
label="%AddWatchpoint.label"
menubarPath="additions"
tooltip="%AddWatchpoint.tooltip">
<enablement>
<pluginState
value="activated"
id="org.eclipse.cdt.debug.ui"/>
</enablement>
</action>
</viewerContribution>
<viewerContribution
targetID="org.eclipse.debug.ui.RegisterView"

View file

@ -11,84 +11,142 @@
package org.eclipse.cdt.debug.internal.ui.actions;
import org.eclipse.cdt.debug.internal.core.model.CVariable;
import org.eclipse.cdt.debug.internal.ui.actions.AddWatchpointDialog;
import org.eclipse.cdt.debug.internal.core.CRequest;
import org.eclipse.cdt.debug.internal.core.ICWatchpointTarget;
import org.eclipse.cdt.debug.ui.CDebugUIPlugin;
import org.eclipse.debug.core.DebugException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeSelection;
import org.eclipse.jface.window.Window;
import org.eclipse.ui.IActionDelegate;
import org.eclipse.ui.IObjectActionDelegate;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.progress.WorkbenchJob;
public class AddWatchpointOnVariableActionDelegate extends AddWatchpointActionDelegate {
/**
* Invoked when user right clicks on an element in the Variables or Expressions
* view and selects 'Add Watchpoint (C/C++)'
*/
public class AddWatchpointOnVariableActionDelegate extends AddWatchpointActionDelegate implements IObjectActionDelegate {
/**
* Constructor for Action1.
* The target variable/expression
*/
private ICWatchpointTarget fVar;
/**
* Constructor
*/
public AddWatchpointOnVariableActionDelegate() {
super();
}
/**
* @see IObjectActionDelegate#setActivePart(IAction, IWorkbenchPart)
/* (non-Javadoc)
* @see org.eclipse.ui.IObjectActionDelegate#setActivePart(org.eclipse.jface.action.IAction, org.eclipse.ui.IWorkbenchPart)
*/
public void setActivePart(IAction action, IWorkbenchPart targetPart) {}
public void setActivePart(IAction action, IWorkbenchPart targetPart) {
// Don't care. Our logic is agnostic to the view we're invoked from.
}
/**
* @see IActionDelegate#run(IAction)
private static class GetSizeRequest extends CRequest implements ICWatchpointTarget.GetSizeRequest {
int fSize;
public int getSize() {
return fSize;
}
public void setSize(int size) {
fSize = size;
}
};
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.internal.ui.actions.AddWatchpointActionDelegate#run(org.eclipse.jface.action.IAction)
*/
public void run(IAction action) {
IStructuredSelection selection = getSelection();
if (selection == null || selection.isEmpty()) {
if (fVar == null) {
return;
}
Object obj = ((TreeSelection)selection).getFirstElement();
if (obj != null && obj instanceof CVariable) {
CVariable var = (CVariable)obj;
String expr = "";
try {
expr = var.getExpressionString();
} catch (DebugException e) {}
AddWatchpointDialog dlg = new AddWatchpointDialog(CDebugUIPlugin.getActiveWorkbenchShell(),
getMemorySpaceManagement()); //$NON-NLS-1$
dlg.setExpression(expr);
dlg.initializeRange(false, Integer.toString(var.sizeof()));
if (dlg.open() == Window.OK) {
addWatchpoint(dlg.getWriteAccess(), dlg.getReadAccess(), dlg.getExpression(), dlg.getMemorySpace(), dlg.getRange());
}
final String expr = fVar.getExpression();
if (expr == null) {
assert false : "how are we getting an empty expression?"; //$NON-NLS-1$
return;
}
// Getting the size of the variable/expression is an asynchronous
// operation...or at least the API is (the CDI implementation reacts
// synchronously)
final ICWatchpointTarget.GetSizeRequest request = new GetSizeRequest() {
public void done() {
// Now that we have the size, put up a dialog to create the watchpoint
final int size = getSize();
assert size > 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();
}
}

View file

@ -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) {

View file

@ -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);
}
/**

View file

@ -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);
}
}

View file

@ -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<IExpressionDMAddress> drm = new DataRequestMonitor<IExpressionDMAddress>(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<IExpressionDMAddress> drm = new DataRequestMonitor<IExpressionDMAddress>(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);
}
}

View file

@ -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 });
}
}

View file

@ -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()) ) {

View file

@ -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);

View file

@ -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) {