From 283f86d8d961184f6220869fcb76a77e3ce16483 Mon Sep 17 00:00:00 2001 From: Marc Khouzam Date: Wed, 16 Apr 2014 14:17:59 -0400 Subject: [PATCH] Bug 393930 - Unable to examine a sub-expression using "watch" Change-Id: Ib8bde486546eef00440a8ef8f1ee05cfe7da48db Signed-off-by: Marc Khouzam Reviewed-on: https://git.eclipse.org/r/24299 Tested-by: Hudson CI --- .../cdt/dsf/mi/service/MIVariableManager.java | 8 +- .../dsf/gdb/tests/MIExpressionsTest.java | 85 +++++++++++++++++++ 2 files changed, 92 insertions(+), 1 deletion(-) diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIVariableManager.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIVariableManager.java index be77fa06dd1..ae82b13282b 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIVariableManager.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIVariableManager.java @@ -2688,10 +2688,16 @@ public class MIVariableManager implements ICommandControl { MIExpressionDMC miExprCtx = (MIExpressionDMC) exprCtx; ExpressionInfo ctxExprInfo = miExprCtx.getExpressionInfo(); ExpressionInfo varExprInfo = varObj.getExpressionInfo(); + // Don't use equals() below because we are concerned with other fields + // of ExpressionInfo that are not considered when doing equals(). + // Instead, only consider equal if both objects are the same one if (ctxExprInfo != varExprInfo) { // exprCtrx could just be created via IExpressions.createExpression, // and thus the parent-child relationship is not yet set. - miExprCtx.setExpressionInfo(varExprInfo); + // Set that relationship while keeping the relative expression of + // the original context (see bug 393930) + miExprCtx.setExpressionInfo(new ExpressionInfo(miExprCtx.getExpression(), miExprCtx.getRelativeExpression(), + varExprInfo.isDynamic(), varExprInfo.getParent(), varExprInfo.getIndexInParentExpression())); } rm.setData(varObj); diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/MIExpressionsTest.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/MIExpressionsTest.java index 5e899771338..229211f6a2e 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/MIExpressionsTest.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/MIExpressionsTest.java @@ -43,6 +43,7 @@ import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext; import org.eclipse.cdt.dsf.debug.service.IStack.IVariableDMData; import org.eclipse.cdt.dsf.mi.service.ClassAccessor.MIExpressionDMCAccessor; import org.eclipse.cdt.dsf.mi.service.MIExpressions; +import org.eclipse.cdt.dsf.mi.service.MIExpressions.MIExpressionDMC; import org.eclipse.cdt.dsf.mi.service.command.events.MIStoppedEvent; import org.eclipse.cdt.dsf.service.DsfServiceEventHandler; import org.eclipse.cdt.dsf.service.DsfServicesTracker; @@ -4178,6 +4179,90 @@ public class MIExpressionsTest extends BaseTestCase { assertEquals("8", value); } + /** + * This tests verifies that we can manually create a child of an expression + * after that child was automatically created through the parent. + * This case happens when selecting a child of an expression and using "Watch" + * to create an expression automatically. + */ + @Test + public void testExplicitChildCreation() throws Throwable { + SyncUtil.runToLocation("testExistingChild"); + MIStoppedEvent stoppedEvent = SyncUtil.step(1, StepType.STEP_OVER); + IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0); + + final String PARENT_EXPR = "b"; + final String CHILD_EXPR = "((b).d)"; + final String CHILD__REL_EXPR = "d"; + + // First fetch the child through its parent + final IExpressionDMContext parentDmc = SyncUtil.createExpression(frameDmc, PARENT_EXPR); + Query query = new Query() { + @Override + protected void execute(final DataRequestMonitor rm) { + fExpService.getSubExpressions( + parentDmc, + new ImmediateDataRequestMonitor(rm) { + @Override + protected void handleSuccess() { + if (getData().length != 2) { + rm.done(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID, + "Wrong number for children. Expecting 2 but got " + getData().length, null)); + return; + } + + MIExpressionDMC firstChildContext = (MIExpressionDMC)getData()[0]; + if (firstChildContext.getExpression().equals(CHILD_EXPR) == false) { + rm.done(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID, + "Got wrong first child. Expected " + CHILD_EXPR + " but got " + firstChildContext.getExpression(), null)); + return; + } + + if (firstChildContext.getRelativeExpression().equals(CHILD__REL_EXPR) == false) { + rm.done(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID, + "Got wrong relative expression. Expected " + CHILD__REL_EXPR + " but got " + firstChildContext.getRelativeExpression(), null)); + return; + } + + fExpService.getFormattedExpressionValue( + fExpService.getFormattedValueContext(firstChildContext, IFormattedValues.NATURAL_FORMAT), + new ImmediateDataRequestMonitor(rm) { + @Override + protected void handleSuccess() { + rm.done(getData().getFormattedValue()); + } + }); + + } + }); + } + }; + + fSession.getExecutor().execute(query); + String value = query.get(500, TimeUnit.MILLISECONDS); + assertEquals("8", value); + + // Now access the child directly + final IExpressionDMContext childDmc = SyncUtil.createExpression(frameDmc, CHILD_EXPR); + query = new Query() { + @Override + protected void execute(final DataRequestMonitor rm) { + fExpService.getFormattedExpressionValue( + fExpService.getFormattedValueContext(childDmc, IFormattedValues.NATURAL_FORMAT), + new ImmediateDataRequestMonitor(rm) { + @Override + protected void handleSuccess() { + rm.done(getData().getFormattedValue()); + } + }); + } + }; + + fSession.getExecutor().execute(query); + value = query.get(500, TimeUnit.MILLISECONDS); + assertEquals("8", value); + } + protected int getChildrenCount(final IExpressionDMContext parentDmc, final int expectedCount) throws Throwable { final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();