@@ -89,9 +89,6 @@ public actor BuildSystemManager {
89
89
/// The set of watched files, along with their main file and language.
90
90
var watchedFiles : [ DocumentURI : ( mainFile: DocumentURI , language: Language ) ] = [ : ]
91
91
92
- /// Statuses for each main file, containing build settings from the build systems.
93
- var mainFileStatuses : [ DocumentURI : MainFileStatus ] = [ : ]
94
-
95
92
/// The underlying primary build system.
96
93
let buildSystem : BuildSystem ?
97
94
@@ -208,11 +205,8 @@ extension BuildSystemManager {
208
205
self . watchedFiles [ uri] = ( mainFile, language)
209
206
}
210
207
211
- let newStatus = await self . cachedStatusOrRegisterForSettings ( for: mainFile, language: language)
212
-
213
- if newStatus. buildSettingsChange != nil , let delegate = self . _delegate {
214
- await delegate. fileBuildSettingsChanged ( [ uri] )
215
- }
208
+ await buildSystem? . registerForChangeNotifications ( for: mainFile, language: language)
209
+ fallbackBuildSystem? . registerForChangeNotifications ( for: mainFile, language: language)
216
210
}
217
211
218
212
/// Return settings for `file` based on the `change` settings for `mainFile`.
@@ -233,115 +227,6 @@ extension BuildSystemManager {
233
227
}
234
228
}
235
229
236
- /// Handle a request for `FileBuildSettings` on `mainFile`.
237
- ///
238
- /// Updates and returns the new `MainFileStatus` for `mainFile`.
239
- func cachedStatusOrRegisterForSettings(
240
- for mainFile: DocumentURI ,
241
- language: Language
242
- ) async -> MainFileStatus {
243
- // If we already have a status for the main file, use that.
244
- // Don't update any existing timeout.
245
- if let status = self . mainFileStatuses [ mainFile] {
246
- return status
247
- }
248
- // This is a new `mainFile` that we need to handle. We need to fetch the
249
- // build settings.
250
- let newStatus : MainFileStatus
251
- if let buildSystem = self . buildSystem {
252
- // Register the timeout if it's applicable.
253
- if let fallback = self . fallbackBuildSystem {
254
- Task {
255
- try await Task . sleep ( nanoseconds: UInt64 ( self . fallbackSettingsTimeout. nanoseconds ( ) !) )
256
- await self . handleFallbackTimer ( for: mainFile, language: language, fallback)
257
- }
258
- }
259
-
260
- // Intentionally register with the `BuildSystem` after setting the fallback to allow for
261
- // testing of the fallback system triggering before the `BuildSystem` can reply (e.g. if a
262
- // fallback time of 0 is specified).
263
- await buildSystem. registerForChangeNotifications ( for: mainFile, language: language)
264
-
265
-
266
- newStatus = . waiting
267
- } else if let fallback = self . fallbackBuildSystem {
268
- // Only have a fallback build system. We consider it be a primary build
269
- // system that functions synchronously.
270
- if let settings = fallback. buildSettings ( for: mainFile, language: language) {
271
- newStatus = . primary( settings)
272
- } else {
273
- newStatus = . unsupported
274
- }
275
- } else { // Don't have any build systems.
276
- newStatus = . unsupported
277
- }
278
-
279
- if let status = self . mainFileStatuses [ mainFile] {
280
- // Since we await above, another call to `cachedStatusOrRegisterForSettings`
281
- // might have set the main file status of `mainFile`. If this race happened,
282
- // return the value set by the concurrently executing function. This is safe
283
- // since all calls from this function are either side-effect free or
284
- // idempotent.
285
- return status
286
- }
287
-
288
- self . mainFileStatuses [ mainFile] = newStatus
289
- return newStatus
290
- }
291
-
292
- /// Update and notify our delegate for the given main file changes if they are
293
- /// convertible into `FileBuildSettingsChange`.
294
- func updateAndNotifyStatuses( changes: [ DocumentURI : MainFileStatus ] ) async {
295
- var changedWatchedFiles = Set < DocumentURI > ( )
296
- for (mainFile, status) in changes {
297
- let watches = self . watchedFiles. filter { $1. mainFile == mainFile }
298
- guard !watches. isEmpty else {
299
- // Possible notification after the file was unregistered. Ignore.
300
- continue
301
- }
302
- let prevStatus = self . mainFileStatuses [ mainFile]
303
- self . mainFileStatuses [ mainFile] = status
304
-
305
- // It's possible that the command line arguments didn't change
306
- // (waitingFallback --> fallback), in that case we don't need to report a change.
307
- // If we were waiting though, we need to emit an initial change.
308
- guard prevStatus == . waiting || status. buildSettings != prevStatus? . buildSettings else {
309
- continue
310
- }
311
- guard status. buildSettingsChange != nil else {
312
- continue
313
- }
314
- for watch in watches {
315
- changedWatchedFiles. insert ( watch. key)
316
- }
317
- }
318
-
319
- if !changedWatchedFiles. isEmpty, let delegate = self . _delegate {
320
- await delegate. fileBuildSettingsChanged ( changedWatchedFiles)
321
- }
322
- }
323
-
324
- /// Handle the fallback timer firing for a given `mainFile`.
325
- ///
326
- /// Since this doesn't occur immediately it's possible that the `mainFile` is
327
- /// no longer referenced or is referenced by multiple watched files.
328
- func handleFallbackTimer(
329
- for mainFile: DocumentURI ,
330
- language: Language ,
331
- _ fallback: FallbackBuildSystem
332
- ) async {
333
- // There won't be a current status if it's unreferenced by any watched file.
334
- // Similarly, if the status isn't `waiting` then there's nothing to do.
335
- guard let status = self . mainFileStatuses [ mainFile] , status == . waiting else {
336
- return
337
- }
338
- if let settings = fallback. buildSettings ( for: mainFile, language: language) {
339
- await self . updateAndNotifyStatuses ( changes: [ mainFile: . waitingUsingFallback( settings) ] )
340
- } else {
341
- // Keep the status as waiting.
342
- }
343
- }
344
-
345
230
public func unregisterForChangeNotifications( for uri: DocumentURI ) async {
346
231
guard let mainFile = self . watchedFiles [ uri] ? . mainFile else {
347
232
log ( " Unbalanced calls for registerForChangeNotifications and unregisterForChangeNotifications " , level: . warning)
@@ -357,7 +242,6 @@ extension BuildSystemManager {
357
242
if !self . watchedFiles. values. lazy. map ( { $0. mainFile } ) . contains ( mainFile) {
358
243
// This was the last reference to the main file. Remove it.
359
244
await self . buildSystem? . unregisterForChangeNotifications ( for: mainFile)
360
- self . mainFileStatuses [ mainFile] = nil
361
245
}
362
246
}
363
247
@@ -377,35 +261,14 @@ extension BuildSystemManager: BuildSystemDelegate {
377
261
}
378
262
}
379
263
380
- public func fileBuildSettingsChangedImpl( _ changes: Set < DocumentURI > ) async {
381
- var statusChanges : [ DocumentURI : MainFileStatus ] = [ : ]
382
- for mainFile in changes {
383
- let watches = self . watchedFiles. filter { $1. mainFile == mainFile }
384
- guard let firstWatch = watches. first else {
385
- // Possible notification after the file was unregistered. Ignore.
386
- continue
387
- }
388
- let newStatus : MainFileStatus
389
-
390
- let settings = await self . buildSettings ( for: mainFile, language: firstWatch. value. language)
391
-
392
- if let settings {
393
- newStatus = settings. isFallback ? . fallback( settings. buildSettings) : . primary( settings. buildSettings)
394
- } else if let fallback = self . fallbackBuildSystem {
395
- // FIXME: we need to stop threading the language everywhere, or we need the build system
396
- // itself to pass it in here. Or alternatively cache the fallback settings/language earlier?
397
- let language = firstWatch. value. language
398
- if let settings = fallback. buildSettings ( for: mainFile, language: language) {
399
- newStatus = . fallback( settings)
400
- } else {
401
- newStatus = . unsupported
402
- }
403
- } else {
404
- newStatus = . unsupported
405
- }
406
- statusChanges [ mainFile] = newStatus
264
+ public func fileBuildSettingsChangedImpl( _ changedFiles: Set < DocumentURI > ) async {
265
+ let changedWatchedFiles = changedFiles. flatMap ( { mainFile in
266
+ self . watchedFiles. filter { $1. mainFile == mainFile } . keys
267
+ } )
268
+
269
+ if !changedWatchedFiles. isEmpty, let delegate = self . _delegate {
270
+ await delegate. fileBuildSettingsChanged ( Set ( changedWatchedFiles) )
407
271
}
408
- await self . updateAndNotifyStatuses ( changes: statusChanges)
409
272
}
410
273
411
274
// FIXME: (async) Make this method isolated once `BuildSystemDelegate` has ben asyncified
@@ -484,11 +347,7 @@ extension BuildSystemManager: MainFilesDelegate {
484
347
log ( " main file for ' \( uri) ' changed old: ' \( state. mainFile) ' -> new: ' \( newMainFile) ' " , level: . info)
485
348
await self . checkUnreferencedMainFile ( state. mainFile)
486
349
487
- let newStatus = await self . cachedStatusOrRegisterForSettings (
488
- for: newMainFile, language: language)
489
- if newStatus. buildSettingsChange != nil {
490
- buildSettingsChanges. insert ( uri)
491
- }
350
+ buildSettingsChanges. insert ( uri)
492
351
}
493
352
}
494
353
@@ -504,11 +363,6 @@ extension BuildSystemManager {
504
363
public func _cachedMainFile( for uri: DocumentURI ) -> DocumentURI ? {
505
364
watchedFiles [ uri] ? . mainFile
506
365
}
507
-
508
- /// *For Testing* Returns the main file used for `uri`, if this is a registered file.
509
- public func _cachedMainFileSettings( for uri: DocumentURI ) -> FileBuildSettings ? ? {
510
- mainFileStatuses [ uri] ? . buildSettings
511
- }
512
366
}
513
367
514
368
/// Choose a new main file for the given uri, preferring to use a previous main file if still
0 commit comments