mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Applied patch from Fran Litterio for Bugzilla 186256.
Initial implementation of the variables view for Open Source.
This commit is contained in:
parent
f719fd899c
commit
ebaacc4b25
4 changed files with 671 additions and 111 deletions
|
@ -1,94 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2006 Wind River Systems and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Wind River Systems - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.dd.dsf.debug.ui.viewmodel.variable;
|
||||
|
||||
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.IDMEvent;
|
||||
import org.eclipse.dd.dsf.debug.service.IRegisters;
|
||||
import org.eclipse.dd.dsf.debug.service.IRunControl;
|
||||
import org.eclipse.dd.dsf.debug.service.IStack;
|
||||
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.viewmodel.IDebugVMConstants;
|
||||
import org.eclipse.dd.dsf.service.DsfSession;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMProvider;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.VMDelta;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.AbstractDMVMLayoutNode;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
|
||||
|
||||
@SuppressWarnings("restriction")
|
||||
public class LocalsLayoutNode extends AbstractDMVMLayoutNode<IVariableDMData> {
|
||||
|
||||
public LocalsLayoutNode(AbstractVMProvider provider, DsfSession session) {
|
||||
super(provider, session, IStack.IVariableDMContext.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateElementsInSessionThread(final IChildrenUpdate update) {
|
||||
if (!checkService(IRegisters.class, null, update)) return;
|
||||
|
||||
final IFrameDMContext frameDmc = findDmcInPath(update.getElementPath(), IFrameDMContext.class) ;
|
||||
|
||||
if (frameDmc != null) {
|
||||
getServicesTracker().getService(IStack.class).getArguments(
|
||||
frameDmc,
|
||||
new DataRequestMonitor<IVariableDMContext[]>(getSession().getExecutor(), null) {
|
||||
@Override
|
||||
public void handleCompleted() {
|
||||
if (!getStatus().isOK()) {
|
||||
update.done();
|
||||
return;
|
||||
}
|
||||
fillUpdateWithVMCs(update, getData());
|
||||
update.done();
|
||||
}});
|
||||
} else {
|
||||
handleFailedUpdate(update);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fillColumnLabel(IDMContext<IVariableDMData> dmContext, IVariableDMData dmData,
|
||||
String columnId, int idx, ILabelUpdate update)
|
||||
{
|
||||
if (IDebugVMConstants.COLUMN_ID__NAME.equals(columnId)) {
|
||||
update.setLabel(dmData.getName(), idx);
|
||||
} else if (IDebugVMConstants.COLUMN_ID__VALUE.equals(columnId)) {
|
||||
update.setLabel(dmData.getValue(), idx);
|
||||
} else {
|
||||
update.setLabel("", idx); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getNodeDeltaFlagsForDMEvent(IDMEvent<?> e) {
|
||||
if (e instanceof IRunControl.ISuspendedDMEvent) {
|
||||
return IModelDelta.CONTENT;
|
||||
}
|
||||
return IModelDelta.NO_CHANGE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void buildDeltaForDMEvent(IDMEvent<?> e, VMDelta parent, int nodeOffset, RequestMonitor rm) {
|
||||
if (e instanceof IRunControl.ISuspendedDMEvent) {
|
||||
// Create a delta that the whole register group has changed.
|
||||
parent.addFlags(IModelDelta.CONTENT);
|
||||
}
|
||||
|
||||
super.buildDeltaForDMEvent(e, parent, nodeOffset, rm);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,341 @@
|
|||
/**
|
||||
* Copyright (c) 2006 Wind River Systems and others. All rights reserved. This program and
|
||||
* the accompanying materials are made available under the terms of the Eclipse Public
|
||||
* License v1.0 which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors: Wind River Systems - initial API and implementation
|
||||
*/
|
||||
|
||||
package org.eclipse.dd.dsf.debug.ui.viewmodel.variable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
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.IDMEvent;
|
||||
import org.eclipse.dd.dsf.datamodel.IDMService;
|
||||
import org.eclipse.dd.dsf.debug.service.IExpressions;
|
||||
import org.eclipse.dd.dsf.debug.service.IFormattedValues;
|
||||
import org.eclipse.dd.dsf.debug.service.IRunControl;
|
||||
import org.eclipse.dd.dsf.debug.service.IStack;
|
||||
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.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.viewmodel.IDebugVMConstants;
|
||||
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.VMDelta;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.AbstractDMVMLayoutNode;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
|
||||
|
||||
@SuppressWarnings("restriction")
|
||||
public class VariableLocalsLayoutNode extends AbstractDMVMLayoutNode<IExpressionDMData> {
|
||||
|
||||
public VariableLocalsLayoutNode(AbstractVMProvider provider, DsfSession session) {
|
||||
super(provider, session, IExpressions.IExpressionDMContext.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* We override this method because we now need to perform an extra level of data fetch to get the
|
||||
* formatted value of the expression.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
@Override
|
||||
protected void updateLabelInSessionThread(ILabelUpdate[] updates) {
|
||||
for (final ILabelUpdate update : updates) {
|
||||
|
||||
final IExpressionDMContext dmc = findDmcInPath(update.getElementPath(), IExpressions.IExpressionDMContext.class);
|
||||
|
||||
((IDMService)getServicesTracker().getService(null, dmc.getServiceFilter())).getModelData(
|
||||
dmc,
|
||||
new DataRequestMonitor<IExpressionDMData>(getSession().getExecutor(), null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
// Check that the request was evaluated and data is still valid. The request could
|
||||
// fail if the state of the service changed during the request, but the view model
|
||||
// has not been updated yet.
|
||||
|
||||
if (!getStatus().isOK() || !getData().isValid()) {
|
||||
assert getStatus().isOK() ||
|
||||
getStatus().getCode() != IDsfService.INTERNAL_ERROR ||
|
||||
getStatus().getCode() != IDsfService.NOT_SUPPORTED;
|
||||
handleFailedUpdate(update);
|
||||
return;
|
||||
}
|
||||
|
||||
// If columns are configured, extract the selected values for each understood column.
|
||||
// First, we fill all of those columns which can be filled without extra data mining.
|
||||
// We also note if we do have to do extra data mining. Any columns need to set the
|
||||
// processing flag so we know we have further work to do. If there are more columns
|
||||
// which need data extraction they need to be added in both "for" loops.
|
||||
|
||||
String[] localColumns = update.getPresentationContext().getColumns();
|
||||
if (localColumns == null)
|
||||
localColumns = new String[] { null };
|
||||
|
||||
boolean weAreExtractingFormattedData = false;
|
||||
|
||||
for (int idx = 0; idx < localColumns.length; idx++) {
|
||||
if (IDebugVMConstants.COLUMN_ID__NAME.equals(localColumns[idx])) {
|
||||
update.setLabel(getData().getName(), idx);
|
||||
} else if (IDebugVMConstants.COLUMN_ID__VALUE.equals(localColumns[idx])) {
|
||||
weAreExtractingFormattedData = true;
|
||||
} else if (IDebugVMConstants.COLUMN_ID__DESCRIPTION.equals(localColumns[idx])) {
|
||||
update.setLabel("", idx); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! weAreExtractingFormattedData ) {
|
||||
update.done();
|
||||
} else {
|
||||
for (int idx = 0; idx < localColumns.length; idx++) {
|
||||
if (IDebugVMConstants.COLUMN_ID__VALUE.equals(localColumns[idx])) {
|
||||
updateFormattedExpressionValue(update, idx, dmc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Private data access routine which performs the extra level of data access needed to
|
||||
* get the formatted data value for a specific register.
|
||||
*/
|
||||
private void updateFormattedExpressionValue(final ILabelUpdate update, final int labelIndex,
|
||||
final IExpressionDMContext dmc)
|
||||
{
|
||||
final IExpressions expressionService = getServicesTracker().getService(IExpressions.class);
|
||||
/*
|
||||
* PREFPAGE : We are using a default format until the preference page is created
|
||||
*
|
||||
* First select the format to be used. This involves checking so see that the preference
|
||||
* page format is supported by the register service. If the format is not supported then
|
||||
* we will pick the first available format.
|
||||
*/
|
||||
|
||||
final String preferencePageFormatId = IFormattedValues.NATURAL_FORMAT;
|
||||
|
||||
expressionService.getAvailableFormattedValues(
|
||||
dmc,
|
||||
new DataRequestMonitor<String[]>(getSession().getExecutor(), null) {
|
||||
@Override
|
||||
public void handleCompleted() {
|
||||
if (!getStatus().isOK()) {
|
||||
handleFailedUpdate(update);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* See if the desired format is supported.
|
||||
*/
|
||||
String[] formatIds = getData();
|
||||
String finalFormatId = IFormattedValues.NATURAL_FORMAT;
|
||||
boolean requestedFormatIsSupported = false;
|
||||
|
||||
for ( String fId : formatIds ) {
|
||||
if ( preferencePageFormatId.equals(fId) ) {
|
||||
// The desired format is supported.
|
||||
|
||||
finalFormatId = preferencePageFormatId;
|
||||
requestedFormatIsSupported = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! requestedFormatIsSupported ) {
|
||||
/*
|
||||
* Desired format is not supported. If there are any formats supported
|
||||
* then use the first available.
|
||||
*/
|
||||
if ( formatIds.length != 0 ) {
|
||||
finalFormatId = formatIds[0];
|
||||
}
|
||||
else {
|
||||
// Expression service does not support any format.
|
||||
|
||||
handleFailedUpdate(update);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Format has been validated. Get the formatted value.
|
||||
*/
|
||||
FormattedValueDMContext valueDmc = expressionService.getFormattedValue(dmc, finalFormatId);
|
||||
|
||||
expressionService.getModelData(
|
||||
valueDmc,
|
||||
new DataRequestMonitor<FormattedValueDMData>(getSession().getExecutor(), null) {
|
||||
@Override
|
||||
public void handleCompleted() {
|
||||
if (!getStatus().isOK()) {
|
||||
handleFailedUpdate(update);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill the label/column with the properly formatted data value.
|
||||
*/
|
||||
update.setLabel(getData().getFormattedValue(), labelIndex);
|
||||
update.done();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void updateElementsInSessionThread(final IChildrenUpdate update) {
|
||||
|
||||
// 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 ISymbolDMContext symbolDmc =
|
||||
// findDmcInPath(update.getElementPath(), ISymbolDMContext.class);
|
||||
|
||||
// Get the services we need to use.
|
||||
|
||||
final IExpressions expressionService = getServicesTracker().getService(IExpressions.class);
|
||||
final IStack stackFrameService = getServicesTracker().getService(IStack.class);
|
||||
|
||||
if (execDmc == null || frameDmc == null || expressionService == null || stackFrameService == null) {
|
||||
handleFailedUpdate(update);
|
||||
return;
|
||||
}
|
||||
|
||||
final DsfExecutor dsfExecutor = getSession().getExecutor();
|
||||
|
||||
// Call IStack.getLocals() to get an array of IVariableDMContext objects representing the local
|
||||
// variables in the stack frame represented by frameDmc.
|
||||
|
||||
final DataRequestMonitor<IVariableDMContext[]> rm =
|
||||
new DataRequestMonitor<IVariableDMContext[]>(dsfExecutor, null) {
|
||||
@Override
|
||||
public void handleCompleted() {
|
||||
if (!getStatus().isOK()) {
|
||||
handleFailedUpdate(update);
|
||||
return;
|
||||
}
|
||||
|
||||
// For each IVariableDMContext object returned by IStack.getLocals(), call
|
||||
// MIStackFrameService.getModelData() to get the IVariableDMData object. This requires
|
||||
// a MultiRequestMonitor object.
|
||||
|
||||
// First, get the data model context objects for the local variables.
|
||||
|
||||
IVariableDMContext[] localsDMCs = getData();
|
||||
|
||||
if (localsDMCs == null) {
|
||||
handleFailedUpdate(update);
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a List in which we store the DM data objects for the local variables. This is
|
||||
// necessary because there is no MultiDataRequestMonitor. :)
|
||||
|
||||
final List<IVariableDMData> localsDMData = new ArrayList<IVariableDMData>();
|
||||
|
||||
// Create the MultiRequestMonitor to handle completion of the set of getModelData() calls.
|
||||
|
||||
final MultiRequestMonitor<DataRequestMonitor<IVariableDMData>> mrm =
|
||||
new MultiRequestMonitor<DataRequestMonitor<IVariableDMData>>(dsfExecutor, null) {
|
||||
@Override
|
||||
public void handleCompleted() {
|
||||
// Now that all the calls to getModelData() are complete, we create an
|
||||
// IExpressionDMContext object for each local variable name, saving them all
|
||||
// in an array.
|
||||
|
||||
IExpressionDMContext[] expressionDMCs = new IExpressionDMContext[localsDMData.size()];
|
||||
|
||||
int i = 0;
|
||||
|
||||
for (IVariableDMData localDMData : localsDMData) {
|
||||
expressionDMCs[i++] = expressionService.createExpression(frameDmc, localDMData.getName());
|
||||
}
|
||||
|
||||
// Lastly, we fill the update from the array of view model context objects
|
||||
// that reference the ExpressionDMC objects for the local variables. This is
|
||||
// the last code to run for a given call to updateElementsInSessionThread().
|
||||
// We can now leave anonymous-inner-class hell.
|
||||
|
||||
fillUpdateWithVMCs(update, expressionDMCs);
|
||||
update.done();
|
||||
}
|
||||
};
|
||||
|
||||
// Perform a set of getModelData() calls, one for each local variable's data model
|
||||
// context object. In the handleCompleted() method of the DataRequestMonitor, add the
|
||||
// IVariableDMData object to the localsDMData List for later processing (see above).
|
||||
|
||||
for (IVariableDMContext localDMC : localsDMCs) {
|
||||
DataRequestMonitor<IVariableDMData> rm =
|
||||
new DataRequestMonitor<IVariableDMData>(dsfExecutor, null) {
|
||||
@Override
|
||||
public void handleCompleted() {
|
||||
localsDMData.add(getData());
|
||||
mrm.requestMonitorDone(this);
|
||||
}
|
||||
};
|
||||
|
||||
mrm.add(rm);
|
||||
|
||||
stackFrameService.getModelData(localDMC, rm);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Make the asynchronous call to IStack.getLocals(). The results are processed in the
|
||||
// DataRequestMonitor.handleCompleted() above.
|
||||
|
||||
stackFrameService.getLocals(frameDmc, rm);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getNodeDeltaFlagsForDMEvent(IDMEvent<?> e) {
|
||||
if (e instanceof IRunControl.ISuspendedDMEvent) {
|
||||
return IModelDelta.CONTENT;
|
||||
// } else if (e instanceof IRegisters.IRegisterChangedDMEvent) {
|
||||
// return IModelDelta.STATE;
|
||||
}
|
||||
return IModelDelta.NO_CHANGE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void buildDeltaForDMEvent(IDMEvent<?> e, VMDelta parent,
|
||||
int nodeOffset, RequestMonitor requestMonitor) {
|
||||
if (e instanceof IRunControl.ISuspendedDMEvent) {
|
||||
// Create a delta that the whole register group has changed.
|
||||
parent.addFlags(IModelDelta.CONTENT);
|
||||
}
|
||||
// if (e instanceof IRegisters.IRegisterChangedDMEvent) {
|
||||
// parent.addNode(new
|
||||
// DMVMContext(((IRegisters.IRegisterChangedDMEvent)e).getDMContext()),
|
||||
// IModelDelta.STATE);
|
||||
// }
|
||||
super.buildDeltaForDMEvent(e, parent, nodeOffset, requestMonitor);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,297 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2006 Wind River Systems and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Wind River Systems - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.dd.dsf.debug.ui.viewmodel.variable;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.dd.dsf.concurrent.DsfExecutor;
|
||||
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.dd.dsf.datamodel.IDMEvent;
|
||||
import org.eclipse.dd.dsf.datamodel.IDMService;
|
||||
import org.eclipse.dd.dsf.debug.service.IExpressions;
|
||||
import org.eclipse.dd.dsf.debug.service.IFormattedValues;
|
||||
import org.eclipse.dd.dsf.debug.service.IRunControl;
|
||||
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.IRunControl.IExecutionDMContext;
|
||||
import org.eclipse.dd.dsf.debug.service.IStack.IFrameDMContext;
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.IDebugVMConstants;
|
||||
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.IVMLayoutNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.VMDelta;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.AbstractDMVMLayoutNode;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
|
||||
|
||||
@SuppressWarnings("restriction")
|
||||
public class VariableSubExpressionsLayoutNode extends AbstractDMVMLayoutNode<IExpressionDMData> {
|
||||
|
||||
public VariableSubExpressionsLayoutNode(AbstractVMProvider provider, DsfSession session) {
|
||||
super(provider, session, IExpressions.IExpressionDMContext.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* List of child nodes containing only a reference to this. This is what enables the view model
|
||||
* provider to know about the recursive nature of subexpression nodes.
|
||||
*/
|
||||
private final IVMLayoutNode[] fChildLayoutNodes = { this };
|
||||
|
||||
@Override
|
||||
public IVMLayoutNode[] getChildLayoutNodes() {
|
||||
return fChildLayoutNodes;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* We override this method because we now need to perform an extra level of data fetch to get the
|
||||
* formatted value of the expression.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
@Override
|
||||
protected void updateLabelInSessionThread(ILabelUpdate[] updates) {
|
||||
for (final ILabelUpdate update : updates) {
|
||||
|
||||
final IExpressionDMContext dmc = findDmcInPath(update.getElementPath(), IExpressions.IExpressionDMContext.class);
|
||||
|
||||
((IDMService)getServicesTracker().getService(null, dmc.getServiceFilter())).getModelData(
|
||||
dmc,
|
||||
new DataRequestMonitor<IExpressionDMData>(getSession().getExecutor(), null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
// Check that the request was evaluated and data is still valid. The request could
|
||||
// fail if the state of the service changed during the request, but the view model
|
||||
// has not been updated yet.
|
||||
|
||||
if (!getStatus().isOK() || !getData().isValid()) {
|
||||
assert getStatus().isOK() ||
|
||||
getStatus().getCode() != IDsfService.INTERNAL_ERROR ||
|
||||
getStatus().getCode() != IDsfService.NOT_SUPPORTED;
|
||||
handleFailedUpdate(update);
|
||||
return;
|
||||
}
|
||||
|
||||
// If columns are configured, extract the selected values for each understood column.
|
||||
// First, we fill all of those columns which can be filled without extra data mining.
|
||||
// We also note if we do have to do extra data mining. Any columns need to set the
|
||||
// processing flag so we know we have further work to do. If there are more columns
|
||||
// which need data extraction they need to be added in both "for" loops.
|
||||
|
||||
String[] localColumns = update.getPresentationContext().getColumns();
|
||||
if (localColumns == null)
|
||||
localColumns = new String[] { null };
|
||||
|
||||
boolean weAreExtractingFormattedData = false;
|
||||
|
||||
for (int idx = 0; idx < localColumns.length; idx++) {
|
||||
if (IDebugVMConstants.COLUMN_ID__NAME.equals(localColumns[idx])) {
|
||||
update.setLabel(getData().getName(), idx);
|
||||
} else if (IDebugVMConstants.COLUMN_ID__VALUE.equals(localColumns[idx])) {
|
||||
weAreExtractingFormattedData = true;
|
||||
} else if (IDebugVMConstants.COLUMN_ID__DESCRIPTION.equals(localColumns[idx])) {
|
||||
update.setLabel("", idx); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! weAreExtractingFormattedData ) {
|
||||
update.done();
|
||||
} else {
|
||||
for (int idx = 0; idx < localColumns.length; idx++) {
|
||||
if (IDebugVMConstants.COLUMN_ID__VALUE.equals(localColumns[idx])) {
|
||||
updateFormattedExpressionValue(update, idx, dmc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Private data access routine which performs the extra level of data access needed to
|
||||
* get the formatted data value for a specific register.
|
||||
*/
|
||||
private void updateFormattedExpressionValue(final ILabelUpdate update, final int labelIndex,
|
||||
final IExpressionDMContext dmc)
|
||||
{
|
||||
final IExpressions expressionService = getServicesTracker().getService(IExpressions.class);
|
||||
/*
|
||||
* PREFPAGE : We are using a default format until the preference page is created
|
||||
*
|
||||
* First select the format to be used. This involves checking so see that the preference
|
||||
* page format is supported by the register service. If the format is not supported then
|
||||
* we will pick the first available format.
|
||||
*/
|
||||
|
||||
final String preferencePageFormatId = IFormattedValues.NATURAL_FORMAT;
|
||||
|
||||
expressionService.getAvailableFormattedValues(
|
||||
dmc,
|
||||
new DataRequestMonitor<String[]>(getSession().getExecutor(), null) {
|
||||
@Override
|
||||
public void handleCompleted() {
|
||||
if (!getStatus().isOK()) {
|
||||
handleFailedUpdate(update);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* See if the desired format is supported.
|
||||
*/
|
||||
String[] formatIds = getData();
|
||||
String finalFormatId = IFormattedValues.NATURAL_FORMAT;
|
||||
boolean requestedFormatIsSupported = false;
|
||||
|
||||
for ( String fId : formatIds ) {
|
||||
if ( preferencePageFormatId.equals(fId) ) {
|
||||
// The desired format is supported.
|
||||
|
||||
finalFormatId = preferencePageFormatId;
|
||||
requestedFormatIsSupported = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! requestedFormatIsSupported ) {
|
||||
/*
|
||||
* Desired format is not supported. If there are any formats supported
|
||||
* then use the first available.
|
||||
*/
|
||||
if ( formatIds.length != 0 ) {
|
||||
finalFormatId = formatIds[0];
|
||||
}
|
||||
else {
|
||||
// Expression service does not support any format.
|
||||
|
||||
handleFailedUpdate(update);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Format has been validated. Get the formatted value.
|
||||
*/
|
||||
FormattedValueDMContext valueDmc = expressionService.getFormattedValue(dmc, finalFormatId);
|
||||
|
||||
expressionService.getModelData(
|
||||
valueDmc,
|
||||
new DataRequestMonitor<FormattedValueDMData>(getSession().getExecutor(), null) {
|
||||
@Override
|
||||
public void handleCompleted() {
|
||||
if (!getStatus().isOK()) {
|
||||
handleFailedUpdate(update);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill the label/column with the properly formatted data value.
|
||||
*/
|
||||
update.setLabel(getData().getFormattedValue(), labelIndex);
|
||||
update.done();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void updateElementsInSessionThread(final IChildrenUpdate update) {
|
||||
// Get the data model context object for the current node in the hierarchy.
|
||||
|
||||
final IExpressionDMContext expressionDMC = findDmcInPath(update.getElementPath(), IExpressionDMContext.class);
|
||||
|
||||
// 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 ISymbolDMContext symbolDmc = findDmcInPath(update.getElementPath(), ISymbolDMContext.class);
|
||||
|
||||
// Get the services we need to use.
|
||||
|
||||
final IExpressions expressionService = getServicesTracker().getService(IExpressions.class);
|
||||
|
||||
if (execDmc == null || frameDmc == null || expressionService == null) {
|
||||
handleFailedUpdate(update);
|
||||
return;
|
||||
}
|
||||
|
||||
final DsfExecutor dsfExecutor = getSession().getExecutor();
|
||||
|
||||
// Call IExpressions.getSubExpressions() to get an Iterable of IExpressionDMContext objects representing
|
||||
// the sub-expressions of the expression represented by the current expression node.
|
||||
|
||||
final DataRequestMonitor<Iterable<IExpressionDMContext>> rm =
|
||||
new DataRequestMonitor<Iterable<IExpressionDMContext>>(dsfExecutor, null) {
|
||||
@Override
|
||||
public void handleCompleted() {
|
||||
if (!getStatus().isOK()) {
|
||||
handleFailedUpdate(update);
|
||||
return;
|
||||
}
|
||||
|
||||
// Fill the update with the the IExpressionDMContext objects returned by
|
||||
// IExpressions.getSubExpressions().
|
||||
|
||||
List<IExpressionDMContext> subExpressionDMCList = (List<IExpressionDMContext>)getData();
|
||||
IExpressionDMContext[] subExpressionDMCArray = new IExpressionDMContext[subExpressionDMCList.size()];
|
||||
Iterator<IExpressionDMContext> iter = subExpressionDMCList.iterator();
|
||||
|
||||
int i = 0;
|
||||
while (iter.hasNext()) {
|
||||
subExpressionDMCArray[i++] = iter.next();
|
||||
}
|
||||
|
||||
fillUpdateWithVMCs(update, subExpressionDMCArray);
|
||||
update.done();
|
||||
}
|
||||
};
|
||||
|
||||
// Make the asynchronous call to IExpressions.getSubExpressions(). The results are processed in the
|
||||
// DataRequestMonitor.handleCompleted() above.
|
||||
|
||||
expressionService.getSubExpressions(expressionDMC, rm);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getNodeDeltaFlagsForDMEvent(IDMEvent<?> e) {
|
||||
if (e instanceof IRunControl.ISuspendedDMEvent) {
|
||||
return IModelDelta.CONTENT;
|
||||
// } else if (e instanceof IRegisters.IExpressionsChangedDMEvent) {
|
||||
// return IModelDelta.STATE;
|
||||
}
|
||||
return IModelDelta.NO_CHANGE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void buildDeltaForDMEvent(IDMEvent<?> e, VMDelta parent, int nodeOffset, RequestMonitor requestMonitor) {
|
||||
if (e instanceof IRunControl.ISuspendedDMEvent) {
|
||||
// Create a delta that the whole register group has changed.
|
||||
parent.addFlags(IModelDelta.CONTENT);
|
||||
}
|
||||
// if (e instanceof IRegisters.IRegisterChangedDMEvent) {
|
||||
// parent.addNode( new DMVMContext(((IRegisters.IRegisterChangedDMEvent)e).getDMContext()), IModelDelta.STATE );
|
||||
// }
|
||||
super.buildDeltaForDMEvent(e, parent, nodeOffset, requestMonitor);
|
||||
}
|
||||
}
|
|
@ -1,13 +1,11 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2006 Wind River Systems 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
|
||||
/**
|
||||
* Copyright (c) 2006 Wind River Systems and others. All rights reserved. This program and
|
||||
* the accompanying materials are made available under the terms of the Eclipse Public
|
||||
* License v1.0 which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Wind River Systems - initial API and implementation
|
||||
*******************************************************************************/
|
||||
* Contributors: Wind River Systems - initial API and implementation
|
||||
*/
|
||||
package org.eclipse.dd.dsf.debug.ui.viewmodel.variable;
|
||||
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.DebugViewSelectionRootLayoutNode;
|
||||
|
@ -17,19 +15,37 @@ import org.eclipse.dd.dsf.ui.viewmodel.IVMLayoutNode;
|
|||
import org.eclipse.dd.dsf.ui.viewmodel.IVMRootLayoutNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.AbstractDMVMProvider;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentation;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentationFactory;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
public class VariableVMProvider extends AbstractDMVMProvider {
|
||||
public VariableVMProvider(AbstractVMAdapter adapter, IPresentationContext context, DsfSession session) {
|
||||
public class VariableVMProvider extends AbstractDMVMProvider implements
|
||||
IColumnPresentationFactory {
|
||||
|
||||
public VariableVMProvider(AbstractVMAdapter adapter, IPresentationContext context, DsfSession session) {
|
||||
super(adapter, context, session);
|
||||
IVMRootLayoutNode debugViewSelectionNode = new DebugViewSelectionRootLayoutNode(this);
|
||||
IVMLayoutNode localsNode = new LocalsLayoutNode(this, getSession());
|
||||
debugViewSelectionNode.setChildNodes(new IVMLayoutNode[] { localsNode });
|
||||
setRootLayoutNode(debugViewSelectionNode);
|
||||
|
||||
/*
|
||||
* Create the top level node to deal with the root selection.
|
||||
*/
|
||||
IVMRootLayoutNode debugViewSelection = new DebugViewSelectionRootLayoutNode(this);
|
||||
|
||||
/*
|
||||
* Create the local variables nodes next. They represent the first level shown in the view.
|
||||
*/
|
||||
IVMLayoutNode localsNode = new VariableLocalsLayoutNode(this, getSession());
|
||||
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());
|
||||
localsNode.setChildNodes(new IVMLayoutNode[] { subExpressioNode });
|
||||
|
||||
/*
|
||||
* Now set this schema set as the layout set.
|
||||
*/
|
||||
setRootLayoutNode(debugViewSelection);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
Loading…
Add table
Reference in a new issue