Skip to content

Commit 5ca5f12

Browse files
committed
refactor(check): clarify snapshot callback and simplify directory watching; ignore .crush
1 parent a2d5323 commit 5ca5f12

File tree

4 files changed

+60
-33
lines changed

4 files changed

+60
-33
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,6 @@ dist
6868

6969
# VSCode history extension
7070
.history
71+
72+
# Ignore AI artifacts
73+
.crush/

packages/language-server/src/plugins/typescript/LSAndTSDocResolver.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,10 @@ interface LSAndTSDocResolverOptions {
4848
nonRecursiveWatchPattern?: string;
4949
/**
5050
* Optional callback invoked when a new snapshot is created.
51-
* Used by svelte-check to dynamically add parent directories to file watchers.
51+
* Passes the absolute file path of the created snapshot.
52+
* Consumers (like svelte-check) can derive the directory as needed.
5253
*/
53-
onSnapshotCreated?: (dirPath: string) => void;
54+
onFileSnapshotCreated?: (filePath: string) => void;
5455
}
5556

5657
export class LSAndTSDocResolver {
@@ -89,13 +90,12 @@ export class LSAndTSDocResolver {
8990
this.tsSystem = this.wrapWithPackageJsonMonitoring(this.options?.tsSystem ?? ts.sys);
9091
this.globalSnapshotsManager = new GlobalSnapshotsManager(this.tsSystem);
9192
// Notify when new snapshots are created so external watchers (svelte-check)
92-
// can add their parent directories dynamically.
93-
if (this.options?.onSnapshotCreated) {
93+
// can react dynamically (for example: add parent directories to file watchers).
94+
if (this.options?.onFileSnapshotCreated) {
9495
this.globalSnapshotsManager.onChange((fileName, newDocument) => {
9596
if (newDocument) {
9697
try {
97-
const dir = dirname(fileName);
98-
this.options?.onSnapshotCreated?.(dir);
98+
this.options?.onFileSnapshotCreated?.(fileName);
9999
} catch {
100100
// best-effort; ignore errors in callback
101101
}

packages/language-server/src/svelte-check.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@ export interface SvelteCheckOptions {
3333
watch?: boolean;
3434
/**
3535
* Optional callback invoked when a new snapshot is created.
36-
* Used by svelte-check to dynamically add watch directories.
36+
* Provides the absolute file path of the snapshot.
3737
*/
38-
onSnapshotCreated?: (dirPath: string) => void;
38+
onFileSnapshotCreated?: (filePath: string) => void;
3939
}
4040

4141
/**
@@ -97,7 +97,7 @@ export class SvelteCheck {
9797
isSvelteCheck: true,
9898
onProjectReloaded: options.onProjectReload,
9999
watch: options.watch,
100-
onSnapshotCreated: options.onSnapshotCreated
100+
onFileSnapshotCreated: options.onFileSnapshotCreated
101101
}
102102
);
103103
this.pluginHost.register(

packages/svelte-check/src/index.ts

Lines changed: 48 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -197,41 +197,64 @@ class DiagnosticsWatcher {
197197
this.updateWatchedDirectories();
198198
}
199199

200+
private isSubdir(candidate: string, parent: string) {
201+
const c = path.resolve(candidate);
202+
const p = path.resolve(parent);
203+
return c === p || c.startsWith(p + path.sep);
204+
}
205+
206+
private minimizeDirs(dirs: string[]): string[] {
207+
const sorted = [...new Set(dirs.map((d) => path.resolve(d)))].sort();
208+
const result: string[] = [];
209+
for (const dir of sorted) {
210+
if (!result.some((p) => this.isSubdir(dir, p))) {
211+
result.push(dir);
212+
}
213+
}
214+
return result;
215+
}
216+
200217
addWatchDirectory(dir: string) {
201-
if (!dir || this.currentWatchedDirs.has(dir)) {
202-
return;
218+
if (!dir) return;
219+
// Skip if already covered by an existing watched directory
220+
for (const existing of this.currentWatchedDirs) {
221+
if (this.isSubdir(dir, existing)) {
222+
return;
223+
}
224+
}
225+
// If new dir is a parent of existing ones, unwatch children
226+
const toRemove: string[] = [];
227+
for (const existing of this.currentWatchedDirs) {
228+
if (this.isSubdir(existing, dir)) {
229+
toRemove.push(existing);
230+
}
231+
}
232+
if (toRemove.length) {
233+
this.watcher.unwatch(toRemove);
234+
for (const r of toRemove) this.currentWatchedDirs.delete(r);
203235
}
204236
this.watcher.add(dir);
205237
this.currentWatchedDirs.add(dir);
206-
// New files might now be visible; schedule a run
207-
this.scheduleDiagnostics();
208238
}
209239

210240
private async updateWatchedDirectories() {
211241
const watchDirs = await this.svelteCheck.getWatchDirectories();
212-
const dirsToWatch = watchDirs || [{ path: this.workspaceUri.fsPath, recursive: true }];
213-
const newDirs = new Set(dirsToWatch.map((d) => d.path));
242+
const desired = this.minimizeDirs(
243+
(watchDirs?.map((d) => d.path) || [this.workspaceUri.fsPath]).map((p) =>
244+
path.resolve(p)
245+
)
246+
);
214247

215-
// Fast diff: find directories to add and remove
216-
const toAdd = [...newDirs].filter((dir) => !this.currentWatchedDirs.has(dir));
217-
const toRemove = [...this.currentWatchedDirs].filter((dir) => !newDirs.has(dir));
248+
const current = new Set([...this.currentWatchedDirs].map((p) => path.resolve(p)));
249+
const desiredSet = new Set(desired);
218250

219-
// Add new directories
220-
if (toAdd.length > 0) {
221-
this.watcher.add(toAdd);
222-
}
251+
const toAdd = desired.filter((d) => !current.has(d));
252+
const toRemove = [...current].filter((d) => !desiredSet.has(d));
223253

224-
// Remove old directories
225-
if (toRemove.length > 0) {
226-
this.watcher.unwatch(toRemove);
227-
}
254+
if (toAdd.length) this.watcher.add(toAdd);
255+
if (toRemove.length) this.watcher.unwatch(toRemove);
228256

229-
// Update current set
230-
this.currentWatchedDirs = newDirs;
231-
232-
if (this.ignoreInitialAdd) {
233-
this.scheduleDiagnostics();
234-
}
257+
this.currentWatchedDirs = new Set(desired);
235258
}
236259

237260
private async updateDocument(path: string, isNew: boolean) {
@@ -319,7 +342,8 @@ parseOptions(async (opts) => {
319342
watcher.updateWatchers();
320343
watcher.scheduleDiagnostics();
321344
};
322-
svelteCheckOptions.onSnapshotCreated = (dirPath: string) => {
345+
svelteCheckOptions.onFileSnapshotCreated = (filePath: string) => {
346+
const dirPath = path.dirname(filePath);
323347
watcher.addWatchDirectory(dirPath);
324348
};
325349
watcher = new DiagnosticsWatcher(

0 commit comments

Comments
 (0)