Skip to content

Fix ArgumentOutOfRangeException in TextModificationService.ColorizeLine - #403

Merged
hendrikmennen merged 1 commit into
mainfrom
fix/text-modification-colorize-crash
Oct 16, 2026
Merged

hendrikmennen merged 1 commit into
mainfrom
fix/text-modification-colorize-crash

Conversation

@hendrikmennen

@hendrikmennen hendrikmennen commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Fixes a crash during editor rendering:

System.ArgumentOutOfRangeException: Value must be between 421 and 429 (Parameter 'endOffset')
Actual value was 430.
   at AvaloniaEdit.Rendering.DocumentColorizingTransformer.ChangeLinePart(...)
   at OneWare.Essentials.EditorExtensions.TextModificationService.ColorizeLine(DocumentLine line)

Root cause

ColorizeLine clamped highlights that span several lines to the current line by changing the stored highlight itself. In AvaloniaEdit, setting TextSegment.StartOffset moves the highlight (its length stays the same). So after the end was clamped, moving the start pushed EndOffset past the line end again. For example, a highlight at 419–430 on line 421–429 ended at 431. The clamping also permanently changed stored highlights such as semantic tokens and caret highlights, so the next lines they covered drew them in the wrong place.

Changes

  • ColorizeLine computes the clamped start and end in local variables (TryClampToLine) and no longer changes the highlight. Empty ranges are skipped.
  • SetModification keeps a highlight's end offset when it trims the start of overlapping highlights, and skips highlights that end up empty.
  • Added InternalsVisibleTo so OneWare.Essentials.UnitTests can call the internal helper.
  • Added regression tests in TextModificationServiceTests.

Testing

dotnet test tests/OneWare.Essentials.UnitTests passes (98/98). Tested running the App

ColorizeLine clamped multi-line segments by mutating them. Setting
TextSegment.StartOffset moves the segment (keeping its length), so the
end offset was pushed past the line end and ChangeLinePart threw. The
mutation also permanently corrupted the stored segments.

Clamp into local offsets instead, and preserve the end offset when
trimming overlapping segments in SetModification.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@hendrikmennen
hendrikmennen merged commit 9374932 into main Oct 16, 2026
5 checks passed
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