From ef195d27032409230c448615a668dd918a22b065 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Thu, 11 Jun 2026 23:51:01 +0200 Subject: [PATCH] Show a hint instead of stale debug steps for languages without step support When the current language is not an IDebugStepProvider (e.g. the IL disassembler), the Debug Steps pane kept displaying the previous language's step tree, and its commands still triggered re-decompiles with a step limit the language ignores. Detaching now clears the tree and the view shows a "not available" note until a step-providing language is selected again. Assisted-by: Claude:claude-fable-5:Claude Code --- ILSpy.Tests/Views/DebugStepsTests.cs | 24 ++++++++++++++++++++++++ ILSpy/ViewModels/DebugStepsPaneModel.cs | 12 ++++++++++++ ILSpy/Views/DebugSteps.axaml | 8 +++++++- 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/ILSpy.Tests/Views/DebugStepsTests.cs b/ILSpy.Tests/Views/DebugStepsTests.cs index cfd26b49b..0b1c4fc5a 100644 --- a/ILSpy.Tests/Views/DebugStepsTests.cs +++ b/ILSpy.Tests/Views/DebugStepsTests.cs @@ -133,6 +133,30 @@ public class DebugStepsTests languageService.Languages.Should().Contain(l => l.Name == "Typed IL"); return Task.CompletedTask; } + [AvaloniaTest] + public Task Pane_Reports_Not_Available_For_Languages_Without_Debug_Steps() + { + // The step tree only makes sense for IDebugStepProvider languages (C#, ILAst, Typed IL). + // For the plain IL disassembler the pane must not keep showing the previous language's + // stale step tree (whose commands would trigger pointless re-decompiles); it reports + // unavailability so the view swaps in a "not available" message instead. + var languageService = AppComposition.Current.GetExport(); + var debugStepsVm = AppComposition.Current.GetExport(); + + languageService.CurrentLanguage = languageService.Languages.OfType().First(); + global::Avalonia.Threading.Dispatcher.UIThread.RunJobs(); + debugStepsVm.IsAvailable.Should().BeTrue("C# provides debug steps"); + + // Simulate a populated tree from the C# run, then flip to the disassembler language. + debugStepsVm.Steps = new[] { new ICSharpCode.Decompiler.IL.Transforms.Stepper.Node("stale") }; + languageService.CurrentLanguage = languageService.Languages.OfType().First(l => l.Name == "IL"); + global::Avalonia.Threading.Dispatcher.UIThread.RunJobs(); + + debugStepsVm.IsAvailable.Should().BeFalse("the IL disassembler provides no debug steps"); + debugStepsVm.Steps.Should().BeNull("the previous language's step tree must not linger"); + return Task.CompletedTask; + } + [AvaloniaTest] public async Task Window_Menu_Toggle_Surfaces_The_Default_Hidden_Debug_Steps_Pane() { diff --git a/ILSpy/ViewModels/DebugStepsPaneModel.cs b/ILSpy/ViewModels/DebugStepsPaneModel.cs index eb963f79a..9a70af238 100644 --- a/ILSpy/ViewModels/DebugStepsPaneModel.cs +++ b/ILSpy/ViewModels/DebugStepsPaneModel.cs @@ -92,6 +92,14 @@ namespace ILSpy.ViewModels [ObservableProperty] Stepper.Node? selectedStep; + /// + /// True while the current language is an . When false, + /// the view replaces the step tree with a "not available" note instead of leaving the + /// previous language's stale tree (whose commands would trigger pointless re-decompiles). + /// + [ObservableProperty] + bool isAvailable; + public IRelayCommand ShowStateBeforeCommand { get; } public IRelayCommand ShowStateAfterCommand { get; } public IRelayCommand DebugStepCommand { get; } @@ -162,6 +170,7 @@ namespace ILSpy.ViewModels // Same language instance — just refresh the steps in case a decompile happened // while we were detached. Steps = activeLanguage!.Stepper.Steps; + IsAvailable = true; return; } DetachFromLanguage(); @@ -169,10 +178,13 @@ namespace ILSpy.ViewModels language.StepperUpdated += OnStepperUpdated; Steps = language.Stepper.Steps; Options = language.StepOptions; + IsAvailable = true; } void DetachFromLanguage() { + IsAvailable = false; + Steps = null; if (activeLanguage != null) { activeLanguage.StepperUpdated -= OnStepperUpdated; diff --git a/ILSpy/Views/DebugSteps.axaml b/ILSpy/Views/DebugSteps.axaml index fe6e7dbad..c5980b05d 100644 --- a/ILSpy/Views/DebugSteps.axaml +++ b/ILSpy/Views/DebugSteps.axaml @@ -7,7 +7,12 @@ mc:Ignorable="d" d:DesignWidth="400" d:DesignHeight="300" x:Class="ILSpy.Views.DebugSteps" x:DataType="vm:DebugStepsPaneModel"> - + + + @@ -49,4 +54,5 @@ +