Skip to content

Commit dc07d1d

Browse files
committed
Fix recursive {this} evaluation in Natvis
This PR addresses the issue where using `this` in natvis causes it to recursively evaluate. Added a check during evaluation if the name is this, special case to just return as is instead of contuining recursing. Added tests to handle the case. Addresses #1391
1 parent a1034b0 commit dc07d1d

File tree

5 files changed

+67
-2
lines changed

5 files changed

+67
-2
lines changed

src/MIDebugEngine/Natvis.Impl/Natvis.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1439,6 +1439,13 @@ private string GetExpressionValue(string expression, IVariableInformation variab
14391439
string processedExpr = ReplaceNamesInExpression(expression, variable, scopedNames);
14401440
IVariableInformation expressionVariable = new VariableInformation(processedExpr, variable, _process.Engine, null);
14411441
expressionVariable.SyncEval();
1442+
1443+
// Avoid recursive natvis formatting when expression is 'this'
1444+
if (expression.Trim() == "this")
1445+
{
1446+
return expressionVariable.Value;
1447+
}
1448+
14421449
return FormatDisplayString(expressionVariable).value;
14431450
}
14441451

test/CppTests/Tests/NatvisTests.cs

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ public NatvisTests(ITestOutputHelper outputHelper) : base(outputHelper)
3838
private const string NatvisSourceName = "main.cpp";
3939

4040
// These line numbers will need to change if src/natvis/main.cpp changes
41-
private const int SimpleClassAssignmentLine = 48;
42-
private const int ReturnSourceLine = 57;
41+
private const int SimpleClassAssignmentLine = 49;
42+
private const int ReturnSourceLine = 61;
4343

4444
[Theory]
4545
[RequiresTestSettings]
@@ -397,6 +397,47 @@ public void TestThisConditional(ITestSettings settings)
397397
}
398398
}
399399

400+
[Theory]
401+
[DependsOnTest(nameof(CompileNatvisDebuggee))]
402+
[RequiresTestSettings]
403+
public void TestThisInDisplayString(ITestSettings settings)
404+
{
405+
this.TestPurpose("This test checks that {this} in a DisplayString value does not produce extra braces.");
406+
this.WriteSettings(settings);
407+
408+
IDebuggee debuggee = Debuggee.Open(this, settings.CompilerSettings, NatvisName, DebuggeeMonikers.Natvis.Default);
409+
410+
using (IDebuggerRunner runner = CreateDebugAdapterRunner(settings))
411+
{
412+
this.Comment("Configure launch");
413+
string visFile = Path.Join(debuggee.SourceRoot, "visualizer_files", "Simple.natvis");
414+
415+
LaunchCommand launch = new LaunchCommand(settings.DebuggerSettings, debuggee.OutputPath, visFile, false);
416+
runner.RunCommand(launch);
417+
418+
this.Comment("Set Breakpoint");
419+
SourceBreakpoints writerBreakpoints = debuggee.Breakpoints(NatvisSourceName, ReturnSourceLine);
420+
runner.SetBreakpoints(writerBreakpoints);
421+
422+
runner.Expects.StoppedEvent(StoppedReason.Breakpoint).AfterConfigurationDone();
423+
424+
using (IThreadInspector threadInspector = runner.GetThreadInspector())
425+
{
426+
IFrameInspector currentFrame = threadInspector.Stack.First();
427+
428+
this.Comment("Verifying {this} in DisplayString does not recurse");
429+
var dpPtr = currentFrame.GetVariable("dpPtr");
430+
431+
// Natvis: <DisplayString>{{ {this}={*this} }}</DisplayString>
432+
// Expected: "{ 0x<hex_address>=42 }" — {this} is the raw address, {*this} is the dereferenced value
433+
Assert.Matches(@"^\{ 0x[0-9a-fA-F]+=42 \}$", dpPtr.Value);
434+
}
435+
436+
runner.Expects.ExitedEvent(exitCode: 0).TerminatedEvent().AfterContinue();
437+
runner.DisconnectAndVerify();
438+
}
439+
}
440+
400441
[Theory]
401442
[DependsOnTest(nameof(CompileNatvisDebuggee))]
402443
[RequiresTestSettings]
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
struct DataPoint
2+
{
3+
int value;
4+
DataPoint(int v) : value(v) {}
5+
};

test/CppTests/debuggees/natvis/src/main.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "SimpleClass.h"
66
#include "SimpleMatrix.h"
77
#include "SimpleTemplated.h"
8+
#include "DataPoint.h"
89

910
class SimpleDisplayObject
1011
{
@@ -54,5 +55,8 @@ int main(int argc, char** argv)
5455
SimpleMap<double, char, int> genericMap(2.71, 'x', 5);
5556
SimpleMap<int, double, int> intKeyMap(7, 1.618, 3);
5657

58+
DataPoint dp(42);
59+
DataPoint *dpPtr = &dp;
60+
5761
return 0;
5862
}

test/CppTests/debuggees/natvis/src/visualizer_files/Simple.natvis

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,4 +97,12 @@
9797
<DisplayString>{{ size={_size} (int-keyed) }}</DisplayString>
9898
</Type>
9999

100+
<Type Name="DataPoint">
101+
<DisplayString>{value}</DisplayString>
102+
</Type>
103+
104+
<Type Name="DataPoint *">
105+
<DisplayString>{{ {this}={*this} }}</DisplayString>
106+
</Type>
107+
100108
</AutoVisualizer>

0 commit comments

Comments
 (0)