1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-03 23:25:26 +02:00

This is an udate that contains Fran Literrio's expression/variables view stuff along with my additions to make the expression view interact with the variables layout nodes. I do not have the bugzilla number offhand

This commit is contained in:
Randy Rohrbach 2007-05-31 18:52:45 +00:00
parent 1f71a2fac3
commit eb5188e48f
7 changed files with 861 additions and 19 deletions

View file

@ -16,6 +16,9 @@ import org.eclipse.dd.dsf.debug.ui.viewmodel.formatsupport.IFormattedValuePrefer
import org.eclipse.dd.dsf.debug.ui.viewmodel.register.RegisterGroupLayoutNode;
import org.eclipse.dd.dsf.debug.ui.viewmodel.register.RegisterLayoutNode;
import org.eclipse.dd.dsf.debug.ui.viewmodel.register.SyncRegisterDataAccess;
import org.eclipse.dd.dsf.debug.ui.viewmodel.variable.SyncVariableDataAccess;
import org.eclipse.dd.dsf.debug.ui.viewmodel.variable.VariableLocalsLayoutNode;
import org.eclipse.dd.dsf.debug.ui.viewmodel.variable.VariableSubExpressionsLayoutNode;
import org.eclipse.dd.dsf.service.DsfSession;
import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMAdapter;
import org.eclipse.dd.dsf.ui.viewmodel.IVMContext;
@ -58,16 +61,54 @@ public class ExpressionVMProvider extends AbstractDMVMProvider
}
protected void configureLayout() {
SyncRegisterDataAccess syncDataAccess = new SyncRegisterDataAccess();
// Configure the layout nodes
/*
* Allocate the synchronous data providers.
*/
SyncRegisterDataAccess syncRegDataAccess = new SyncRegisterDataAccess();
SyncVariableDataAccess syncvarDataAccess = new SyncVariableDataAccess() ;
/*
* Create the top level node which provides the anchor starting point.
*/
IVMRootLayoutNode debugViewSelectionNode = new DebugViewSelectionRootLayoutNode(this);
/*
* Now the Overarching management node.
*/
ExpressionManagerLayoutNode expressionManagerNode = new ExpressionManagerLayoutNode(this);
debugViewSelectionNode.setChildNodes(new IVMLayoutNode[] {expressionManagerNode});
IExpressionLayoutNode registerGroupNode = new RegisterGroupLayoutNode(this, getSession(), syncDataAccess);
expressionManagerNode.setExpressionLayoutNodes(new IExpressionLayoutNode[] { registerGroupNode });
IVMLayoutNode registerNode = new RegisterLayoutNode(this, this, getSession(), syncDataAccess);
/*
* The expression view wants to support fully all of the components of the register view.
*/
IExpressionLayoutNode registerGroupNode = new RegisterGroupLayoutNode(this, getSession(), syncRegDataAccess);
IVMLayoutNode registerNode = new RegisterLayoutNode(this, this, getSession(), syncRegDataAccess);
registerGroupNode.setChildNodes(new IVMLayoutNode[] { registerNode });
/*
* Create the local variables nodes next. They represent the first level shown in the view.
*/
IExpressionLayoutNode localsNode = new VariableLocalsLayoutNode(this, this, getSession(), syncvarDataAccess);
IVMLayoutNode subExpressioNode = new VariableSubExpressionsLayoutNode(this, getSession(), syncvarDataAccess);
localsNode.setChildNodes(new IVMLayoutNode[] { subExpressioNode });
/*
* Tell the expression node which subnodes 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.
*/
expressionManagerNode.setExpressionLayoutNodes(new IExpressionLayoutNode[] { registerGroupNode, localsNode });
/*
* Let the work know which is the top level node.
*/
setRootLayoutNode(debugViewSelectionNode);
}

View file

@ -0,0 +1,487 @@
/*
* SyncVariableDataAccess.java
* Created on May 22, 2007
*
* Copyright 2007 Wind River Systems Inc. All rights reserved.
*/
package org.eclipse.dd.dsf.debug.ui.viewmodel.variable;
import java.util.concurrent.ExecutionException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
import org.eclipse.dd.dsf.concurrent.DsfExecutor;
import org.eclipse.dd.dsf.concurrent.Query;
import org.eclipse.dd.dsf.concurrent.ThreadSafeAndProhibitedFromDsfExecutor;
import org.eclipse.dd.dsf.debug.service.IExpressions;
import org.eclipse.dd.dsf.debug.service.IExpressions.IExpressionDMContext;
import org.eclipse.dd.dsf.debug.service.IExpressions.IExpressionDMData;
import org.eclipse.dd.dsf.debug.service.IFormattedValues.FormattedValueDMContext;
import org.eclipse.dd.dsf.debug.service.IFormattedValues.FormattedValueDMData;
import org.eclipse.dd.dsf.debug.service.IFormattedValues.IFormattedDataDMContext;
import org.eclipse.dd.dsf.debug.ui.DsfDebugUIPlugin;
import org.eclipse.dd.dsf.service.DsfSession;
import org.eclipse.dd.dsf.service.IDsfService;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.util.tracker.ServiceTracker;
@ThreadSafeAndProhibitedFromDsfExecutor("")
public class SyncVariableDataAccess {
/**
* Need to use the OSGi service tracker here (instead of DsfServiceTracker),
* because we're accessing it in non-dispatch thread. DsfServiceTracker is
* not thread-safe.
*/
private ServiceTracker fServiceTracker;
private synchronized IExpressions getService(String filter) {
if (fServiceTracker == null) {
try {
fServiceTracker = new ServiceTracker(DsfDebugUIPlugin
.getBundleContext(), DsfDebugUIPlugin.getBundleContext()
.createFilter(filter), null);
fServiceTracker.open();
} catch (InvalidSyntaxException e) {
assert false : "Invalid filter in DMC: " + filter; //$NON-NLS-1$
return null;
}
} else {
/*
* All of the DMCs that this cell modifier is invoked for should
* originate from the same service. This assertion checks this
* assumption by comparing the service reference in the tracker to
* the filter string in the DMC.
*/
try {
assert DsfDebugUIPlugin.getBundleContext().createFilter(filter)
.match(fServiceTracker.getServiceReference());
} catch (InvalidSyntaxException e) {
}
}
return (IExpressions) fServiceTracker.getService();
}
public void dispose() {
if (fServiceTracker != null) {
fServiceTracker.close();
}
}
public IExpressionDMContext getVariableDMC(Object element) {
if (element instanceof IAdaptable) {
return (IExpressionDMContext) ((IAdaptable) element).getAdapter(IExpressionDMContext.class);
}
return null;
}
public class GetVariableValueQuery extends Query<IExpressionDMData> {
private IExpressionDMContext fDmc;
public GetVariableValueQuery(DsfExecutor executor, IExpressionDMContext dmc) {
super(executor);
fDmc = dmc;
}
@Override
protected void execute(final DataRequestMonitor<IExpressionDMData> rm) {
/*
* Guard agains the session being disposed. If session is disposed
* it could mean that the executor is shut-down, which in turn could
* mean that we can't complete the RequestMonitor argument. in that
* case, cancel to notify waiting thread.
*/
final DsfSession session = DsfSession.getSession(fDmc.getSessionId());
if (session == null) {
cancel(false);
return;
}
IExpressions service = getService(fDmc.getServiceFilter());
if (service == null) {
rm.setStatus(new Status(IStatus.ERROR, DsfDebugUIPlugin.PLUGIN_ID, IDsfService.INVALID_STATE, "Service not available", null)); //$NON-NLS-1$
rm.done();
return;
}
service.getModelData(fDmc, new DataRequestMonitor<IExpressionDMData>(session.getExecutor(), rm) {
@Override
protected void handleCompleted() {
/*
* We're in another dispatch, so we must guard against
* executor shutdown again.
*/
if (!DsfSession.isSessionActive(session.getId())) {
GetVariableValueQuery.this.cancel(false);
return;
}
super.handleCompleted();
}
@Override
protected void handleOK() {
/*
* All good set return value.
*/
rm.setData(getData());
rm.done();
}
});
}
}
public IExpressionDMContext getExpressionDMC(Object element) {
if (element instanceof IAdaptable) {
return (IExpressionDMContext) ((IAdaptable) element).getAdapter(IExpressionDMContext.class);
}
return null;
}
public IExpressionDMData readVariable(Object element) {
/*
* Get the DMC and the session. If element is not an register DMC, or
* session is stale, then bail out.
*/
IExpressionDMContext dmc = getExpressionDMC(element);
if (dmc == null) return null;
DsfSession session = DsfSession.getSession(dmc.getSessionId());
if (session == null) return null;
/*
* Create the query to request the value from service. Note: no need to
* guard agains RejectedExecutionException, because
* DsfSession.getSession() above would only return an active session.
*/
GetVariableValueQuery query = new GetVariableValueQuery(session.getExecutor(), dmc);
session.getExecutor().execute(query);
/*
* Now we have the data, go and get it. Since the call is completed now
* the ".get()" will not suspend it will immediately return with the
* data.
*/
try {
return query.get();
} catch (InterruptedException e) {
assert false;
return null;
} catch (ExecutionException e) {
return null;
}
}
public class SetVariableValueQuery extends Query<Object> {
private IExpressionDMContext fDmc;
private String fValue;
private String fFormatId;
public SetVariableValueQuery(DsfExecutor executor, IExpressionDMContext dmc, String value, String formatId) {
super(executor);
fDmc = dmc;
fValue = value;
fFormatId = formatId;
}
@Override
protected void execute(final DataRequestMonitor<Object> rm) {
/*
* We're in another dispatch, so we must guard against executor
* shutdown again.
*/
final DsfSession session = DsfSession.getSession(fDmc.getSessionId());
if (session == null) {
cancel(false);
return;
}
/*
* Guard against a disposed service
*/
IExpressions service = getService(fDmc.getServiceFilter());
if (service == null) {
rm.setStatus(new Status(IStatus.ERROR, DsfDebugUIPlugin.PLUGIN_ID, IDsfService.INVALID_STATE, "Service unavailable", null)); //$NON-NLS-1$
rm.done();
return;
}
/*
* Write the bit field using a string/format style.
*/
service.writeExpression(
fDmc,
fValue,
fFormatId,
new DataRequestMonitor<IExpressionDMData>(session.getExecutor(), rm) {
@Override
protected void handleCompleted() {
/*
* We're in another dispatch, so we must guard
* against executor shutdown again.
*/
if (!DsfSession.isSessionActive(session.getId())) {
SetVariableValueQuery.this.cancel(false);
return;
}
super.handleCompleted();
}
@Override
protected void handleOK() {
/*
* All good set return value.
*/
rm.setData(new Object());
rm.done();
}
}
);
}
}
public void writeVariable(Object element, String value, String formatId) {
/*
* Get the DMC and the session. If element is not an register DMC, or
* session is stale, then bail out.
*/
IExpressionDMContext dmc = getExpressionDMC(element);
if (dmc == null) return;
DsfSession session = DsfSession.getSession(dmc.getSessionId());
if (session == null) return;
/*
* Create the query to write the value to the service. Note: no need to
* guard agains RejectedExecutionException, because
* DsfSession.getSession() above would only return an active session.
*/
SetVariableValueQuery query = new SetVariableValueQuery(session.getExecutor(), dmc, value, formatId);
session.getExecutor().execute(query);
/*
* Now we have the data, go and get it. Since the call is completed now
* the ".get()" will not suspend it will immediately return with the
* data.
*/
try {
/*
* Return value is irrelevant, any error would come through with an
* exception.
*/
query.get();
} catch (InterruptedException e) {
assert false;
} catch (ExecutionException e) {
/*
* View must be shutting down, no need to show error dialog.
*/
}
}
public IFormattedDataDMContext<?> getFormattedDMC(Object element) {
if (element instanceof IAdaptable) {
return (IFormattedDataDMContext<?>) ((IAdaptable) element).getAdapter(IFormattedDataDMContext.class);
}
return null;
}
public class GetSupportFormatsValueQuery extends Query<Object> {
IFormattedDataDMContext<?> fDmc;
public GetSupportFormatsValueQuery(DsfExecutor executor, IFormattedDataDMContext<?> dmc) {
super(executor);
fDmc = dmc;
}
@Override
protected void execute(final DataRequestMonitor<Object> rm) {
/*
* We're in another dispatch, so we must guard against executor
* shutdown again.
*/
final DsfSession session = DsfSession.getSession(fDmc.getSessionId());
if (session == null) {
cancel(false);
return;
}
/*
* Guard against a disposed service
*/
IExpressions service = getService(fDmc.getServiceFilter());
if (service == null) {
rm.setStatus(new Status(IStatus.ERROR, DsfDebugUIPlugin.PLUGIN_ID, IDsfService.INVALID_STATE, "Service unavailable", null)); //$NON-NLS-1$
rm.done();
return;
}
/*
* Write the bit field using a string/format style.
*/
service.getAvailableFormattedValues(
fDmc,
new DataRequestMonitor<String[]>(session.getExecutor(), rm) {
@Override
protected void handleCompleted() {
/*
* We're in another dispatch, so we must
* guard against executor shutdown again.
*/
if (!DsfSession.isSessionActive(session.getId())) {
GetSupportFormatsValueQuery.this.cancel(false);
return;
}
super.handleCompleted();
}
@Override
protected void handleOK() {
/*
* All good set return value.
*/
rm.setData(new Object());
rm.done();
}
}
);
}
}
public String[] getSupportedFormats(Object element) {
/*
* Get the DMC and the session. If element is not an register DMC, or
* session is stale, then bail out.
*/
IFormattedDataDMContext<?> dmc = getFormattedDMC(element);
if (dmc == null) return null;
DsfSession session = DsfSession.getSession(dmc.getSessionId());
if (session == null) return null;
/*
* Create the query to write the value to the service. Note: no need to
* guard agains RejectedExecutionException, because
* DsfSession.getSession() above would only return an active session.
*/
GetSupportFormatsValueQuery query = new GetSupportFormatsValueQuery(session.getExecutor(), dmc);
session.getExecutor().execute(query);
/*
* Now we have the data, go and get it. Since the call is completed now
* the ".get()" will not suspend it will immediately return with the
* data.
*/
try {
return (String[]) query.get();
} catch (InterruptedException e) {
assert false;
return null;
} catch (ExecutionException e) {
return null;
}
}
public class GetFormattedValueValueQuery extends Query<Object> {
private IFormattedDataDMContext<?> fDmc;
private String fFormatId;
public GetFormattedValueValueQuery(DsfExecutor executor, IFormattedDataDMContext<?> dmc, String formatId) {
super(executor);
fDmc = dmc;
fFormatId = formatId;
}
@Override
protected void execute(final DataRequestMonitor<Object> rm) {
/*
* We're in another dispatch, so we must guard against executor
* shutdown again.
*/
final DsfSession session = DsfSession.getSession(fDmc.getSessionId());
if (session == null) {
cancel(false);
return;
}
/*
* Guard against a disposed service
*/
IExpressions service = getService(fDmc.getServiceFilter());
if (service == null) {
rm .setStatus(new Status(IStatus.ERROR, DsfDebugUIPlugin.PLUGIN_ID, IDsfService.INVALID_STATE, "Service unavailable", null)); //$NON-NLS-1$
rm.done();
return;
}
/*
* Convert to the proper formatting DMC then go get the formatted value.
*/
FormattedValueDMContext formDmc = service.getFormattedValue(fDmc, fFormatId);
service.getModelData(formDmc, new DataRequestMonitor<FormattedValueDMData>(session.getExecutor(), rm) {
@Override
protected void handleCompleted() {
/*
* We're in another dispatch, so we must guard against executor shutdown again.
*/
if (!DsfSession.isSessionActive(session.getId())) {
GetFormattedValueValueQuery.this.cancel(false);
return;
}
super.handleCompleted();
}
@Override
protected void handleOK() {
/*
* All good set return value.
*/
rm.setData(getData().getFormattedValue());
rm.done();
}
});
}
}
public String getFormattedValue(Object element, String formatId) {
/*
* Get the DMC and the session. If element is not an register DMC, or
* session is stale, then bail out.
*/
IFormattedDataDMContext<?> dmc = getFormattedDMC(element);
if (dmc == null) return null;
DsfSession session = DsfSession.getSession(dmc.getSessionId());
if (session == null) return null;
/*
* Create the query to write the value to the service. Note: no need to
* guard agains RejectedExecutionException, because
* DsfSession.getSession() above would only return an active session.
*/
GetFormattedValueValueQuery query = new GetFormattedValueValueQuery(session.getExecutor(), dmc, formatId);
session.getExecutor().execute(query);
/*
* Now we have the data, go and get it. Since the call is completed now
* the ".get()" will not suspend it will immediately return with the
* data.
*/
try {
return (String) query.get();
} catch (InterruptedException e) {
assert false;
return null;
} catch (ExecutionException e) {
return null;
}
}
}

View file

@ -0,0 +1,91 @@
/*
* VariableLayoutValueCellModifier.java
* Created on May 22, 2007
*
* Copyright 2007 Wind River Systems Inc. All rights reserved.
*/
package org.eclipse.dd.dsf.debug.ui.viewmodel.variable;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.dd.dsf.debug.service.IExpressions.IExpressionDMContext;
import org.eclipse.dd.dsf.debug.ui.viewmodel.IDebugVMConstants;
import org.eclipse.dd.dsf.debug.ui.viewmodel.expression.WatchExpressionCellModifier;
import org.eclipse.dd.dsf.debug.ui.viewmodel.formatsupport.IFormattedValuePreferenceStore;
public class VariableLayoutValueCellModifier extends WatchExpressionCellModifier {
private SyncVariableDataAccess fDataAccess = null;
private IFormattedValuePreferenceStore fFormattedValuePreferenceStore;
public VariableLayoutValueCellModifier(IFormattedValuePreferenceStore formattedValuePreferenceStore, SyncVariableDataAccess access) {
fDataAccess = access;
fFormattedValuePreferenceStore = formattedValuePreferenceStore;
}
/*
* Used to make sure we are dealing with a valid variable.
*/
private IExpressionDMContext getVariableDMC(Object element) {
if (element instanceof IAdaptable) {
return (IExpressionDMContext)((IAdaptable)element).getAdapter(IExpressionDMContext.class);
}
return null;
}
@Override
public boolean canModify(Object element, String property) {
// If we're in the column value, modify the register data. Otherwise, call the super-class to edit
// the watch expression.
if (IDebugVMConstants.COLUMN_ID__VALUE.equals(property)) {
// Make sure we are are dealing with a valid set of information.
if (getVariableDMC(element) == null)
return false;
return true ;
}
return super.canModify(element, property);
}
@Override
public Object getValue(Object element, String property) {
// If we're in the column value, modify the variable value. Otherwise, call the super-class to edit
// the watch expression.
if (IDebugVMConstants.COLUMN_ID__VALUE.equals(property)) {
// Make sure we are working on the editable areas.
// Write the value in the currently requested format. Since they could
// have freeformed typed in any format this is just a guess and may not
// really accomplish anything.
String value = fDataAccess.getFormattedValue(element, fFormattedValuePreferenceStore.getDefaultFormatId());
if (value == null)
return "..."; //$NON-NLS-1$
return value;
}
return super.getValue(element, property);
}
@Override
public void modify(Object element, String property, Object value) {
// If we're in the column value, modify the register data. Otherwise, call the super-class to edit
// the watch expression.
if (IDebugVMConstants.COLUMN_ID__VALUE.equals(property)) {
if (value instanceof String) {
// PREFPAGE : We are using a default format until the preference page is created.
fDataAccess.writeVariable(element, (String) value, fFormattedValuePreferenceStore.getDefaultFormatId());
}
}
else {
super.modify(element, property, value);
}
}
}

View file

@ -12,10 +12,12 @@ package org.eclipse.dd.dsf.debug.ui.viewmodel.variable;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
import org.eclipse.dd.dsf.concurrent.DsfExecutor;
import org.eclipse.dd.dsf.concurrent.MultiRequestMonitor;
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
import org.eclipse.dd.dsf.datamodel.IDMContext;
import org.eclipse.dd.dsf.datamodel.IDMEvent;
import org.eclipse.dd.dsf.datamodel.IDMService;
import org.eclipse.dd.dsf.debug.service.IExpressions;
@ -30,23 +32,130 @@ import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.dd.dsf.debug.service.IStack.IFrameDMContext;
import org.eclipse.dd.dsf.debug.service.IStack.IVariableDMContext;
import org.eclipse.dd.dsf.debug.service.IStack.IVariableDMData;
import org.eclipse.dd.dsf.debug.ui.DsfDebugUIPlugin;
import org.eclipse.dd.dsf.debug.ui.viewmodel.IDebugVMConstants;
import org.eclipse.dd.dsf.debug.ui.viewmodel.expression.AbstractExpressionLayoutNode;
import org.eclipse.dd.dsf.debug.ui.viewmodel.formatsupport.IFormattedValuePreferenceStore;
import org.eclipse.dd.dsf.debug.ui.viewmodel.formatsupport.IFormattedValueVMContext;
import org.eclipse.dd.dsf.service.DsfSession;
import org.eclipse.dd.dsf.service.IDsfService;
import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMProvider;
import org.eclipse.dd.dsf.ui.viewmodel.IVMContext;
import org.eclipse.dd.dsf.ui.viewmodel.VMDelta;
import org.eclipse.dd.dsf.ui.viewmodel.dm.AbstractDMVMLayoutNode;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.model.IDebugTarget;
import org.eclipse.debug.core.model.IExpression;
import org.eclipse.debug.core.model.IValue;
import org.eclipse.debug.core.model.IVariable;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementEditor;
import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
import org.eclipse.debug.ui.actions.IWatchExpressionFactoryAdapterExtension;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.ICellModifier;
import org.eclipse.jface.viewers.TextCellEditor;
import org.eclipse.swt.widgets.Composite;
@SuppressWarnings({"restriction", "nls"})
public class VariableLocalsLayoutNode extends AbstractDMVMLayoutNode<IExpressionDMData> {
public class VariableLocalsLayoutNode extends AbstractExpressionLayoutNode<IExpressionDMData> implements IElementEditor {
private final IFormattedValuePreferenceStore fFormattedPrefStore;
private final SyncVariableDataAccess fSyncVariableDataAccess;
protected class VariableLocalsVMC extends DMVMContext implements IFormattedValueVMContext, IVariable {
private IExpression fExpression;
public VariableLocalsVMC(IDMContext<?> dmc) {
super(dmc);
}
public VariableLocalsLayoutNode(AbstractVMProvider provider, DsfSession session) {
super(provider, session, IExpressions.IExpressionDMContext.class);
public IFormattedValuePreferenceStore getPreferenceStore() {
return fFormattedPrefStore;
}
public void setExpression(IExpression expression) {
fExpression = expression;
}
@Override
@SuppressWarnings("unchecked")
public Object getAdapter(Class adapter) {
if (fExpression != null && adapter.isAssignableFrom(fExpression.getClass())) {
return fExpression;
} else if (adapter.isAssignableFrom(IWatchExpressionFactoryAdapterExtension.class)) {
return fVariableLocalsExpressionFactory;
} else {
return super.getAdapter(adapter);
}
}
@Override
public boolean equals(Object other) {
if (other instanceof VariableLocalsVMC && super.equals(other)) {
VariableLocalsVMC otherGroup = (VariableLocalsVMC)other;
return (otherGroup.fExpression == null && fExpression == null) ||
(otherGroup.fExpression != null && otherGroup.fExpression.equals(fExpression));
}
return false;
}
@Override
public int hashCode() {
return super.hashCode() + (fExpression != null ? fExpression.hashCode() : 0);
}
public String getName() throws DebugException { return toString(); }
public String getReferenceTypeName() throws DebugException { return ""; } //$NON-NLS-1$
public IValue getValue() throws DebugException { return null; }
public boolean hasValueChanged() throws DebugException { return false; }
public void setValue(IValue value) throws DebugException {}
public void setValue(String expression) throws DebugException {}
public boolean supportsValueModification() { return false; }
public boolean verifyValue(IValue value) throws DebugException { return false; }
public boolean verifyValue(String expression) throws DebugException { return false; }
public IDebugTarget getDebugTarget() { return null;}
public ILaunch getLaunch() { return null; }
public String getModelIdentifier() { return DsfDebugUIPlugin.PLUGIN_ID; }
}
protected class VariableLocalsExpressionFactory implements IWatchExpressionFactoryAdapterExtension {
public boolean canCreateWatchExpression(IVariable variable) {
return variable instanceof VariableLocalsVMC;
}
public String createWatchExpression(IVariable variable) throws CoreException {
//VariableLocalsVMC registerVmc = ((VariableLocalsVMC)variable);
/*
* This needs to be completed by filling in the fully qualified expression.
* Currently the ExpressionDMC does not support that. This will be changed
* shortly. For now I am creating a bugzilla about this not being complete
* and checking this in.
*/
return null;
}
}
final protected VariableLocalsExpressionFactory fVariableLocalsExpressionFactory = new VariableLocalsExpressionFactory();
public VariableLocalsLayoutNode(IFormattedValuePreferenceStore prefStore, AbstractVMProvider provider,
DsfSession session, SyncVariableDataAccess syncVariableDataAccess) {
super(provider, session, IExpressions.IExpressionDMContext.class);
fFormattedPrefStore = prefStore;
fSyncVariableDataAccess = syncVariableDataAccess;
}
@Override
protected IVMContext createVMContext(IDMContext<IExpressionDMData> dmc) {
return new VariableLocalsVMC(dmc);
}
/**
* We override this method because we now need to perform an extra level of data fetch to get the
* formatted value of the expression.
@ -97,6 +206,8 @@ public class VariableLocalsLayoutNode extends AbstractDMVMLayoutNode<IExpression
weAreExtractingFormattedData = true;
} else if (IDebugVMConstants.COLUMN_ID__DESCRIPTION.equals(localColumns[idx])) {
update.setLabel("", idx);
} else if (IDebugVMConstants.COLUMN_ID__EXPRESSION.equals(localColumns[idx])) {
update.setLabel(getData().getName(), idx);
}
}
@ -132,7 +243,7 @@ public class VariableLocalsLayoutNode extends AbstractDMVMLayoutNode<IExpression
* we will pick the first available format.
*/
final String preferencePageFormatId = IFormattedValues.NATURAL_FORMAT;
final String preferencePageFormatId = fFormattedPrefStore.getDefaultFormatId();
expressionService.getAvailableFormattedValues(
dmc,
@ -212,10 +323,8 @@ public class VariableLocalsLayoutNode extends AbstractDMVMLayoutNode<IExpression
// ISSUE: Do we need to explicitly get the IExecutionDMContext and ISymbolDMContext since they
// should be in the parent chain of the IFrameDMContext object?
final IExecutionDMContext execDmc =
findDmcInPath(update.getElementPath(), IExecutionDMContext.class);
final IFrameDMContext frameDmc =
findDmcInPath(update.getElementPath(), IFrameDMContext.class);
final IExecutionDMContext execDmc = findDmcInPath(update.getElementPath(), IExecutionDMContext.class);
final IFrameDMContext frameDmc = findDmcInPath(update.getElementPath(), IFrameDMContext.class);
//final ISymbolDMContext symbolDmc =
// findDmcInPath(update.getElementPath(), ISymbolDMContext.class);
@ -345,4 +454,76 @@ public class VariableLocalsLayoutNode extends AbstractDMVMLayoutNode<IExpression
// }
super.buildDeltaForDMEvent(e, parent, nodeOffset, requestMonitor);
}
public CellEditor getCellEditor(IPresentationContext context, String columnId, Object element, Composite parent) {
if (IDebugVMConstants.COLUMN_ID__VALUE.equals(columnId)) {
return new TextCellEditor(parent);
}
else if (IDebugVMConstants.COLUMN_ID__EXPRESSION.equals(columnId)) {
return new TextCellEditor(parent);
}
return null;
}
public ICellModifier getCellModifier(IPresentationContext context, Object element) {
return new VariableLayoutValueCellModifier(fFormattedPrefStore, fSyncVariableDataAccess);
}
@Override
public void getElementForExpression(final IChildrenUpdate update, final String expressionText, final IExpression expression) {
/*
* Create a valid DMC for this entered expression.
*/
final IFrameDMContext frameDmc = findDmcInPath(update.getElementPath(), IFrameDMContext.class);
final IExpressions expressionService = getServicesTracker().getService(IExpressions.class);
IExpressionDMContext expressionDMC = expressionService.createExpression(frameDmc, expressionText);
/*
* Now create the valid VMC which wrappers it.
*/
IVMContext vmc = createVMContext(expressionDMC);
/*
* Associate this expression with the newly valid DMC and return this VMC back up the chain of command
* so it will be used when displaying the value in the expression view.
*/
associateExpression(vmc, expression);
update.setChild(vmc, 0);
update.done();
}
@Override
protected void associateExpression(Object element, IExpression expression) {
if (element instanceof VariableLocalsVMC) {
((VariableLocalsVMC)element).setExpression(expression);
}
}
@Override
protected int getDeltaFlagsForExpressionPart(Object event) {
if (event instanceof IRunControl.ISuspendedDMEvent) {
return IModelDelta.CONTENT;
}
return IModelDelta.NO_CHANGE;
}
@Override
protected void testContextForExpression(Object element, String expression, DataRequestMonitor<Boolean> rm) {
/*
* Since we are overriding "getElementForExpression" we do not need to do anything here. But
* we are forced to supply this routine because it is abstract in the extending class.
*/
}
public int getExpressionLength(String expression) {
/*
* Since we are overriding "getElementForExpression" we do not need to do anything here.
* We just assume the entire expression is for us.
*/
return expression.length() ;
}
}

View file

@ -40,9 +40,12 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
@SuppressWarnings("restriction")
public class VariableSubExpressionsLayoutNode extends AbstractDMVMLayoutNode<IExpressionDMData> {
private SyncVariableDataAccess fSyncVariableDataAccess;
public VariableSubExpressionsLayoutNode(AbstractVMProvider provider, DsfSession session) {
public VariableSubExpressionsLayoutNode(AbstractVMProvider provider, DsfSession session, SyncVariableDataAccess syncVariableDataAccess) {
super(provider, session, IExpressions.IExpressionDMContext.class);
fSyncVariableDataAccess = syncVariableDataAccess;
}
/**

View file

@ -8,7 +8,9 @@
*/
package org.eclipse.dd.dsf.debug.ui.viewmodel.variable;
import org.eclipse.dd.dsf.debug.service.IFormattedValues;
import org.eclipse.dd.dsf.debug.ui.viewmodel.DebugViewSelectionRootLayoutNode;
import org.eclipse.dd.dsf.debug.ui.viewmodel.formatsupport.IFormattedValuePreferenceStore;
import org.eclipse.dd.dsf.service.DsfSession;
import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMAdapter;
import org.eclipse.dd.dsf.ui.viewmodel.IVMLayoutNode;
@ -20,11 +22,18 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationCont
@SuppressWarnings("restriction")
public class VariableVMProvider extends AbstractDMVMProvider implements
IColumnPresentationFactory {
IColumnPresentationFactory, IFormattedValuePreferenceStore {
private String defaultFormatId = IFormattedValues.NATURAL_FORMAT;
public VariableVMProvider(AbstractVMAdapter adapter, IPresentationContext context, DsfSession session) {
super(adapter, context, session);
/*
* Create the variable data access routines.
*/
SyncVariableDataAccess varAccess = new SyncVariableDataAccess() ;
/*
* Create the top level node to deal with the root selection.
*/
@ -33,13 +42,13 @@ public class VariableVMProvider extends AbstractDMVMProvider implements
/*
* Create the local variables nodes next. They represent the first level shown in the view.
*/
IVMLayoutNode localsNode = new VariableLocalsLayoutNode(this, getSession());
IVMLayoutNode localsNode = new VariableLocalsLayoutNode(this, this, getSession(), varAccess);
debugViewSelection.setChildNodes(new IVMLayoutNode[] { localsNode });
/*
* Create the next level which represents members of structs/unions/enums and elements of arrays.
*/
IVMLayoutNode subExpressioNode = new VariableSubExpressionsLayoutNode(this, getSession());
IVMLayoutNode subExpressioNode = new VariableSubExpressionsLayoutNode(this, getSession(), varAccess);
localsNode.setChildNodes(new IVMLayoutNode[] { subExpressioNode });
/*
@ -57,4 +66,20 @@ public class VariableVMProvider extends AbstractDMVMProvider implements
public String getColumnPresentationId(IPresentationContext context, Object element) {
return VariableColumnPresentation.ID;
}
/*
* (non-Javadoc)
* @see org.eclipse.dd.dsf.debug.ui.viewmodel.formatsupport.IFormattedValuePreferenceStore#getDefaultFormatId()
*/
public String getDefaultFormatId() {
return defaultFormatId;
}
/*
* (non-Javadoc)
* @see org.eclipse.dd.dsf.debug.ui.viewmodel.formatsupport.IFormattedValuePreferenceStore#setDefaultFormatId(java.lang.String)
*/
public void setDefaultFormatId(String id) {
defaultFormatId = id;
}
}

View file

@ -14,6 +14,7 @@ import java.util.Map;
import org.eclipse.cdt.core.IAddress;
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
import org.eclipse.dd.dsf.datamodel.IDMContext;
import org.eclipse.dd.dsf.datamodel.IDMData;
import org.eclipse.dd.dsf.datamodel.IDMEvent;
@ -167,4 +168,17 @@ public interface IExpressions extends IDMService, IFormattedValues {
* @param rm: Request completion monitor.
*/
void getBaseExpressions(IExpressionDMContext exprContext, DataRequestMonitor<IExpressionDMContext[]> rm);
/**
* This method supports the writing/modifying the value of the expression.
*
* @param expressionContext: The data model context representing an expression.
*
* @param expressionValue: The new value of the expression as a String.
*
* @param formatId: The format ID specifying the format of parameter <b>expressionValue</b>.
*
* @param rm: Request completion monitor.
*/
void writeExpression(IDMContext<?> expressionContext, String exressionValue, String formatId, RequestMonitor rm);
}