diff --git a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs index 7ef08ee92..0fd1294a1 100644 --- a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs +++ b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs @@ -33,6 +33,7 @@ using ICSharpCode.Decompiler.CSharp.Resolver; using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.CSharp.Transforms; using ICSharpCode.Decompiler.CSharp.TypeSystem; +using ICSharpCode.Decompiler.DebugSteps; using ICSharpCode.Decompiler.DebugInfo; using ICSharpCode.Decompiler.Disassembler; using ICSharpCode.Decompiler.Documentation; diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/TransformContext.cs b/ICSharpCode.Decompiler/CSharp/Transforms/TransformContext.cs index 8dad120dc..9b73530ba 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/TransformContext.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/TransformContext.cs @@ -24,7 +24,7 @@ using System.Diagnostics; using System.Threading; using ICSharpCode.Decompiler.CSharp.Syntax; -using ICSharpCode.Decompiler.IL.Transforms; +using ICSharpCode.Decompiler.DebugSteps; using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -82,29 +82,14 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms [DebuggerStepThrough] internal void Step(string description, AstNode? near = null) { - Stepper.Node stepNode; - try - { - stepNode = Stepper.Step(description, modifiedNode: near); - } - catch (StepLimitReachedException) - { - // The limit fell on this step: Stepper recorded it as LimitReachedStep but threw - // before we could attach the node candidates. Attach them to the limit-reached node - // (the tree is still in its pre-mutation state) so the "show state before" view can - // locate the change, mirroring how the IL path records candidates before its throw. - if (Stepper.LimitReachedStep is { } limitStep) - TrackModifiedNode(limitStep, near); - throw; - } - TrackModifiedNode(stepNode, near); + Stepper.Step(description, CreateNodeInfo(near)); } [Conditional("STEP")] [DebuggerStepThrough] internal void StepStartGroup(string description, AstNode? near = null) { - TrackModifiedNode(Stepper.StartGroup(description, modifiedNode: near), near); + Stepper.StartGroup(description, CreateNodeInfo(near)); } [Conditional("STEP")] @@ -123,28 +108,28 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms { if (Stepper.LastStep != null && modifiedNode != null) { + var marker = new DebugStepMarker(); + modifiedNode.AddAnnotation(marker); Stepper.LastStep.ModifiedNode = modifiedNode; - TrackModifiedNode(Stepper.LastStep, modifiedNode, insertFirst: true); + Stepper.LastStep.RecordModifiedNode(modifiedNode, extraIdentity: marker, insertFirst: true); } } - static void TrackModifiedNode(Stepper.Node step, AstNode? modifiedNode, bool insertFirst = false) + static DebugStepNodeInfo? CreateNodeInfo(AstNode? modifiedNode) { if (modifiedNode == null) - return; + return null; // The marker rides CopyAnnotationsFrom so a replaced node's step still resolves to the // emitted text; it is recorded as a second identity for the changed node. The seam - // neighbours and ancestor chain are captured from the original node on the initial pass - // (insertFirst == false); a produced-node update only prepends the new node. + // neighbors and ancestor chain are captured from the original node before mutation. var marker = new DebugStepMarker(); modifiedNode.AddAnnotation(marker); - step.RecordModifiedNode( + return new DebugStepNodeInfo( modifiedNode, - insertFirst ? null : modifiedNode.NextSibling, - insertFirst ? null : modifiedNode.PrevSibling, - insertFirst ? null : Ancestors(modifiedNode), - extraIdentity: marker, - insertFirst: insertFirst); + modifiedNode.NextSibling, + modifiedNode.PrevSibling, + Ancestors(modifiedNode), + extraIdentity: marker); static IEnumerable Ancestors(AstNode node) { @@ -154,13 +139,4 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms } } - /// - /// Annotation attached to a step's modified node so the debug-step highlighter can still locate - /// that node's rendered range after a later transform copies its annotations onto a replacement - /// (via CopyAnnotationsFrom). This is the only annotation NodeLookup bridges to a text - /// range; indexing every annotation would add dead keys and let shared ones collide by identity. - /// - public sealed class DebugStepMarker - { - } } diff --git a/ICSharpCode.Decompiler/IL/Transforms/Stepper.cs b/ICSharpCode.Decompiler/DebugSteps/Stepper.cs similarity index 69% rename from ICSharpCode.Decompiler/IL/Transforms/Stepper.cs rename to ICSharpCode.Decompiler/DebugSteps/Stepper.cs index 2839dd233..2dab0f037 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/Stepper.cs +++ b/ICSharpCode.Decompiler/DebugSteps/Stepper.cs @@ -25,15 +25,41 @@ using System.Linq; using ICSharpCode.Decompiler.Util; -namespace ICSharpCode.Decompiler.IL.Transforms +namespace ICSharpCode.Decompiler.DebugSteps { /// - /// Exception thrown when an IL transform runs into the . + /// Exception thrown when a debug-step-enabled transform pipeline runs into the . /// public class StepLimitReachedException : Exception { } + /// + /// Language-specific node identities and navigation data captured before a transform mutation. + /// + public readonly struct DebugStepNodeInfo + { + public object Node { get; } + public object? NextSibling { get; } + public object? PreviousSibling { get; } + public IEnumerable? Ancestors { get; } + public object? ExtraIdentity { get; } + + public DebugStepNodeInfo( + object node, + object? nextSibling = null, + object? previousSibling = null, + IEnumerable? ancestors = null, + object? extraIdentity = null) + { + Node = node ?? throw new ArgumentNullException(nameof(node)); + NextSibling = nextSibling; + PreviousSibling = previousSibling; + Ancestors = ancestors; + ExtraIdentity = extraIdentity; + } + } + /// /// Helper class that manages recording transform steps. /// @@ -63,7 +89,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms public class Node { public string Description { get; } - public ILInstruction? Position { get; set; } + public object? Position { get; set; } public object? ModifiedNode { get; set; } /// /// Precise identities of the changed node (the node itself, its debug-step marker, and @@ -71,14 +97,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// public IList ModifiedNodeCandidates { get; } = new List(); /// - /// Neighbours of the changed node, recorded before the mutation. When the node itself is + /// Neighbors of the changed node, recorded before the mutation. When the node itself is /// gone from the rendered text (a removal), a caret is placed at the gap they leave: - /// at the start of a following neighbour, or the end of a preceding one (AtEnd). + /// at the start of a following neighbor, or the end of a preceding one (AtEnd). /// public IList<(object Anchor, bool AtEnd)> SeamAnchors { get; } = new List<(object, bool)>(); /// /// The changed node's ancestor chain, resolved as a last resort when neither the node - /// nor a seam neighbour has a rendered range. + /// nor a seam neighbor has a rendered range. /// public IList AncestorCandidates { get; } = new List(); /// @@ -101,12 +127,23 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// Records the highlight candidates for this step from an already-navigated node: the /// node's identity (optionally a second identity such as a debug-step marker), its /// immediate siblings as seam anchors, and its ancestor chain. Callers pass the - /// neighbours because and the C# AST expose navigation - /// differently; the ordering/dedup/seam strategy lives here so the two languages' + /// neighbors because each transform representation exposes navigation differently; + /// the ordering/dedup/seam strategy lives here so languages' /// recording can't drift. marks a produced-node update /// (from EndStep): the node is preferred over existing candidates and the seam and /// ancestor anchors are left untouched, since they were captured from the original node. /// + public void RecordModifiedNode(DebugStepNodeInfo modifiedNode, bool insertFirst = false) + { + RecordModifiedNode( + modifiedNode.Node, + modifiedNode.NextSibling, + modifiedNode.PreviousSibling, + modifiedNode.Ancestors, + modifiedNode.ExtraIdentity, + insertFirst); + } + public void RecordModifiedNode( object node, object? nextSibling = null, @@ -159,44 +196,21 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// May throw in debug mode. /// [DebuggerStepThrough] - public Node Step(string description, ILInstruction? near = null, object? modifiedNode = null) - { - return StepInternal(description, near, modifiedNode ?? near); - } - - [DebuggerStepThrough] - private Node StepInternal(string description, ILInstruction? near, object? modifiedNode) + public Node Step(string description, DebugStepNodeInfo? modifiedNode = null) { + object? node = modifiedNode?.Node; var stepNode = new Node($"{step}: {description}") { - Position = near, - ModifiedNode = modifiedNode, + Position = node, + ModifiedNode = node, BeginStep = step, EndStep = step + 1 }; - // Record the IL position, its neighbours, and its ancestor chain as highlight candidates - // here, before the limit-reached check below can throw: the debug-step view halts the - // pipeline at the selected step, so that step would otherwise carry no candidates and the - // "show state before" view could not locate the change. A later transform may detach the - // exact instruction; a surviving neighbour then anchors a seam caret, and failing that a - // surviving ancestor (ultimately the ILFunction) still resolves. - if (near != null) + // Record highlight candidates before the limit-reached check below can throw: the debug-step + // view halts the pipeline at the selected step, so that step would otherwise carry no + // candidates and the "show state before" view could not locate the change. + if (modifiedNode is { } info) { - object? next = null, prev = null; - if (near.Parent is { } parent) - { - int index = near.ChildIndex; - if (index + 1 < parent.Children.Count) - next = parent.Children[index + 1]; - if (index - 1 >= 0) - prev = parent.Children[index - 1]; - } - stepNode.RecordModifiedNode(near, next, prev, Ancestors(near)); - - static IEnumerable Ancestors(ILInstruction inst) - { - for (var node = inst.Parent; node != null; node = node.Parent) - yield return node; - } + stepNode.RecordModifiedNode(info); } if (step == StepLimit) { @@ -217,9 +231,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms } [DebuggerStepThrough] - public Node StartGroup(string description, ILInstruction? near = null, object? modifiedNode = null) + public Node StartGroup(string description, DebugStepNodeInfo? modifiedNode = null) { - var stepNode = StepInternal(description, near, modifiedNode ?? near); + var stepNode = Step(description, modifiedNode); groups.Push(stepNode); return stepNode; } @@ -254,4 +268,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms node.EndStep = step; } } + + /// + /// Annotation attached to a step's modified node so the debug-step highlighter can still locate + /// that node's rendered range after a later transform copies its annotations onto a replacement + /// (via CopyAnnotationsFrom). This is the only annotation the UI bridges to a text range; indexing + /// every annotation would add dead keys and let shared ones collide by identity. + /// + public sealed class DebugStepMarker + { + } } diff --git a/ICSharpCode.Decompiler/IL/Transforms/IILTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/IILTransform.cs index f0321cff9..4c00a8871 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/IILTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/IILTransform.cs @@ -19,11 +19,13 @@ #nullable enable using System; +using System.Collections.Generic; using System.Diagnostics; using System.Threading; using ICSharpCode.Decompiler.CSharp.Resolver; using ICSharpCode.Decompiler.CSharp.TypeSystem; +using ICSharpCode.Decompiler.DebugSteps; using ICSharpCode.Decompiler.DebugInfo; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; @@ -105,14 +107,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms [DebuggerStepThrough] internal void Step(string description, ILInstruction? near) { - Stepper.Step(description, near); + Stepper.Step(description, CreateNodeInfo(near)); } [Conditional("STEP")] [DebuggerStepThrough] internal void StepStartGroup(string description, ILInstruction? near = null) { - Stepper.StartGroup(description, near); + Stepper.StartGroup(description, CreateNodeInfo(near)); } [Conditional("STEP")] @@ -138,5 +140,27 @@ namespace ICSharpCode.Decompiler.IL.Transforms step.RecordModifiedNode(modifiedNode, insertFirst: true); } } + + static DebugStepNodeInfo? CreateNodeInfo(ILInstruction? instruction) + { + if (instruction == null) + return null; + object? next = null, previous = null; + if (instruction.Parent is { } parent) + { + int index = instruction.ChildIndex; + if (index + 1 < parent.Children.Count) + next = parent.Children[index + 1]; + if (index - 1 >= 0) + previous = parent.Children[index - 1]; + } + return new DebugStepNodeInfo(instruction, next, previous, Ancestors(instruction)); + + static IEnumerable Ancestors(ILInstruction instruction) + { + for (var node = instruction.Parent; node != null; node = node.Parent) + yield return node; + } + } } } diff --git a/ILSpy.Tests/Views/DebugStepsTests.cs b/ILSpy.Tests/Views/DebugStepsTests.cs index b604870a1..ef49b192b 100644 --- a/ILSpy.Tests/Views/DebugStepsTests.cs +++ b/ILSpy.Tests/Views/DebugStepsTests.cs @@ -33,6 +33,7 @@ using AwesomeAssertions; using ICSharpCode.Decompiler.CSharp; using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.CSharp.Transforms; +using ICSharpCode.Decompiler.DebugSteps; using ICSharpCode.ILSpy; using ICSharpCode.ILSpy.AppEnv; @@ -239,8 +240,7 @@ public class DebugStepsTests // The first leaf step that acts on a concrete instruction; a step whose Position is null // (e.g. an empty transform group) has nothing to highlight and is not what a user replays. - static ICSharpCode.Decompiler.IL.Transforms.Stepper.Node? FirstLeafStep( - System.Collections.Generic.IEnumerable steps) + static Stepper.Node? FirstLeafStep(System.Collections.Generic.IEnumerable steps) { foreach (var step in steps) { @@ -304,37 +304,37 @@ public class DebugStepsTests public Task DebugStepHighlighter_Removal_Resolves_To_Seam_Caret() { // A step whose node was removed has no precise range and (in this fixture) no rendered - // ancestor, only surviving neighbours. It must resolve to a zero-length caret at the gap: + // ancestor, only surviving neighbors. It must resolve to a zero-length caret at the gap: // the successor's start when one survives, otherwise the predecessor's end. var successor = new object(); var predecessor = new object(); var successorLookup = new NodeLookup(); successorLookup.AddNode(successor, 40, 6); - var removalWithSuccessor = new ICSharpCode.Decompiler.IL.Transforms.Stepper.Node("0: Remove statement") { + var removalWithSuccessor = new Stepper.Node("0: Remove statement") { BeginStep = 0, EndStep = 1 }; removalWithSuccessor.SeamAnchors.Add((successor, false)); removalWithSuccessor.SeamAnchors.Add((predecessor, true)); - var successorStepper = new ICSharpCode.Decompiler.IL.Transforms.Stepper(); + var successorStepper = new Stepper(); successorStepper.Steps.Add(removalWithSuccessor); DebugStepHighlighter.TryResolve(successorStepper, stepLimit: 1, highlightStep: 0, successorLookup, out var caret) - .Should().BeTrue("a removed node must still resolve to a surviving seam neighbour"); + .Should().BeTrue("a removed node must still resolve to a surviving seam neighbor"); caret.Length.Should().Be(0, "a removal has no text to highlight, only a caret at the gap"); caret.Start.Should().Be(40, "the caret sits at the successor's start, where the node was"); // Only the predecessor survives: the caret sits at its end (10 + 5). var predecessorLookup = new NodeLookup(); predecessorLookup.AddNode(predecessor, 10, 5); - var removalWithPredecessor = new ICSharpCode.Decompiler.IL.Transforms.Stepper.Node("0: Remove statement") { + var removalWithPredecessor = new Stepper.Node("0: Remove statement") { BeginStep = 0, EndStep = 1 }; removalWithPredecessor.SeamAnchors.Add((successor, false)); removalWithPredecessor.SeamAnchors.Add((predecessor, true)); - var predecessorStepper = new ICSharpCode.Decompiler.IL.Transforms.Stepper(); + var predecessorStepper = new Stepper(); predecessorStepper.Steps.Add(removalWithPredecessor); DebugStepHighlighter.TryResolve(predecessorStepper, stepLimit: 1, highlightStep: 0, predecessorLookup, out var endCaret) @@ -348,9 +348,9 @@ public class DebugStepsTests public Task DebugStepFilter_Keeps_Matches_And_The_Path_To_Them() { var converter = new DebugStepFilterConverter(); - var matchingLeaf = new ICSharpCode.Decompiler.IL.Transforms.Stepper.Node("3: Introduce query continuation"); - var otherLeaf = new ICSharpCode.Decompiler.IL.Transforms.Stepper.Node("4: Flatten switch section block"); - var group = new ICSharpCode.Decompiler.IL.Transforms.Stepper.Node("CombineQueryExpressions"); + var matchingLeaf = new Stepper.Node("3: Introduce query continuation"); + var otherLeaf = new Stepper.Node("4: Flatten switch section block"); + var group = new Stepper.Node("CombineQueryExpressions"); group.Children.Add(matchingLeaf); group.Children.Add(otherLeaf); @@ -365,7 +365,7 @@ public class DebugStepsTests Filter(otherLeaf, "continuation").Should().BeFalse(); return Task.CompletedTask; - bool Filter(ICSharpCode.Decompiler.IL.Transforms.Stepper.Node node, string filter) + bool Filter(Stepper.Node node, string filter) => (bool)converter.Convert(new object?[] { node, filter }, typeof(bool), null, CultureInfo.InvariantCulture); } @@ -377,9 +377,9 @@ public class DebugStepsTests // would not catch at build time. Realising the view with a populated tree and a live filter // must not throw. var vm = new DebugStepsPaneModel(); - var group = new ICSharpCode.Decompiler.IL.Transforms.Stepper.Node("CombineQueryExpressions"); - group.Children.Add(new ICSharpCode.Decompiler.IL.Transforms.Stepper.Node("3: Introduce query continuation")); - group.Children.Add(new ICSharpCode.Decompiler.IL.Transforms.Stepper.Node("4: Flatten switch section block")); + var group = new Stepper.Node("CombineQueryExpressions"); + group.Children.Add(new Stepper.Node("3: Introduce query continuation")); + group.Children.Add(new Stepper.Node("4: Flatten switch section block")); vm.Steps = new[] { group }; vm.IsAvailable = true; @@ -483,7 +483,7 @@ public class DebugStepsTests 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") }; + debugStepsVm.Steps = new[] { new Stepper.Node("stale") }; languageService.CurrentLanguage = languageService.Languages.OfType().First(l => l.Name == "IL"); global::Avalonia.Threading.Dispatcher.UIThread.RunJobs(); diff --git a/ILSpy/Languages/CSharpLanguage.DebugSteps.cs b/ILSpy/Languages/CSharpLanguage.DebugSteps.cs index 13b5c6a27..6d350cee4 100644 --- a/ILSpy/Languages/CSharpLanguage.DebugSteps.cs +++ b/ILSpy/Languages/CSharpLanguage.DebugSteps.cs @@ -22,7 +22,7 @@ using System; using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.CSharp; -using ICSharpCode.Decompiler.IL.Transforms; +using ICSharpCode.Decompiler.DebugSteps; using ICSharpCode.ILSpy.AppEnv; using ICSharpCode.ILSpy.Docking; diff --git a/ILSpy/Languages/CSharpLanguage.cs b/ILSpy/Languages/CSharpLanguage.cs index 679f2317d..d017b515a 100644 --- a/ILSpy/Languages/CSharpLanguage.cs +++ b/ILSpy/Languages/CSharpLanguage.cs @@ -32,8 +32,8 @@ using ICSharpCode.Decompiler.CSharp.OutputVisitor; using ICSharpCode.Decompiler.CSharp.ProjectDecompiler; using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.CSharp.Transforms; +using ICSharpCode.Decompiler.DebugSteps; using ICSharpCode.Decompiler.IL; -using ICSharpCode.Decompiler.IL.Transforms; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Output; using ICSharpCode.Decompiler.Solution; diff --git a/ILSpy/Languages/IDebugStepProvider.cs b/ILSpy/Languages/IDebugStepProvider.cs index 8316f5562..465b85bc4 100644 --- a/ILSpy/Languages/IDebugStepProvider.cs +++ b/ILSpy/Languages/IDebugStepProvider.cs @@ -20,7 +20,7 @@ using System; -using ICSharpCode.Decompiler.IL.Transforms; +using ICSharpCode.Decompiler.DebugSteps; namespace ICSharpCode.ILSpy.Languages { diff --git a/ILSpy/Languages/ILAstLanguage.cs b/ILSpy/Languages/ILAstLanguage.cs index eaa6b6f9c..fe4ff0dde 100644 --- a/ILSpy/Languages/ILAstLanguage.cs +++ b/ILSpy/Languages/ILAstLanguage.cs @@ -24,6 +24,7 @@ using System.Composition; using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.CSharp; +using ICSharpCode.Decompiler.DebugSteps; using ICSharpCode.Decompiler.Disassembler; using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.IL.Transforms; diff --git a/ILSpy/TextView/DebugStepHighlighter.cs b/ILSpy/TextView/DebugStepHighlighter.cs index 93d83f610..650a9be4f 100644 --- a/ILSpy/TextView/DebugStepHighlighter.cs +++ b/ILSpy/TextView/DebugStepHighlighter.cs @@ -16,7 +16,7 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -using ICSharpCode.Decompiler.IL.Transforms; +using ICSharpCode.Decompiler.DebugSteps; namespace ICSharpCode.ILSpy.TextView { @@ -71,7 +71,7 @@ namespace ICSharpCode.ILSpy.TextView if (step.ModifiedNode != null && nodeLookup.TryGetRange(step.ModifiedNode, out range)) return true; // The node itself is gone (a removal): point a zero-length caret at the gap it left, - // anchored to a surviving neighbour, rather than flooding the enclosing block. + // anchored to a surviving neighbor, rather than flooding the enclosing block. foreach (var (anchor, atEnd) in step.SeamAnchors) { if (nodeLookup.TryGetRange(anchor, out var anchorRange)) diff --git a/ILSpy/TextView/NodeLookup.cs b/ILSpy/TextView/NodeLookup.cs index e2603bef4..a03f39b3b 100644 --- a/ILSpy/TextView/NodeLookup.cs +++ b/ILSpy/TextView/NodeLookup.cs @@ -19,7 +19,7 @@ using System.Collections.Generic; using ICSharpCode.Decompiler.CSharp.Syntax; -using ICSharpCode.Decompiler.CSharp.Transforms; +using ICSharpCode.Decompiler.DebugSteps; namespace ICSharpCode.ILSpy.TextView { diff --git a/ILSpy/ViewModels/DebugStepsPaneModel.cs b/ILSpy/ViewModels/DebugStepsPaneModel.cs index 1eb7abeb4..013841852 100644 --- a/ILSpy/ViewModels/DebugStepsPaneModel.cs +++ b/ILSpy/ViewModels/DebugStepsPaneModel.cs @@ -27,8 +27,8 @@ using Avalonia.Threading; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; +using ICSharpCode.Decompiler.DebugSteps; using ICSharpCode.Decompiler.IL; -using ICSharpCode.Decompiler.IL.Transforms; using ICSharpCode.ILSpy.AppEnv; using ICSharpCode.ILSpy.Commands; diff --git a/ILSpy/Views/DebugStepFilterConverter.cs b/ILSpy/Views/DebugStepFilterConverter.cs index f94417afb..5e78a9ccf 100644 --- a/ILSpy/Views/DebugStepFilterConverter.cs +++ b/ILSpy/Views/DebugStepFilterConverter.cs @@ -24,7 +24,7 @@ using System.Globalization; using Avalonia.Data.Converters; -using ICSharpCode.Decompiler.IL.Transforms; +using ICSharpCode.Decompiler.DebugSteps; namespace ICSharpCode.ILSpy.Views {