1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-07 17:56:01 +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.executables,
org.eclipse.cdt.debug.core.model, org.eclipse.cdt.debug.core.model,
org.eclipse.cdt.debug.core.sourcelookup, 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.breakpoints;x-friends:="org.eclipse.cdt.debug.edc",
org.eclipse.cdt.debug.internal.core.executables;x-internal:=true, org.eclipse.cdt.debug.internal.core.executables;x-internal:=true,
org.eclipse.cdt.debug.internal.core.model;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.ICType;
import org.eclipse.cdt.debug.core.model.ICValue; import org.eclipse.cdt.debug.core.model.ICValue;
import org.eclipse.cdt.debug.internal.core.CSettingsManager; 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.core.runtime.CoreException;
import org.eclipse.debug.core.DebugEvent; import org.eclipse.debug.core.DebugEvent;
import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.DebugException;
@ -72,7 +73,7 @@ class VariableEventListener implements ICDIEventListener {
/** /**
* Represents a variable in the CDI model. * 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 { interface IInternalVariable {
IInternalVariable createShadow( int start, int length ) throws DebugException; 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 // 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"> id="org.eclipse.cdt.debug.ui.actions.method.ToggleMethodBreakpointAction">
</action> </action>
</objectContribution> </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 <objectContribution
objectClass="org.eclipse.cdt.core.model.IVariable" objectClass="org.eclipse.cdt.core.model.IVariable"
id="org.eclipse.cdt.debug.ui.WatchpointActions"> id="org.eclipse.cdt.debug.ui.WatchpointActions">
@ -808,20 +821,6 @@
class="org.eclipse.cdt.debug.core.model.ICVariable"> class="org.eclipse.cdt.debug.core.model.ICVariable">
</selection> </selection>
</action> </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>
<viewerContribution <viewerContribution
targetID="org.eclipse.debug.ui.RegisterView" targetID="org.eclipse.debug.ui.RegisterView"

View file

@ -11,84 +11,142 @@
package org.eclipse.cdt.debug.internal.ui.actions; package org.eclipse.cdt.debug.internal.ui.actions;
import org.eclipse.cdt.debug.internal.core.model.CVariable; import org.eclipse.cdt.debug.internal.core.CRequest;
import org.eclipse.cdt.debug.internal.ui.actions.AddWatchpointDialog; import org.eclipse.cdt.debug.internal.core.ICWatchpointTarget;
import org.eclipse.cdt.debug.ui.CDebugUIPlugin; 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.action.IAction;
import org.eclipse.jface.viewers.ISelection; 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.viewers.TreeSelection;
import org.eclipse.jface.window.Window; import org.eclipse.jface.window.Window;
import org.eclipse.ui.IActionDelegate;
import org.eclipse.ui.IObjectActionDelegate; import org.eclipse.ui.IObjectActionDelegate;
import org.eclipse.ui.IWorkbenchPart; 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() { public AddWatchpointOnVariableActionDelegate() {
super(); super();
} }
/** /* (non-Javadoc)
* @see IObjectActionDelegate#setActivePart(IAction, IWorkbenchPart) * @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.
}
/** private static class GetSizeRequest extends CRequest implements ICWatchpointTarget.GetSizeRequest {
* @see IActionDelegate#run(IAction) 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) { public void run(IAction action) {
IStructuredSelection selection = getSelection(); if (fVar == null) {
if (selection == null || selection.isEmpty()) {
return; return;
} }
Object obj = ((TreeSelection)selection).getFirstElement(); final String expr = fVar.getExpression();
if (obj != null && obj instanceof CVariable) { if (expr == null) {
CVariable var = (CVariable)obj; assert false : "how are we getting an empty expression?"; //$NON-NLS-1$
return;
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());
}
} }
// 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()) { if (selection == null || selection.isEmpty()) {
action.setEnabled(false); action.setEnabled(false);
return; return;
} }
if (selection instanceof TreeSelection) { if (selection instanceof TreeSelection) {
Object obj = ((TreeSelection)selection).getFirstElement(); Object obj = ((TreeSelection)selection).getFirstElement();
if (obj != null && obj instanceof CVariable) { fVar = (ICWatchpointTarget)DebugPlugin.getAdapter(obj, ICWatchpointTarget.class);
action.setEnabled(true); if (fVar != null) {
} else { final ICWatchpointTarget.CanCreateWatchpointRequest request = new CanCreateWatchpointRequest() {
action.setEnabled(false); 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.ICType;
import org.eclipse.cdt.debug.core.model.ICValue; import org.eclipse.cdt.debug.core.model.ICValue;
import org.eclipse.cdt.debug.core.model.IDisassemblyBlock; 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.CDebugTarget;
import org.eclipse.cdt.debug.internal.core.model.CExpression; import org.eclipse.cdt.debug.internal.core.model.CExpression;
import org.eclipse.cdt.debug.internal.core.model.CStackFrame; import org.eclipse.cdt.debug.internal.core.model.CStackFrame;
@ -179,6 +180,12 @@ public class DisassemblyBackendCdi implements IDisassemblyBackend, IDebugEventSe
fFrameLevel = 0; 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) /* (non-Javadoc)
* @see org.eclipse.cdt.debug.internal.ui.disassembly.dsf.IDisassemblyBackend#retrieveFrameAddress(int) * @see org.eclipse.cdt.debug.internal.ui.disassembly.dsf.IDisassemblyBackend#retrieveFrameAddress(int)
*/ */
@ -190,7 +197,7 @@ public class DisassemblyBackendCdi implements IDisassemblyBackend, IDebugEventSe
return; return;
} }
IStackFrame stackFrame= stackFrames[targetFrame]; IStackFrame stackFrame= stackFrames[targetFrame];
fDisassemblyRetrieval.asyncGetFrameAddress(stackFrame, new IDisassemblyRetrieval.AddressRequest() { fDisassemblyRetrieval.asyncGetFrameAddress(stackFrame, new AddressRequest() {
@Override @Override
public void done() { public void done() {
fCallback.setUpdatePending(false); fCallback.setUpdatePending(false);
@ -238,6 +245,12 @@ public class DisassemblyBackendCdi implements IDisassemblyBackend, IDebugEventSe
return fTargetFrameContext.getFrameLineNumber(); 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) /* (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) * @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); endAddress= startAddress.add(addressLength);
} }
final BigInteger finalEndAddress= endAddress; final BigInteger finalEndAddress= endAddress;
final IDisassemblyRetrieval.DisassemblyRequest disassemblyRequest= new IDisassemblyRetrieval.DisassemblyRequest() { final IDisassemblyRetrieval.DisassemblyRequest disassemblyRequest= new DisassemblyRequest() {
@Override @Override
public void done() { public void done() {
if (!isCanceled() && getDisassemblyBlock() != null) { if (!isCanceled() && getDisassemblyBlock() != null) {
@ -365,7 +378,7 @@ public class DisassemblyBackendCdi implements IDisassemblyBackend, IDebugEventSe
public void retrieveDisassembly(String file, int lines, public void retrieveDisassembly(String file, int lines,
BigInteger endAddress, final boolean mixed, final boolean showSymbols, BigInteger endAddress, final boolean mixed, final boolean showSymbols,
final boolean showDisassembly) { final boolean showDisassembly) {
final IDisassemblyRetrieval.DisassemblyRequest disassemblyRequest= new IDisassemblyRetrieval.DisassemblyRequest() { final IDisassemblyRetrieval.DisassemblyRequest disassemblyRequest= new DisassemblyRequest() {
@Override @Override
public void done() { public void done() {
if (!isCanceled() && getDisassemblyBlock() != null) { if (!isCanceled() && getDisassemblyBlock() != null) {

View file

@ -14,89 +14,21 @@ package org.eclipse.cdt.debug.internal.ui.disassembly.dsf;
import java.math.BigInteger; import java.math.BigInteger;
import org.eclipse.cdt.debug.core.model.IDisassemblyBlock; 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.IRequest;
import org.eclipse.debug.core.model.IStackFrame; import org.eclipse.debug.core.model.IStackFrame;
/** /**
*/ */
public interface IDisassemblyRetrieval { 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);
} }
/** interface DisassemblyRequest extends IRequest {
*/ IDisassemblyBlock getDisassemblyBlock();
public static class AddressRequest extends Request { void setDisassemblyBlock(IDisassemblyBlock disassemblyBlock);
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;
}
} }
/** /**

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.concurrent.ThreadSafe;
import org.eclipse.cdt.dsf.debug.ui.viewmodel.AbstractDebugVMAdapter; 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.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.modules.ModulesVMProvider;
import org.eclipse.cdt.dsf.debug.ui.viewmodel.register.RegisterVMProvider; 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.breakpoints.GdbBreakpointVMProvider;
import org.eclipse.cdt.dsf.gdb.internal.ui.viewmodel.launch.LaunchVMProvider; import org.eclipse.cdt.dsf.gdb.internal.ui.viewmodel.launch.LaunchVMProvider;
import org.eclipse.cdt.dsf.service.DsfSession; import org.eclipse.cdt.dsf.service.DsfSession;
@ -47,11 +45,11 @@ public class GdbViewModelAdapter extends AbstractDebugVMAdapter
if ( IDebugUIConstants.ID_DEBUG_VIEW.equals(context.getId()) ) { if ( IDebugUIConstants.ID_DEBUG_VIEW.equals(context.getId()) ) {
return new LaunchVMProvider(this, context, getSession()); return new LaunchVMProvider(this, context, getSession());
} else if (IDebugUIConstants.ID_VARIABLE_VIEW.equals(context.getId()) ) { } 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()) ) { } else if (IDebugUIConstants.ID_REGISTER_VIEW.equals(context.getId()) ) {
return new RegisterVMProvider(this, context, getSession()); return new RegisterVMProvider(this, context, getSession());
} else if (IDebugUIConstants.ID_EXPRESSION_VIEW.equals(context.getId()) ) { } 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()) ) { } else if (IDebugUIConstants.ID_MODULE_VIEW.equals(context.getId()) ) {
return new ModulesVMProvider(this, context, getSession()); return new ModulesVMProvider(this, context, getSession());
} else if (IDebugUIConstants.ID_BREAKPOINT_VIEW.equals(context.getId()) ) { } else if (IDebugUIConstants.ID_BREAKPOINT_VIEW.equals(context.getId()) ) {

View file

@ -146,8 +146,8 @@ public class VariableVMNode extends AbstractExpressionVMNode
fExpression = expression; fExpression = expression;
} }
@Override @SuppressWarnings("rawtypes")
@SuppressWarnings("rawtype") @Override
public Object getAdapter(Class adapter) { public Object getAdapter(Class adapter) {
if (fExpression != null && adapter.isAssignableFrom(fExpression.getClass())) { if (fExpression != null && adapter.isAssignableFrom(fExpression.getClass())) {
return fExpression; return fExpression;
@ -750,7 +750,7 @@ public class VariableVMNode extends AbstractExpressionVMNode
IExpressionDMContext expressionDMC = expressionService.createExpression( IExpressionDMContext expressionDMC = expressionService.createExpression(
createCompositeDMVMContext(update), createCompositeDMVMContext(update),
update.getExpression().getExpressionText()); update.getExpression().getExpressionText());
VariableExpressionVMC variableVmc = new VariableExpressionVMC(expressionDMC); VariableExpressionVMC variableVmc = (VariableExpressionVMC)createVMContext(expressionDMC);
variableVmc.setExpression(update.getExpression()); variableVmc.setExpression(update.getExpression());
update.setExpressionElement(variableVmc); update.setExpressionElement(variableVmc);

View file

@ -69,27 +69,8 @@ public class VariableVMProvider extends AbstractDMVMProvider
store.addPropertyChangeListener(fPreferencesListener); store.addPropertyChangeListener(fPreferencesListener);
setDelayEventHandleForViewUpdate(store.getBoolean(IDsfDebugUIConstants.PREF_WAIT_FOR_VIEW_UPDATE_AFTER_STEP_ENABLE)); setDelayEventHandleForViewUpdate(store.getBoolean(IDsfDebugUIConstants.PREF_WAIT_FOR_VIEW_UPDATE_AFTER_STEP_ENABLE));
/* configureLayout();
* 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 });
}
@Override @Override
public void dispose() { public void dispose() {
@ -97,6 +78,30 @@ public class VariableVMProvider extends AbstractDMVMProvider
getPresentationContext().removePropertyChangeListener(fPresentationContextListener); getPresentationContext().removePropertyChangeListener(fPresentationContextListener);
super.dispose(); 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 @Override
public IColumnPresentation createColumnPresentation(IPresentationContext context, Object element) { public IColumnPresentation createColumnPresentation(IPresentationContext context, Object element) {