Highlighting: invalidate from the edited row, not the whole buffer
Every edit bumped the buffer version (through SetDirty) and called InvalidateFrom(0), so all cached spans and line states were discarded and stateful highlighters re-lexed from row 0 to the viewport on each keystroke. Buffer mutators now report the row they changed (edited_at_), which bumps the version and tells the engine to drop only rows from there down; a row's highlighting depends only on rows above it. A version change that arrives without that notice still clears everything, so a missed path cannot show stale spans. The engine keeps states as a contiguous vector and caches spans for every row it lexes. SetDirty no longer touches the version: the edits themselves do, including undo and redo back to the saved state (D9 still holds; its test now checks the highlighting itself). Typing near the end of a 100k-line C++ file: 46.3 ms -> 0.14 ms of highlighting work per keystroke. Audit finding P3. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015rcVQiiWyTzoNrsvLSaAfB
This commit is contained in:
@@ -390,21 +390,17 @@ public:
|
||||
|
||||
void SetDirty(bool d)
|
||||
{
|
||||
// The version tracks content, not the dirty flag: every text mutation
|
||||
// bumps it (see edited_at_), including undo/redo back to the saved state.
|
||||
dirty_ = d;
|
||||
// Bump even when clearing: undo/redo back to the saved state changes the
|
||||
// text and then calls SetDirty(false). Without a bump the highlighter
|
||||
// keeps serving spans for the pre-undo text.
|
||||
MarkContentChanged();
|
||||
}
|
||||
|
||||
|
||||
// Invalidate version-keyed caches (syntax highlighting) after a content change.
|
||||
// Whole-buffer content change (load, reload, replace): bump the version
|
||||
// and drop all cached highlighting.
|
||||
void MarkContentChanged()
|
||||
{
|
||||
++version_;
|
||||
if (highlighter_) {
|
||||
highlighter_->InvalidateFrom(0);
|
||||
}
|
||||
edited_at_(0);
|
||||
}
|
||||
|
||||
|
||||
@@ -699,6 +695,15 @@ private:
|
||||
|
||||
// Syntax/highlighting state
|
||||
std::uint64_t version_ = 0; // increment on edits
|
||||
|
||||
// Record a content change starting at `row`: bump the version and let the
|
||||
// highlighter drop cached rows from `row` down (rows above are unaffected).
|
||||
void edited_at_(int row)
|
||||
{
|
||||
++version_;
|
||||
if (highlighter_)
|
||||
highlighter_->OnEdit(row < 0 ? 0 : row, version_);
|
||||
}
|
||||
bool syntax_enabled_ = true;
|
||||
bool syntax_user_override_ = false; // true once user explicitly set syntax state via a command
|
||||
std::string filetype_;
|
||||
|
||||
Reference in New Issue
Block a user