From ddc9fce9fa6b26d122f2c3530fde78923ff74ad5 Mon Sep 17 00:00:00 2001 From: Andrew Wang Date: Sun, 17 May 2026 14:17:07 -0700 Subject: [PATCH] Fix inverted condition check for LinkedListItems in NatVis MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The condition guard was using IsNullOrWhiteSpace instead of !IsNullOrWhiteSpace, which meant LinkedListItems with a Condition attribute were never filtered — items were always shown regardless of the condition value. Added an integration test (TestLinkedListItemsCondition) that creates two ConditionalLinkedList objects — one with isActive=true and one with isActive=false — and verifies that the natvis LinkedListItems Condition attribute is respected. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/MIDebugEngine/Natvis.Impl/Natvis.cs | 2 +- test/CppTests/Tests/NatvisTests.cs | 50 ++++++++++++++++++- .../natvis/src/ConditionalLinkedList.h | 25 ++++++++++ test/CppTests/debuggees/natvis/src/main.cpp | 10 ++++ .../natvis/src/visualizer_files/Simple.natvis | 14 ++++++ 5 files changed, 98 insertions(+), 3 deletions(-) create mode 100644 test/CppTests/debuggees/natvis/src/ConditionalLinkedList.h diff --git a/src/MIDebugEngine/Natvis.Impl/Natvis.cs b/src/MIDebugEngine/Natvis.Impl/Natvis.cs index 010a1ce54..edf7f702a 100755 --- a/src/MIDebugEngine/Natvis.Impl/Natvis.cs +++ b/src/MIDebugEngine/Natvis.Impl/Natvis.cs @@ -789,7 +789,7 @@ private IVariableInformation[] ExpandVisualized(IVariableInformation variable) // m_element // LinkedListItemsType item = (LinkedListItemsType)i; - if (String.IsNullOrWhiteSpace(item.Condition)) + if (!String.IsNullOrWhiteSpace(item.Condition)) { if (!EvalCondition(item.Condition, variable, visualizer.ScopedNames, visualizer.Intrinsics)) continue; diff --git a/test/CppTests/Tests/NatvisTests.cs b/test/CppTests/Tests/NatvisTests.cs index 58b2a2223..46f31299c 100644 --- a/test/CppTests/Tests/NatvisTests.cs +++ b/test/CppTests/Tests/NatvisTests.cs @@ -38,8 +38,8 @@ public NatvisTests(ITestOutputHelper outputHelper) : base(outputHelper) private const string NatvisSourceName = "main.cpp"; // These line numbers will need to change if src/natvis/main.cpp changes - private const int SimpleClassAssignmentLine = 65; - private const int ReturnSourceLine = 80; + private const int SimpleClassAssignmentLine = 66; + private const int ReturnSourceLine = 90; [Theory] [RequiresTestSettings] @@ -674,6 +674,52 @@ public void TestHideRawView(ITestSettings settings) } } + [Theory] + [DependsOnTest(nameof(CompileNatvisDebuggee))] + [RequiresTestSettings] + public void TestLinkedListItemsCondition(ITestSettings settings) + { + this.TestPurpose("This test checks that a Condition attribute on LinkedListItems is evaluated correctly."); + this.WriteSettings(settings); + + IDebuggee debuggee = Debuggee.Open(this, settings.CompilerSettings, NatvisName, DebuggeeMonikers.Natvis.Default); + + using (IDebuggerRunner runner = CreateDebugAdapterRunner(settings)) + { + this.Comment("Configure launch"); + string visFile = Path.Join(debuggee.SourceRoot, "visualizer_files", "Simple.natvis"); + + LaunchCommand launch = new LaunchCommand(settings.DebuggerSettings, debuggee.OutputPath, visFile, false); + runner.RunCommand(launch); + + this.Comment("Set Breakpoint"); + SourceBreakpoints writerBreakpoints = debuggee.Breakpoints(NatvisSourceName, ReturnSourceLine); + runner.SetBreakpoints(writerBreakpoints); + + runner.Expects.StoppedEvent(StoppedReason.Breakpoint).AfterConfigurationDone(); + + using (IThreadInspector threadInspector = runner.GetThreadInspector()) + { + IFrameInspector currentFrame = threadInspector.Stack.First(); + + this.Comment("Verifying LinkedListItems with Condition='isActive' when isActive is true"); + var activeList = currentFrame.GetVariable("activeList"); + Assert.Contains("active=true", activeList.Value); + Assert.Equal("3", activeList.GetVariable("Count").Value); + Assert.True(activeList.Variables.ContainsKey("[0]"), "activeList should show indexed children when condition is true"); + + this.Comment("Verifying LinkedListItems with Condition='isActive' when isActive is false"); + var inactiveList = currentFrame.GetVariable("inactiveList"); + Assert.Contains("active=false", inactiveList.Value); + Assert.Equal("2", inactiveList.GetVariable("Count").Value); + Assert.False(inactiveList.Variables.ContainsKey("[0]"), "inactiveList should not show indexed children when condition is false"); + } + + runner.Expects.ExitedEvent(exitCode: 0).TerminatedEvent().AfterContinue(); + runner.DisconnectAndVerify(); + } + } + #endregion } } diff --git a/test/CppTests/debuggees/natvis/src/ConditionalLinkedList.h b/test/CppTests/debuggees/natvis/src/ConditionalLinkedList.h new file mode 100644 index 000000000..93301010b --- /dev/null +++ b/test/CppTests/debuggees/natvis/src/ConditionalLinkedList.h @@ -0,0 +1,25 @@ +#include + +class ConditionalLinkedList +{ +private: + struct Node { + int data; + Node* next; + Node(int value) : data(value), next(NULL) {} + }; + + Node* head; + int numElements; + bool isActive; + +public: + ConditionalLinkedList(bool active) : head(NULL), numElements(0), isActive(active) {} + + void Add(int val) { + Node* n = new Node(val); + n->next = head; + head = n; + numElements++; + } +}; diff --git a/test/CppTests/debuggees/natvis/src/main.cpp b/test/CppTests/debuggees/natvis/src/main.cpp index 1a578fa08..1216a3e13 100644 --- a/test/CppTests/debuggees/natvis/src/main.cpp +++ b/test/CppTests/debuggees/natvis/src/main.cpp @@ -6,6 +6,7 @@ #include "SimpleMatrix.h" #include "SimpleTemplated.h" #include "DataPoint.h" +#include "ConditionalLinkedList.h" class SimpleDisplayObject { @@ -77,5 +78,14 @@ int main(int argc, char** argv) DataPoint dp(42); DataPoint *dpPtr = &dp; + ConditionalLinkedList activeList(true); + activeList.Add(10); + activeList.Add(20); + activeList.Add(30); + + ConditionalLinkedList inactiveList(false); + inactiveList.Add(100); + inactiveList.Add(200); + return 0; } diff --git a/test/CppTests/debuggees/natvis/src/visualizer_files/Simple.natvis b/test/CppTests/debuggees/natvis/src/visualizer_files/Simple.natvis index 189136e35..0c833dde5 100644 --- a/test/CppTests/debuggees/natvis/src/visualizer_files/Simple.natvis +++ b/test/CppTests/debuggees/natvis/src/visualizer_files/Simple.natvis @@ -121,4 +121,18 @@ {{ {this}={*this} }} + + {{ active={isActive}, count={numElements} }} + + isActive + numElements + + numElements + head + next + data + + + + \ No newline at end of file