Skip to content

Commit cb0d921

Browse files
committed
fix
1 parent c8bb5c7 commit cb0d921

File tree

5 files changed

+39
-6
lines changed

5 files changed

+39
-6
lines changed

src/cm/colorView.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,8 @@ class ColorViewPlugin {
213213
scheduleDecorations(view: EditorView): void {
214214
this.pendingView = view;
215215
if (this.raf) return;
216+
// Color chips are decorative, so batch rapid viewport/doc changes into
217+
// one animation frame instead of rebuilding on every intermediate update.
216218
this.raf = requestAnimationFrame(() => {
217219
this.raf = 0;
218220
const pendingView = this.pendingView;

src/cm/indentGuides.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,8 @@ function createIndentGuidesPlugin(
367367
scheduleBuild(view: EditorView): void {
368368
this.pendingView = view;
369369
if (this.raf) return;
370+
// Guide rebuilding is cosmetic and can be expensive on large
371+
// viewports, so we intentionally collapse bursts into one frame.
370372
this.raf = requestAnimationFrame(() => {
371373
this.raf = 0;
372374
const pendingView = this.pendingView;

src/cm/lsp/diagnostics.ts

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
StateEffect,
99
StateField,
1010
} from "@codemirror/state";
11-
import type { EditorView } from "@codemirror/view";
11+
import { type EditorView, ViewPlugin } from "@codemirror/view";
1212
import type {
1313
LSPClientWithWorkspace,
1414
LSPPluginAPI,
@@ -18,7 +18,8 @@ import type {
1818
} from "./types";
1919

2020
const setPublishedDiagnostics = StateEffect.define<LspDiagnostic[]>();
21-
let diagnosticsEventTimer = 0;
21+
let diagnosticsEventTimer: ReturnType<typeof setTimeout> | null = null;
22+
let diagnosticsViewCount = 0;
2223

2324
export const LSP_DIAGNOSTICS_EVENT = "acode:lsp-diagnostics-updated";
2425

@@ -67,6 +68,12 @@ function emitDiagnosticsUpdated(): void {
6768
document.dispatchEvent(event);
6869
}
6970

71+
function clearScheduledDiagnosticsUpdated(): void {
72+
if (diagnosticsEventTimer == null) return;
73+
clearTimeout(diagnosticsEventTimer);
74+
diagnosticsEventTimer = null;
75+
}
76+
7077
const lspPublishedDiagnostics = StateField.define<LspDiagnostic[]>({
7178
create(): LspDiagnostic[] {
7279
return [];
@@ -164,13 +171,30 @@ function sameDiagnostics(
164171
}
165172

166173
function scheduleDiagnosticsUpdated(): void {
167-
if (diagnosticsEventTimer) return;
168-
diagnosticsEventTimer = window.setTimeout(() => {
169-
diagnosticsEventTimer = 0;
170-
emitDiagnosticsUpdated();
174+
if (diagnosticsEventTimer != null) return;
175+
diagnosticsEventTimer = setTimeout(() => {
176+
diagnosticsEventTimer = null;
177+
if (diagnosticsViewCount > 0) {
178+
emitDiagnosticsUpdated();
179+
}
171180
}, 32);
172181
}
173182

183+
const diagnosticsLifecyclePlugin = ViewPlugin.fromClass(
184+
class {
185+
constructor() {
186+
diagnosticsViewCount++;
187+
}
188+
189+
destroy(): void {
190+
diagnosticsViewCount = Math.max(0, diagnosticsViewCount - 1);
191+
if (!diagnosticsViewCount) {
192+
clearScheduledDiagnosticsUpdated();
193+
}
194+
}
195+
},
196+
);
197+
174198
function mapDiagnostics(
175199
plugin: LSPPluginAPI,
176200
state: EditorState,
@@ -262,6 +286,7 @@ export function lspDiagnosticsUiExtension(includeGutter = true): Extension[] {
262286
? () => []
263287
: undefined;
264288
const extensions: Extension[] = [
289+
diagnosticsLifecyclePlugin,
265290
lspPublishedDiagnostics,
266291
linter(lspLinterSource, {
267292
needsRefresh(update) {

src/cm/lsp/documentHighlights.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ function buildDecos(
105105
: [view.viewport];
106106
const decos: Range<Decoration>[] = [];
107107
let rangeIndex = 0;
108+
// process() keeps highlights sorted so visible range culling can advance
109+
// with a single cursor instead of rescanning visibleRanges for every mark.
108110
for (const h of highlights) {
109111
if (h.from < 0 || h.to > docLen || h.from >= h.to) continue;
110112
while (

src/cm/rainbowBrackets.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ const rainbowBracketsPlugin = ViewPlugin.fromClass(
4040
scheduleBuild(view: EditorView): void {
4141
this.pendingView = view;
4242
if (this.raf) return;
43+
// Rainbow bracket colors are purely visual, so batch rebuilds to the
44+
// next frame instead of recomputing on every transient update.
4345
this.raf = requestAnimationFrame(() => {
4446
this.raf = 0;
4547
const pendingView = this.pendingView;

0 commit comments

Comments
 (0)