@@ -145,47 +145,91 @@ async function getDiagnostics(
145
145
146
146
class DiagnosticsWatcher {
147
147
private updateDiagnostics : any ;
148
+ private watcher : any ;
149
+ private currentWatchedDirs = new Set < string > ( ) ;
150
+ private fileEnding = / \. ( s v e l t e | d \. t s | t s | j s | j s x | t s x | m j s | c j s | m t s | c t s ) $ / ;
151
+ private viteConfigRegex = / v i t e \. c o n f i g \. ( j s | t s ) \. t i m e s t a m p - / ;
152
+ private userIgnored : Array < ( path : string ) => boolean > ;
153
+ private offset : number ;
148
154
149
155
constructor (
150
156
private workspaceUri : URI ,
151
157
private svelteCheck : SvelteCheck ,
152
158
private writer : Writer ,
153
159
filePathsToIgnore : string [ ] ,
154
- ignoreInitialAdd : boolean
160
+ private ignoreInitialAdd : boolean
155
161
) {
156
- const fileEnding = / \. ( s v e l t e | d \. t s | t s | j s | j s x | t s x | m j s | c j s | m t s | c t s ) $ / ;
157
- const viteConfigRegex = / v i t e \. c o n f i g \. ( j s | t s ) \. t i m e s t a m p - / ;
158
- const userIgnored = createIgnored ( filePathsToIgnore ) ;
159
- const offset = workspaceUri . fsPath . length + 1 ;
162
+ this . userIgnored = createIgnored ( filePathsToIgnore ) ;
163
+ this . offset = workspaceUri . fsPath . length + 1 ;
160
164
161
- watch ( workspaceUri . fsPath , {
165
+ // Create watcher with initial paths
166
+ this . watcher = watch ( [ ] , {
162
167
ignored : ( path , stats ) => {
163
168
if (
164
169
path . includes ( 'node_modules' ) ||
165
170
path . includes ( '.git' ) ||
166
- ( stats ?. isFile ( ) && ( ! fileEnding . test ( path ) || viteConfigRegex . test ( path ) ) )
171
+ ( stats ?. isFile ( ) && ( ! this . fileEnding . test ( path ) || this . viteConfigRegex . test ( path ) ) )
167
172
) {
168
173
return true ;
169
174
}
170
175
171
- if ( userIgnored . length !== 0 ) {
172
- path = path . slice ( offset ) ;
173
- for ( const i of userIgnored ) {
174
- if ( i ( path ) ) {
176
+ if ( this . userIgnored . length !== 0 ) {
177
+ // Make path relative to workspace for user ignores
178
+ const workspaceRelative = path . startsWith ( this . workspaceUri . fsPath )
179
+ ? path . slice ( this . workspaceUri . fsPath . length + 1 )
180
+ : path ;
181
+ for ( const i of this . userIgnored ) {
182
+ if ( i ( workspaceRelative ) ) {
175
183
return true ;
176
184
}
177
185
}
178
186
}
179
187
180
188
return false ;
181
189
} ,
182
- ignoreInitial : ignoreInitialAdd
190
+ ignoreInitial : this . ignoreInitialAdd
183
191
} )
184
192
. on ( 'add' , ( path ) => this . updateDocument ( path , true ) )
185
193
. on ( 'unlink' , ( path ) => this . removeDocument ( path ) )
186
194
. on ( 'change' , ( path ) => this . updateDocument ( path , false ) ) ;
187
195
188
- if ( ignoreInitialAdd ) {
196
+ this . updateWatchedDirectories ( ) ;
197
+ }
198
+
199
+ private async updateWatchedDirectories ( ) {
200
+ const watchDirs = await this . svelteCheck . getWatchDirectories ( ) ;
201
+ const dirsToWatch = watchDirs || [ { path : this . workspaceUri . fsPath , recursive : true } ] ;
202
+
203
+ // Apply exclude heuristic to ensure we never watch commonly excluded directories
204
+ const excludePatterns = [ 'node_modules' , '.git' , 'dist' , 'build' , 'out' , '.svelte-kit' , 'coverage' , '.nyc_output' ] ;
205
+ const filteredDirs = dirsToWatch . filter ( dir => {
206
+ const dirPath = dir . path . replace ( / \\ / g, '/' ) ;
207
+ return ! excludePatterns . some ( pattern =>
208
+ dirPath . includes ( `/${ pattern } /` ) ||
209
+ dirPath . endsWith ( `/${ pattern } ` )
210
+ ) ;
211
+ } ) ;
212
+
213
+ const newDirs = new Set ( filteredDirs . map ( d => d . path ) ) ;
214
+
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 ) ) ;
218
+
219
+ // Add new directories
220
+ if ( toAdd . length > 0 ) {
221
+ this . watcher . add ( toAdd ) ;
222
+ }
223
+
224
+ // Remove old directories
225
+ if ( toRemove . length > 0 ) {
226
+ this . watcher . unwatch ( toRemove ) ;
227
+ }
228
+
229
+ // Update current set
230
+ this . currentWatchedDirs = newDirs ;
231
+
232
+ if ( this . ignoreInitialAdd ) {
189
233
this . scheduleDiagnostics ( ) ;
190
234
}
191
235
}
@@ -210,10 +254,15 @@ class DiagnosticsWatcher {
210
254
this . scheduleDiagnostics ( ) ;
211
255
}
212
256
213
- scheduleDiagnostics ( ) {
257
+ scheduleDiagnostics ( updateWatchers = false ) {
214
258
clearTimeout ( this . updateDiagnostics ) ;
215
259
this . updateDiagnostics = setTimeout (
216
- ( ) => getDiagnostics ( this . workspaceUri , this . writer , this . svelteCheck ) ,
260
+ async ( ) => {
261
+ if ( updateWatchers ) {
262
+ await this . updateWatchedDirectories ( ) ;
263
+ }
264
+ getDiagnostics ( this . workspaceUri , this . writer , this . svelteCheck ) ;
265
+ } ,
217
266
1000
218
267
) ;
219
268
}
@@ -264,7 +313,7 @@ parseOptions(async (opts) => {
264
313
} ;
265
314
266
315
if ( opts . watch ) {
267
- svelteCheckOptions . onProjectReload = ( ) => watcher . scheduleDiagnostics ( ) ;
316
+ svelteCheckOptions . onProjectReload = ( ) => watcher . scheduleDiagnostics ( true ) ;
268
317
const watcher = new DiagnosticsWatcher (
269
318
opts . workspaceUri ,
270
319
new SvelteCheck ( opts . workspaceUri . fsPath , svelteCheckOptions ) ,
0 commit comments