Skip to content

Add fine-grained debug steps with highlighting for C# and ILAst#3839

Open
siegfriedpammer wants to merge 13 commits into
masterfrom
add-steps-to-all-transforms
Open

Add fine-grained debug steps with highlighting for C# and ILAst#3839
siegfriedpammer wants to merge 13 commits into
masterfrom
add-steps-to-all-transforms

Conversation

@siegfriedpammer

@siegfriedpammer siegfriedpammer commented Jun 28, 2026

Copy link
Copy Markdown
Member

What

Makes the Debug Steps pane fine-grained and navigable for both the C# AST and ILAst decompiler views. Previously the pane listed one entry per transform; now it shows the individual mutation steps inside each transform, grouped by transform, with a filter box in the top-right corner to narrow the tree by matching text. Selecting a step (or "Show state before/after") re-decompiles at that point and highlights and scrolls to the exact node/instruction the transform changed (amber marker, centered in the view). A step that removes a node drops a thin caret at the gap it left, rather than flooding the enclosing block.

How

  • C# AST (TransformContext): each transform records fine-grained Step / EndStep calls; the changed node is mapped to its rendered text span via the highlighting token writer + NodeLookup.
  • ILAst (ILTransformContext): the same Step / EndStep two-method API. IL rendering has no token-writer seam like the C# output visitor, so per-instruction text spans are recorded by bracketing rendering through the optional INodeTrackingOutput. The bracket lives in exactly one place: ILInstruction.WriteTo is sealed to wrap a new protected abstract WriteToCore (the override point), so a newly added instruction cannot forget it — the T4 generator and every hand-written override now emit WriteToCore.
  • Range resolution is shared between the two languages and tiered: the precise identities of the changed node (the node, its debug-step marker, and any node its mutation produced) → a seam caret anchored to a surviving neighbour when the node itself is gone from the rendered text (a removal) → the ancestor chain as a last resort. NodeLookup bridges only the debug-step marker to a text range, not every annotation. Both the C# and IL paths attach the changed node's fallback candidates to the step even when it is the one that hits the step limit, so "show state before" (which halts at the selected step) still resolves.
  • Highlight centering reuses the fold-aware bookmark helper (CenterLineInView / GetVisualTopByDocumentLine, background dispatcher priority, document re-check), so it lands correctly even with collapsed foldings — dense in the ILAst block output.
  • Node-range tracking is only wired when a step limit is set, so a normal (Release) decompile does not pay the per-node/per-annotation bookkeeping for a debug-only feature.

Tests

Headless UI tests cover both languages: the changed node/instruction is located for both the "before" and "after" replay of a selected step (asserting a precise, in-bounds, non-flooding range — not merely non-null); a removal step resolves to a zero-length seam caret; the filter keeps matches and the path to them; and NodeLookup bridges only the debug-step marker. The decompiler engine builds clean in Debug (with STEP) and Release (the [Conditional("STEP")] step calls compile out with no unused-local fallout).

🤖 Generated with Claude Code

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR upgrades ILSpy’s Debug Steps feature to support fine-grained, navigable mutation steps for both the C# AST and ILAst views, with automatic highlight + scroll-to-change after replaying a selected step (“before/after”).

Changes:

  • Adds step-level replay support by threading a HighlightStep through decompilation requests and outputs.
  • Introduces language-agnostic node-to-text range tracking (INodeTrackingOutput + NodeLookup) and a shared step-to-range resolver (DebugStepHighlighter).
  • Instruments C# and ILAst rendering/transform pipelines to record step metadata and node spans; adds headless UI tests.

Reviewed changes

Copilot reviewed 97 out of 97 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
ILSpy/ViewModels/DebugStepsPaneModel.cs Passes highlightStep through debug-step replay commands.
ILSpy/TextView/TextRange.cs Adds a lightweight (Start, Length) range type for highlighting.
ILSpy/TextView/NodeLookup.cs Adds object→text-range map (incl. AST annotations) used for highlight resolution.
ILSpy/TextView/DecompilerTextView.axaml.cs Adds debug-step marker rendering and centering behavior in the editor.
ILSpy/TextView/DecompilerTabPageModel.cs Threads highlight state (DebugStepHighlight) through decompile lifecycle and tab model.
ILSpy/TextView/DebugStepHighlighter.cs Resolves a stepper step to a TextRange via NodeLookup.
ILSpy/TextView/AvaloniaEditTextOutput.cs Implements INodeTrackingOutput; collects node spans and debug highlight output.
ILSpy/Languages/ILAstLanguage.cs Applies step highlight resolution for ILAst output runs.
ILSpy/Languages/CSharpLanguage.DebugSteps.cs Switches C# stepper source to decompiler-provided stepper on full runs.
ILSpy/Languages/CSharpLanguage.cs Wires stepper limits into C# decompiler and emits highlight range after rendering.
ILSpy/Languages/CSharpHighlightingTokenWriter.cs Records AST node spans during token writing for later highlight lookup.
ILSpy/DecompilationOptions.cs Adds HighlightStep option to distinguish “stop point” from “highlighted step.”
ILSpy.Tests/Views/DebugStepsTests.cs Adds headless UI tests for step grouping and highlight resolution (C# + ILAst).
ICSharpCode.Decompiler/Output/INodeTrackingOutput.cs Introduces optional node-span tracking API + extension helpers.
ICSharpCode.Decompiler/IL/Transforms/UsingTransform.cs Records produced-node via EndStep for accurate highlight targeting.
ICSharpCode.Decompiler/IL/Transforms/UserDefinedLogicTransform.cs Records produced-node via EndStep for accurate highlight targeting.
ICSharpCode.Decompiler/IL/Transforms/TransformExpressionTrees.cs Records produced-node via EndStep for accurate highlight targeting.
ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs Records produced-node via EndStep for accurate highlight targeting.
ICSharpCode.Decompiler/IL/Transforms/TransformCollectionAndObjectInitializers.cs Records produced-node via EndStep for accurate highlight targeting.
ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs Records produced-node via EndStep for accurate highlight targeting.
ICSharpCode.Decompiler/IL/Transforms/TransformArrayInitializers.cs Records produced-node via EndStep for accurate highlight targeting.
ICSharpCode.Decompiler/IL/Transforms/SwitchOnStringTransform.cs Records produced-node via EndStep for accurate highlight targeting.
ICSharpCode.Decompiler/IL/Transforms/Stepper.cs Adds modified-node tracking fields, limit bookkeeping, and GetStepByBeginStep.
ICSharpCode.Decompiler/IL/Transforms/RemoveUnconstrainedGenericReferenceTypeCheck.cs Records produced-node via EndStep for accurate highlight targeting.
ICSharpCode.Decompiler/IL/Transforms/RemoveInfeasiblePathTransform.cs Records produced-node via EndStep for accurate highlight targeting.
ICSharpCode.Decompiler/IL/Transforms/RemoveDeadVariableInit.cs Records produced-node via EndStep for accurate highlight targeting.
ICSharpCode.Decompiler/IL/Transforms/ReduceNestingTransform.cs Records produced-node via EndStep for accurate highlight targeting.
ICSharpCode.Decompiler/IL/Transforms/ProxyCallReplacer.cs Records produced-node via EndStep for accurate highlight targeting.
ICSharpCode.Decompiler/IL/Transforms/PatternMatchingTransform.cs Records produced-node via EndStep for accurate highlight targeting.
ICSharpCode.Decompiler/IL/Transforms/NullPropagationTransform.cs Records produced-node via EndStep for accurate highlight targeting.
ICSharpCode.Decompiler/IL/Transforms/NullableLiftingTransform.cs Records produced-node via EndStep for accurate highlight targeting.
ICSharpCode.Decompiler/IL/Transforms/NamedArgumentTransform.cs Records produced-node via EndStep for accurate highlight targeting.
ICSharpCode.Decompiler/IL/Transforms/LockTransform.cs Records produced-node via EndStep for accurate highlight targeting.
ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs Returns produced call node so callers can EndStep accurately.
ICSharpCode.Decompiler/IL/Transforms/LdLocaDupInitObjTransform.cs Records produced-node via EndStep for accurate highlight targeting.
ICSharpCode.Decompiler/IL/Transforms/InterpolatedStringTransform.cs Records produced-node via EndStep for accurate highlight targeting.
ICSharpCode.Decompiler/IL/Transforms/InlineArrayTransform.cs Records produced-node via EndStep for accurate highlight targeting.
ICSharpCode.Decompiler/IL/Transforms/IndexRangeTransform.cs Records produced-node via EndStep for accurate highlight targeting.
ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs Records produced-node via EndStep for accurate highlight targeting.
ICSharpCode.Decompiler/IL/Transforms/IILTransform.cs Adds EndStep helper for IL transforms to prefer produced nodes.
ICSharpCode.Decompiler/IL/Transforms/FixRemainingIncrements.cs Records produced-node via EndStep for accurate highlight targeting.
ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs Records produced-node via EndStep for accurate highlight targeting.
ICSharpCode.Decompiler/IL/Transforms/EarlyExpressionTransforms.cs Records produced-node via EndStep for accurate highlight targeting.
ICSharpCode.Decompiler/IL/Transforms/DynamicIsEventAssignmentTransform.cs Records produced-node via EndStep for accurate highlight targeting.
ICSharpCode.Decompiler/IL/Transforms/DetectCatchWhenConditionBlocks.cs Records produced-node via EndStep for accurate highlight targeting.
ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs Records produced-node via EndStep for accurate highlight targeting.
ICSharpCode.Decompiler/IL/Transforms/DeconstructionTransform.cs Records produced-node via EndStep for accurate highlight targeting.
ICSharpCode.Decompiler/IL/Transforms/CopyPropagation.cs Records produced-node via EndStep for accurate highlight targeting.
ICSharpCode.Decompiler/IL/Transforms/CachedDelegateInitialization.cs Records produced-node via EndStep for accurate highlight targeting.
ICSharpCode.Decompiler/IL/Instructions/UsingInstruction.cs Wraps IL instruction writing with node-span tracking calls.
ICSharpCode.Decompiler/IL/Instructions/UnaryInstruction.cs Wraps IL instruction writing with node-span tracking calls.
ICSharpCode.Decompiler/IL/Instructions/TryInstruction.cs Wraps IL instruction writing with node-span tracking calls.
ICSharpCode.Decompiler/IL/Instructions/SwitchInstruction.cs Wraps IL instruction writing with node-span tracking calls.
ICSharpCode.Decompiler/IL/Instructions/StringToInt.cs Wraps IL instruction writing with node-span tracking calls.
ICSharpCode.Decompiler/IL/Instructions/SimpleInstruction.cs Wraps IL instruction writing with node-span tracking calls.
ICSharpCode.Decompiler/IL/Instructions/NullCoalescingInstruction.cs Wraps IL instruction writing with node-span tracking calls.
ICSharpCode.Decompiler/IL/Instructions/NullableInstructions.cs Wraps IL instruction writing with node-span tracking calls.
ICSharpCode.Decompiler/IL/Instructions/MemoryInstructions.cs Wraps IL instruction writing with node-span tracking calls.
ICSharpCode.Decompiler/IL/Instructions/MatchInstruction.cs Wraps IL instruction writing with node-span tracking calls.
ICSharpCode.Decompiler/IL/Instructions/LockInstruction.cs Wraps IL instruction writing with node-span tracking calls.
ICSharpCode.Decompiler/IL/Instructions/Leave.cs Wraps IL instruction writing with node-span tracking calls.
ICSharpCode.Decompiler/IL/Instructions/LdLen.cs Wraps IL instruction writing with node-span tracking calls.
ICSharpCode.Decompiler/IL/Instructions/ILFunction.cs Wraps IL instruction writing with node-span tracking calls.
ICSharpCode.Decompiler/IL/Instructions/IfInstruction.cs Wraps IL instruction writing with node-span tracking calls.
ICSharpCode.Decompiler/IL/Instructions/ExpressionTreeCast.cs Wraps IL instruction writing with node-span tracking calls.
ICSharpCode.Decompiler/IL/Instructions/DynamicInstructions.cs Wraps IL instruction writing with node-span tracking calls.
ICSharpCode.Decompiler/IL/Instructions/DeconstructResultInstruction.cs Wraps IL instruction writing with node-span tracking calls.
ICSharpCode.Decompiler/IL/Instructions/DeconstructInstruction.cs Wraps IL instruction writing with node-span tracking calls.
ICSharpCode.Decompiler/IL/Instructions/Conv.cs Wraps IL instruction writing with node-span tracking calls.
ICSharpCode.Decompiler/IL/Instructions/CompoundAssignmentInstruction.cs Wraps IL instruction writing with node-span tracking calls.
ICSharpCode.Decompiler/IL/Instructions/Comp.cs Wraps IL instruction writing with node-span tracking calls.
ICSharpCode.Decompiler/IL/Instructions/CallInstruction.cs Wraps IL instruction writing with node-span tracking calls.
ICSharpCode.Decompiler/IL/Instructions/CallIndirect.cs Wraps IL instruction writing with node-span tracking calls.
ICSharpCode.Decompiler/IL/Instructions/Branch.cs Wraps IL instruction writing with node-span tracking calls.
ICSharpCode.Decompiler/IL/Instructions/BlockContainer.cs Wraps IL instruction writing with node-span tracking calls.
ICSharpCode.Decompiler/IL/Instructions/Block.cs Wraps IL instruction writing with node-span tracking calls.
ICSharpCode.Decompiler/IL/Instructions/BinaryNumericInstruction.cs Wraps IL instruction writing with node-span tracking calls.
ICSharpCode.Decompiler/IL/Instructions.tt Updates T4 template to auto-wrap generated WriteTo with node-span tracking.
ICSharpCode.Decompiler/IL/Instructions.cs Regenerated IL instruction WriteTo methods to include node-span tracking.
ICSharpCode.Decompiler/CSharp/Transforms/TransformFieldAndConstructorInitializers.cs Adds per-mutation step recording in the C# AST pipeline.
ICSharpCode.Decompiler/CSharp/Transforms/TransformContext.cs Adds STEP-only Step/EndStep helpers and node-candidate tracking for AST steps.
ICSharpCode.Decompiler/CSharp/Transforms/ReplaceMethodCallsWithOperators.cs Adds per-mutation step recording in the C# AST pipeline.
ICSharpCode.Decompiler/CSharp/Transforms/PrettifyAssignments.cs Adds per-mutation step recording in the C# AST pipeline.
ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs Adds per-mutation step recording in the C# AST pipeline.
ICSharpCode.Decompiler/CSharp/Transforms/NormalizeBlockStatements.cs Adds per-mutation step recording in the C# AST pipeline.
ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUsingDeclarations.cs Adds step recording around ambiguous-type qualification and using insertion.
ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUnsafeModifier.cs Adds step recording for unsafe modifier / pointer syntax transforms.
ICSharpCode.Decompiler/CSharp/Transforms/IntroduceQueryExpressions.cs Adds step recording for query-expression synthesis and rewrites.
ICSharpCode.Decompiler/CSharp/Transforms/IntroduceExtensionMethods.cs Adds step recording for extension-method call rewriting.
ICSharpCode.Decompiler/CSharp/Transforms/FlattenSwitchBlocks.cs Adds step recording for switch block flattening.
ICSharpCode.Decompiler/CSharp/Transforms/FixNameCollisions.cs Adds step recording for rename fixes.
ICSharpCode.Decompiler/CSharp/Transforms/EscapeInvalidIdentifiers.cs Adds step recording for identifier escaping.
ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs Adds step recording for variable declaration insertion and rewrites.
ICSharpCode.Decompiler/CSharp/Transforms/CombineQueryExpressions.cs Adds step recording for query continuation and identifier removal.
ICSharpCode.Decompiler/CSharp/Transforms/AddXmlDocumentationTransform.cs Adds step recording for XML doc insertion.
ICSharpCode.Decompiler/CSharp/Transforms/AddCheckedBlocks.cs Adds step recording when inserting checked/unchecked blocks/expressions.
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs Adds AST transform groups + step-limit support via shared Stepper.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +105 to +113
[Conditional("STEP")]
internal void EndStep(AstNode? modifiedNode)
{
if (Stepper.LastStep != null)
{
Stepper.LastStep.ModifiedNode = modifiedNode;
TrackModifiedNode(Stepper.LastStep, modifiedNode, insertFirst: true);
}
}
Comment on lines +961 to +964
Editor.TextArea.Caret.Offset = start;
Editor.TextArea.Caret.BringCaretToView();
Dispatcher.UIThread.Post(() => CenterDocumentOffsetInView(start));
CaretHighlightAdorner.DisplayCaretHighlightAnimation(Editor.TextArea);

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 97 out of 97 changed files in this pull request and generated 3 comments.

Comment on lines +292 to +300
public void MarkNodeEnd(object node)
{
if (openNodes.Count == 0)
return;
var (currentNode, start) = openNodes.Pop();
if (!ReferenceEquals(currentNode, node))
return;
NodeLookup.AddNode(node, start, builder.Length - start);
}
Comment thread ILSpy/Languages/CSharpLanguage.cs Outdated
Comment on lines 532 to 541
var output = new AvaloniaEditTextOutput { LengthLimit = outputLengthLimit };
// decompilerSettings is null only in design-time / minimal test hosts
// without composition; fall back to defaults there.
var options = new DecompilationOptions(
decompilerSettings ?? new ICSharpCode.Decompiler.DecompilerSettings()) {
CancellationToken = cts.Token,
StepLimit = stepLimit,
HighlightStep = highlightStep,
IsDebug = isDebug,
};
@siegfriedpammer siegfriedpammer force-pushed the add-steps-to-all-transforms branch 2 times, most recently from fb820cd to b40936a Compare July 1, 2026 06:44
Record AST transform groups and mutation steps through the C# pipeline, replay selected steps with the stepper, and carry modified-node ranges through output so the Debug Steps pane can highlight the selected mutation without replacing its full step tree.

Assisted-by: CodeAlta:gpt-5.5:CodeAlta
Place the selected debug-step node in the middle of the editor after replay so navigation lands with enough surrounding context instead of just barely scrolling the mark into view.

Assisted-by: CodeAlta:gpt-5.5:CodeAlta
The C# debug-steps view highlights and centers the exact AST node a
transform changed; the ILAst view already had the step tree and
replay-at-step but produced no highlight. Bring it to parity.

IL rendering has no token-writer seam like the C# output visitor, so
per-instruction text spans are recorded by bracketing
ILInstruction.WriteTo via a new INodeTrackingOutput. The dominant
inst.ReplaceWith(newInst) transform pattern detaches the instruction
passed to Step, so ILTransformContext gains EndStep to record the
produced instruction; Stepper additionally records the position's
ancestor chain as fallback candidates before the step-limit throw, so
the "show state before" view -- which halts at the selected step --
still resolves to a surviving ancestor (ultimately the ILFunction).
The highlight-range resolver is shared with the C# language.

Assisted-by: Claude:claude-opus-4-8:Claude Code
The Debug Steps "show state before/after" replay re-decompiles the active
tab; the headless UI tests inferred completion by polling IsDecompiling +
Text, which can return on stale state or hit the 60s wait deadline when
that shared signal races under CI load (the observed intermittent CI
timeout). RestartDecompileWithStepLimit now returns the decompile Task so
the replay completion can be awaited deterministically; the tests await it
instead of polling. The production IsDecompiling reset is unchanged -- the
last decompile's finally always resets it; the race was only in the test's
completion inference.

Assisted-by: Claude:claude-opus-4-8:Claude Code
MarkNodeStart and BeginSpan captured builder.Length to anchor a node range
or highlight span, but indentation is written lazily on the first token of a
line. A node or span opened at the start of an indented line therefore
recorded its start before the leading tabs, so the debug-step highlight (and
any span) extended back across the indentation to column 0.

Flush the pending indent in both before capturing the offset, matching the
WPF AvalonEditTextOutput.BeginSpan the Avalonia port derived from. The emitted
text is unchanged -- the indent is written either way, in the same place; only
the recorded start moves to the first real character.

Assisted-by: Claude:claude-opus-4-8:Claude Code
The debug-step highlight centred with a logical (line-number * line-height)
calculation posted at default dispatcher priority. That ignores collapsed
foldings above the target, races the layout of a just-applied document
(silently no-oping when the viewport is not yet measured), and does not recheck
the document, so a newer decompile could scroll the wrong content. The symptom
was unreliable centring, most visible in the ILAst view whose nested block
output is fold-dense and larger.

Route the highlight through the existing CenterLineInView helper that bookmark
navigation already uses: it centres via GetVisualTopByDocumentLine (fold-aware),
runs at Background priority so the document finishes measuring first, and
rechecks the document identity.

Assisted-by: Claude:claude-opus-4-8:Claude Code
NodeLookup population runs per AST node (and per annotation) on every on-screen
C# decompile, but the debug-step highlighter only consumes it when a step limit
is set. Gate the node-tracking token writer on StepLimit so the common Release
path skips the bookkeeping; AvaloniaEditTextOutput is an ISmartTextOutput, so it
still gets full syntax highlighting via the existing branch.

Assisted-by: Claude:claude-opus-4-8:Claude Code
A step that removes a node has nothing left to highlight in the resulting text,
so range resolution fell back to the enclosing block and flooded it. Record the
changed node's surviving neighbours as seam anchors (captured before the
mutation) and split a step's candidates into precise / seam / ancestor tiers:
when neither the node nor its marker resolves, place a zero-length caret at the
gap -- the successor's start, else the predecessor's end -- and only fall back
to the enclosing block when no neighbour survives. A zero-length highlight is
rendered as a caret (positioned, pulsed, centered) with no background mark.

Assisted-by: Claude:claude-opus-4-8:Claude Code
The step tree can run to hundreds of entries per decompile, so finding a
specific mutation means scrolling. Add a filter box in the pane's top-right
corner: a row survives when its description -- or any descendant's -- contains
the text (case-insensitive), keeping the path to every match, and the tree
auto-expands while filtering so matches nested under transform groups stay
visible. Implemented as an item-visibility converter over the existing TreeView
rather than switching to SharpTreeView, which would change the Steps contract
and rewrite the pane's tests for no functional gain here.

Assisted-by: Claude:claude-opus-4-8:Claude Code
The debug-step node bracket (MarkNodeStart/try/finally/MarkNodeEnd) was copied
into every hand-written WriteTo override and re-emitted by the T4 generator, so
a newly added instruction could silently omit it and lose step highlighting with
no compile error or test failure. Seal WriteTo on ILInstruction to apply the
bracket once and delegate to a new abstract WriteToCore; move every override
(hand-written and generated) to WriteToCore without the wrapper. Rendered output
is unchanged -- the marks are no-ops unless the output tracks nodes.

Assisted-by: Claude:claude-opus-4-8:Claude Code
NodeLookup.AddNode indexed every annotation of every rendered node by reference
identity, but the debug-step highlighter only ever looks up the DebugStepMarker;
the rest were dead keys, and a shared annotation (ResolveResult and friends,
copied across nodes) would resolve to whichever node rendered last. Make
DebugStepMarker public and bridge only it -- behaviour-preserving for resolution
while dropping the per-annotation dictionary churn on every rendered node.

Assisted-by: Claude:claude-opus-4-8:Claude Code
When the step limit falls on a C# transform step, Stepper.Step records the node
as LimitReachedStep but throws before TransformContext can attach the node's
highlight candidates, so the 'show state before' view had only the bare modified
node to resolve against -- and nothing if that node renders no text of its own.
The IL path already records its candidates before the throw; mirror that on the
C# side by attaching the candidates to the limit-reached node in the catch, then
re-throwing so the pipeline still halts.

Assisted-by: Claude:claude-opus-4-8:Claude Code
The replay tests only checked DebugStepHighlight was non-null, which the
ancestor fallback satisfies unconditionally -- a regression widening every
highlight to the enclosing method would have passed. Assert instead that the
range lies in bounds, does not span the whole document, and (unless it is a
zero-length removal caret) covers non-whitespace rendered code.

Assisted-by: Claude:claude-opus-4-8:Claude Code
@siegfriedpammer siegfriedpammer force-pushed the add-steps-to-all-transforms branch from b40936a to 954ab83 Compare July 1, 2026 10:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants