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