mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-23 14:42:11 +02:00
[304588] Return the problem number of children even if GDB counts private/public/protected as a level of children.
This commit is contained in:
parent
f642b20a88
commit
20baa38a22
4 changed files with 254 additions and 25 deletions
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2010 Wind River Systems and others.
|
||||
* Copyright (c) 2006, 2010 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
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2010 Monta Vista and others.
|
||||
* Copyright (c) 2008, 2010 Monta Vista 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
|
||||
|
@ -210,7 +210,10 @@ public class MIVariableManager implements ICommandControl {
|
|||
private String fullExp = null;
|
||||
private String type = null;
|
||||
private GDBType gdbType;
|
||||
private int numChildren = 0;
|
||||
// A hint at the number of children. This value is obtained
|
||||
// from -var-create or -var-list-children. It may not be right in the case
|
||||
// of C++ structures, where GDB has a level of children for private/public/protected.
|
||||
private int numChildrenHint = 0;
|
||||
private Boolean editable = null;
|
||||
|
||||
// The current values of the expression for each format. (null if not known yet)
|
||||
|
@ -260,7 +263,33 @@ public class MIVariableManager implements ICommandControl {
|
|||
|
||||
/** @since 3.0 */
|
||||
public GDBType getGDBType() { return gdbType; }
|
||||
public int getNumChildren() { return numChildren; }
|
||||
/**
|
||||
* Returns a hint to the number of children. This hint is often correct,
|
||||
* except when we are dealing with C++ complex structures where
|
||||
* GDB has 'private/public/protected' as children.
|
||||
*
|
||||
* Use <code>isNumChildrenHintTrustworthy()</code> to know if the
|
||||
* hint can be trusted.
|
||||
*
|
||||
* Note that a hint of 0 children can always be trusted.
|
||||
*
|
||||
* @since 3.0 */
|
||||
public int getNumChildrenHint() { return numChildrenHint; }
|
||||
/**
|
||||
* Returns whether the number of children hint can be
|
||||
* trusted for this variable object.
|
||||
*
|
||||
* @since 3.0
|
||||
*/
|
||||
public boolean isNumChildrenHintTrustworthy() {
|
||||
// For complex structures which are not arrays, we cannot trust the hint.
|
||||
// This is only valid for C++, so we should even check for it using
|
||||
// -var-info-expression. Do we have to use -var-info-expression for each
|
||||
// variable object, or can we do it one time ony for the whole program?
|
||||
// Right now, we always assume we could be using C++
|
||||
return (!isComplex() || isArray());
|
||||
}
|
||||
|
||||
public String getValue(String format) { return valueMap.get(format); }
|
||||
|
||||
public ExpressionInfo[] getChildren() { return children; }
|
||||
|
@ -270,8 +299,9 @@ public class MIVariableManager implements ICommandControl {
|
|||
public boolean isPointer() { return (getGDBType() == null) ? false : getGDBType().getType() == GDBType.POINTER; }
|
||||
public boolean isMethod() { return (getGDBType() == null) ? false : getGDBType().getType() == GDBType.FUNCTION; }
|
||||
// A complex variable is one with children. However, it must not be a pointer since a pointer has one child
|
||||
// according to GDB, but is still a 'simple' variable
|
||||
public boolean isComplex() { return (getGDBType() == null) ? false : getGDBType().getType() != GDBType.POINTER && getNumChildren() > 0; }
|
||||
// according to GDB, but is still a 'simple' variable.
|
||||
// Note that the numChildrenHint can be trusted when asking if the number of children is 0 or not
|
||||
public boolean isComplex() { return (getGDBType() == null) ? false : getGDBType().getType() != GDBType.POINTER && getNumChildrenHint() > 0; }
|
||||
|
||||
public void setGdbName(String n) { gdbName = n; }
|
||||
public void setCurrentFormat(String f) { format = f; }
|
||||
|
@ -280,7 +310,7 @@ public class MIVariableManager implements ICommandControl {
|
|||
fullExp = fullExpression;
|
||||
type = t;
|
||||
gdbType = fGDBTypeParser.parse(t);
|
||||
numChildren = num;
|
||||
numChildrenHint = num;
|
||||
}
|
||||
|
||||
public void setValue(String format, String val) { valueMap.put(format, val); }
|
||||
|
@ -591,7 +621,9 @@ public class MIVariableManager implements ICommandControl {
|
|||
}
|
||||
|
||||
// If the variable does not have children, we can return an empty list right away
|
||||
if (getNumChildren() == 0) {
|
||||
// The numChildrenHint value is trustworthy when wanting to know if there are children
|
||||
// at all.
|
||||
if (getNumChildrenHint() == 0) {
|
||||
// First store the empty list, for the next time
|
||||
setChildren(new ExpressionInfo[0]);
|
||||
rm.setData(getChildren());
|
||||
|
@ -604,7 +636,8 @@ public class MIVariableManager implements ICommandControl {
|
|||
// never need. Using -var-list-children will create a variable object for every child
|
||||
// immediately, that is why won't don't want to use it for arrays.
|
||||
if (isArray()) {
|
||||
ExpressionInfo[] childrenOfArray = new ExpressionInfo[getNumChildren()];
|
||||
// We can trust the numChildrenHint value for arrays.
|
||||
ExpressionInfo[] childrenOfArray = new ExpressionInfo[getNumChildrenHint()];
|
||||
for (int i= 0; i < childrenOfArray.length; i++) {
|
||||
String indexStr = "[" + i + "]";//$NON-NLS-1$//$NON-NLS-2$
|
||||
String fullExpr = exprDmc.getExpression() + indexStr;
|
||||
|
@ -794,11 +827,22 @@ public class MIVariableManager implements ICommandControl {
|
|||
* @param rm
|
||||
* The data request monitor that will hold the count of children returned
|
||||
*/
|
||||
private void getChildrenCount(final DataRequestMonitor<Integer> rm) {
|
||||
// No need to lock the object or wait for it to be ready since this operation does not
|
||||
// affect other operations
|
||||
rm.setData(getNumChildren());
|
||||
rm.done();
|
||||
private void getChildrenCount(MIExpressionDMC exprDmc, final DataRequestMonitor<Integer> rm) {
|
||||
if (isNumChildrenHintTrustworthy()){
|
||||
rm.setData(getNumChildrenHint());
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
getChildren(
|
||||
exprDmc,
|
||||
new DataRequestMonitor<ExpressionInfo[]>(fSession.getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
rm.setData(getData().length);
|
||||
rm.done();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
@ -1590,15 +1634,36 @@ public class MIVariableManager implements ICommandControl {
|
|||
new DataRequestMonitor<MIVariableObject>(fSession.getExecutor(), drm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
drm.setData(
|
||||
new ExprMetaGetVarInfo(
|
||||
exprCtx.getRelativeExpression(),
|
||||
getData().getNumChildren(),
|
||||
getData().getType(),
|
||||
getData().getGDBType(),
|
||||
!getData().isComplex()));
|
||||
drm.done();
|
||||
processCommandDone(token, drm.getData());
|
||||
final MIVariableObject varObj = getData();
|
||||
if (varObj.isNumChildrenHintTrustworthy()) {
|
||||
drm.setData(
|
||||
new ExprMetaGetVarInfo(
|
||||
exprCtx.getRelativeExpression(),
|
||||
getData().getNumChildrenHint(),
|
||||
getData().getType(),
|
||||
getData().getGDBType(),
|
||||
!getData().isComplex()));
|
||||
drm.done();
|
||||
processCommandDone(token, drm.getData());
|
||||
} else {
|
||||
// We have to ask for the children count because the hint could be wrong
|
||||
varObj.getChildrenCount(
|
||||
exprCtx,
|
||||
new DataRequestMonitor<Integer>(fSession.getExecutor(), drm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
drm.setData(
|
||||
new ExprMetaGetVarInfo(
|
||||
exprCtx.getRelativeExpression(),
|
||||
getData(),
|
||||
varObj.getType(),
|
||||
varObj.getGDBType(),
|
||||
!varObj.isComplex()));
|
||||
drm.done();
|
||||
processCommandDone(token, drm.getData());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
} else if (command instanceof ExprMetaGetAttributes) {
|
||||
|
@ -1675,7 +1740,7 @@ public class MIVariableManager implements ICommandControl {
|
|||
} else if (command instanceof ExprMetaGetChildCount) {
|
||||
@SuppressWarnings("unchecked")
|
||||
final DataRequestMonitor<ExprMetaGetChildCountInfo> drm = (DataRequestMonitor<ExprMetaGetChildCountInfo>)rm;
|
||||
final IExpressionDMContext exprCtx = (IExpressionDMContext)(command.getContext());
|
||||
final MIExpressionDMC exprCtx = (MIExpressionDMC)(command.getContext());
|
||||
|
||||
getVariable(
|
||||
exprCtx,
|
||||
|
@ -1683,6 +1748,7 @@ public class MIVariableManager implements ICommandControl {
|
|||
@Override
|
||||
protected void handleSuccess() {
|
||||
getData().getChildrenCount(
|
||||
exprCtx,
|
||||
new DataRequestMonitor<Integer>(fSession.getExecutor(), drm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
|
|
|
@ -10,7 +10,13 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.dsf.mi.service;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.cdt.dsf.debug.service.IExpressions.IExpressionDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.IExpressions.IExpressionDMData;
|
||||
import org.eclipse.cdt.dsf.debug.service.IExpressions.IExpressionDMData.BasicType;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterDMContext;
|
||||
import org.eclipse.cdt.dsf.mi.service.MIExpressions.ExpressionDMData;
|
||||
import org.eclipse.cdt.dsf.mi.service.MIExpressions.MIExpressionDMC;
|
||||
|
||||
public class ClassAccessor {
|
||||
|
@ -45,4 +51,69 @@ public class ClassAccessor {
|
|||
return miExprDmc.getRelativeExpression();
|
||||
}
|
||||
}
|
||||
|
||||
public static class ExpressionDMDataAccessor {
|
||||
private ExpressionDMData miExprData;
|
||||
|
||||
public ExpressionDMDataAccessor(IExpressionDMData data) {
|
||||
miExprData = (ExpressionDMData) data;
|
||||
}
|
||||
|
||||
public BasicType getBasicType() {
|
||||
return miExprData.getBasicType();
|
||||
}
|
||||
|
||||
public String getEncoding() {
|
||||
return miExprData.getEncoding();
|
||||
}
|
||||
|
||||
public Map<String, Integer> getEnumerations() {
|
||||
return miExprData.getEnumerations();
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return miExprData.getName();
|
||||
}
|
||||
|
||||
public IRegisterDMContext getRegister() {
|
||||
return miExprData.getRegister();
|
||||
}
|
||||
|
||||
public String getStringValue() {
|
||||
return miExprData.getStringValue();
|
||||
}
|
||||
|
||||
public String getTypeId() {
|
||||
return miExprData.getTypeId();
|
||||
}
|
||||
|
||||
public String getTypeName() {
|
||||
return miExprData.getTypeName();
|
||||
}
|
||||
|
||||
public int getNumChildren() {
|
||||
return miExprData.getNumChildren();
|
||||
}
|
||||
|
||||
public boolean isEditable() {
|
||||
return miExprData.isEditable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
return miExprData.equals(other);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return miExprData.hashCode();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return miExprData.toString();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 Ericsson and others.
|
||||
* Copyright (c) 2007, 2010 Ericsson 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
|
||||
|
@ -32,6 +32,7 @@ import org.eclipse.cdt.dsf.debug.service.IFormattedValues.FormattedValueDMData;
|
|||
import org.eclipse.cdt.dsf.debug.service.IRunControl.StepType;
|
||||
import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext;
|
||||
import org.eclipse.cdt.dsf.mi.service.MIExpressions;
|
||||
import org.eclipse.cdt.dsf.mi.service.ClassAccessor.ExpressionDMDataAccessor;
|
||||
import org.eclipse.cdt.dsf.mi.service.ClassAccessor.MIExpressionDMCAccessor;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.events.MIStoppedEvent;
|
||||
import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
|
||||
|
@ -291,6 +292,97 @@ public class MIExpressionsTest extends BaseTestCase {
|
|||
doTestChildren(stoppedEvent);
|
||||
}
|
||||
|
||||
/**
|
||||
* This test makes sure we get the right number of children.
|
||||
*/
|
||||
@Test
|
||||
public void testChildrenCount() throws Throwable {
|
||||
// Next we test that we can retrieve children count while reading the
|
||||
// value and vice-versa
|
||||
|
||||
SyncUtil.runToLocation("testChildren");
|
||||
MIStoppedEvent stoppedEvent = SyncUtil.step(1, StepType.STEP_OVER);
|
||||
|
||||
final IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);
|
||||
|
||||
final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();
|
||||
|
||||
// First we get the expected value of the array pointer.
|
||||
final IExpressionDMContext exprDmc = SyncUtil.createExpression(frameDmc, "f");
|
||||
|
||||
fExpService.getExecutor().submit(new Runnable() {
|
||||
public void run() {
|
||||
fExpService.getSubExpressionCount(
|
||||
exprDmc,
|
||||
new DataRequestMonitor<Integer>(fExpService.getExecutor(), null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
if (!isSuccess()) {
|
||||
wait.waitFinished(getStatus());
|
||||
} else {
|
||||
int count = getData();
|
||||
if (count != 5) {
|
||||
wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
|
||||
"Failed getting count for children. Got " + count + " instead of 5", null));
|
||||
} else {
|
||||
wait.waitFinished();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
|
||||
assertTrue(wait.getMessage(), wait.isOK());
|
||||
}
|
||||
|
||||
/**
|
||||
* This test makes sure we get the right number of children.
|
||||
*/
|
||||
@Test
|
||||
public void testChildrenCountInExpressionData() throws Throwable {
|
||||
// Next we test that we can retrieve children count while reading the
|
||||
// value and vice-versa
|
||||
|
||||
SyncUtil.runToLocation("testChildren");
|
||||
MIStoppedEvent stoppedEvent = SyncUtil.step(1, StepType.STEP_OVER);
|
||||
|
||||
final IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);
|
||||
|
||||
final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();
|
||||
|
||||
// First we get the expected value of the array pointer.
|
||||
final IExpressionDMContext exprDmc = SyncUtil.createExpression(frameDmc, "f");
|
||||
|
||||
fExpService.getExecutor().submit(new Runnable() {
|
||||
public void run() {
|
||||
fExpService.getExpressionData(
|
||||
exprDmc,
|
||||
new DataRequestMonitor<IExpressionDMData>(fExpService.getExecutor(), null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
if (!isSuccess()) {
|
||||
wait.waitFinished(getStatus());
|
||||
} else {
|
||||
ExpressionDMDataAccessor data = new ExpressionDMDataAccessor(getData());
|
||||
int count = data.getNumChildren();
|
||||
if (count != 5) {
|
||||
wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
|
||||
"Failed getting count for children. Got " + count + " instead of 5", null));
|
||||
} else {
|
||||
wait.waitFinished();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
|
||||
assertTrue(wait.getMessage(), wait.isOK());
|
||||
}
|
||||
|
||||
/**
|
||||
* This test verifies that the ExpressionService can write to a variable.
|
||||
*/
|
||||
|
|
Loading…
Add table
Reference in a new issue