Skip to content

Sisco/fix editor replace method#30

Merged
dsisco11 merged 3 commits into
masterfrom
sisco/fix-editor-replace-method
Jan 7, 2026
Merged

Sisco/fix editor replace method#30
dsisco11 merged 3 commits into
masterfrom
sisco/fix-editor-replace-method

Conversation

@dsisco11

@dsisco11 dsisco11 commented Jan 7, 2026

Copy link
Copy Markdown
Owner

Fix Query Region System and SyntaxEditor Replacements

Summary

This PR refactors the entire node query system to fix fundamental issues with how SyntaxEditor handles multi-node replacements and range queries like Query.Between. The core problem was that SyntaxEditor was designed around single-node replacements, but queries can match multiple sibling nodes that need to be replaced atomically.

Problem

The original implementation had several shortcomings:

  1. Query.Between and sequence queries match multiple consecutive siblings, but SyntaxEditor.Replace() only handled single-node replacements
  2. Block inner queries (.Inner(), .Start(), .End()) didn't correctly resolve to slot positions within the parent
  3. Path computation was expensive - NodePath.FromNode() was called in hot loops during region enumeration

Solution

Introduced a new QueryRegion abstraction that represents a contiguous range of slots within a parent container:

internal readonly struct QueryRegion
{
    public NodePath ParentPath { get; }      // Path to parent container
    public int StartSlot { get; }            // First slot index (inclusive)
    public int EndSlot { get; }              // Last slot index (exclusive)  
    public SyntaxNode? FirstNode { get; }    // First node in range (for trivia)
    public int Position { get; }             // Document position
}

This allows SyntaxEditor to correctly:

  • Replace ranges of nodes atomically (e.g., Query.Between(start, end))
  • Handle zero-width insertion positions (e.g., empty block inner)
  • Insert at specific slot positions within containers

Key Changes

New Files:

  • QueryRegion.cs - Region struct and IRegionQuery interface
  • PathTrackingWalker - O(1) incremental path tracking during tree traversal
  • SyntaxEditorBenchmarks.cs - Comprehensive benchmarks for editor operations

Modified Files:

  • SyntaxEditor.cs - Rewritten to use regions instead of single nodes
  • NodeQueryTypes.cs - Added IRegionQuery implementations to all query types
  • QueryCombinators.cs - Updated combinators to produce correct regions
  • GreenNode.cs - Added GetLeadingTrivia/TrailingTrivia and GetFirstLeaf/GetLastLeaf helpers
  • GreenBlock.cs - Added slot-based child access methods

Performance Optimizations

  1. PathTrackingWalker - Tracks path incrementally during traversal (O(1) per step vs O(depth) for NodePath.FromNode())
  2. Lazy ParentPath - Only computed when actually accessed during editing
  3. Precomputed trivia widths - Uses GreenLeaf.LeadingTriviaWidth/TrailingTriviaWidth instead of summing at runtime
  4. Optimized SelectRegions - Inlined match checks for KindNodeQuery and BlockNodeQuery

Test Coverage

Added 15+ new tests covering:

  • Query.Between with Replace/Remove/Insert/Edit operations
  • Block inner content replacement (empty and non-empty)
  • Multi-position insertions (50+ positions)
  • Deep tree traversal (20-50 levels)
  • Trivia preservation across edits

Breaking Changes

None - all changes are internal. The public SyntaxEditor API is unchanged.

Files Changed

 SyntaxEditorBenchmarks.cs     | 375 ++++++++++++++
 SyntaxEditorTests.cs          | 362 +++++++++++++
 QueryRegion.cs                | 245 +++++++++
 SyntaxEditor.cs               | 572 ++++++++++++---------
 NodeQueryTypes.cs             | 286 +++++++++++
 QueryCombinators.cs           | 181 +++++++
 GreenNode.cs                  |  88 ++++
 GreenBlock.cs                 | 203 ++++++++
 17 files changed, 2388 insertions(+), 739 deletions(-)

@dsisco11 dsisco11 merged commit 28aca6c into master Jan 7, 2026
2 checks passed
@dsisco11 dsisco11 deleted the sisco/fix-editor-replace-method branch January 7, 2026 03:01
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.

1 participant