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.
|
* Copyright (c) 2006 Wind River Systems and others. All rights reserved. This program and
|
||||||
* All rights reserved. This program and the accompanying materials
|
* the accompanying materials are made available under the terms of the Eclipse Public
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* License v1.0 which accompanies this distribution, and is available at
|
||||||
* which accompanies this distribution, and is available at
|
|
||||||
* http://www.eclipse.org/legal/epl-v10.html
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
*
|
*
|
||||||
* Contributors:
|
* Contributors: Wind River Systems - initial API and implementation
|
||||||
* Wind River Systems - initial API and implementation
|
*/
|
||||||
*******************************************************************************/
|
|
||||||
package org.eclipse.dd.dsf.debug.ui.viewmodel.variable;
|
package org.eclipse.dd.dsf.debug.ui.viewmodel.variable;
|
||||||
|
|
||||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.DebugViewSelectionRootLayoutNode;
|
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.IVMRootLayoutNode;
|
||||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.AbstractDMVMProvider;
|
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.IColumnPresentation;
|
||||||
|
import org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentationFactory;
|
||||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
|
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("restriction")
|
@SuppressWarnings("restriction")
|
||||||
public class VariableVMProvider extends AbstractDMVMProvider {
|
public class VariableVMProvider extends AbstractDMVMProvider implements
|
||||||
|
IColumnPresentationFactory {
|
||||||
|
|
||||||
public VariableVMProvider(AbstractVMAdapter adapter, IPresentationContext context, DsfSession session) {
|
public VariableVMProvider(AbstractVMAdapter adapter, IPresentationContext context, DsfSession session) {
|
||||||
super(adapter, context, session);
|
super(adapter, context, session);
|
||||||
IVMRootLayoutNode debugViewSelectionNode = new DebugViewSelectionRootLayoutNode(this);
|
|
||||||
IVMLayoutNode localsNode = new LocalsLayoutNode(this, getSession());
|
/*
|
||||||
debugViewSelectionNode.setChildNodes(new IVMLayoutNode[] { localsNode });
|
* Create the top level node to deal with the root selection.
|
||||||
setRootLayoutNode(debugViewSelectionNode);
|
*/
|
||||||
|
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
|
@Override
|
||||||
|
|
Loading…
Add table
Reference in a new issue