Skip to content

Commit b92d27e

Browse files
authored
Merge pull request #252 from benlangmuir/deadlock-begone
Make BuildSystemManager passthrough notifications fully `async
2 parents 77c2ae4 + f5bd9cf commit b92d27e

File tree

3 files changed

+58
-8
lines changed

3 files changed

+58
-8
lines changed

Sources/SKCore/BuildSystemManager.swift

+10-6
Original file line numberDiff line numberDiff line change
@@ -210,17 +210,21 @@ extension BuildSystemManager: BuildSystemDelegate {
210210
}
211211

212212
public func filesDependenciesUpdated(_ changedFiles: Set<DocumentURI>) {
213-
if let delegate = self.delegate {
214-
notifyQueue.async {
215-
delegate.filesDependenciesUpdated(changedFiles)
213+
queue.async {
214+
if let delegate = self._delegate {
215+
self.notifyQueue.async {
216+
delegate.filesDependenciesUpdated(changedFiles)
217+
}
216218
}
217219
}
218220
}
219221

220222
public func buildTargetsChanged(_ changes: [BuildTargetEvent]) {
221-
if let delegate = self.delegate {
222-
notifyQueue.async {
223-
delegate.buildTargetsChanged(changes)
223+
queue.async {
224+
if let delegate = self._delegate {
225+
self.notifyQueue.async {
226+
delegate.buildTargetsChanged(changes)
227+
}
224228
}
225229
}
226230
}

Tests/SKCoreTests/BuildSystemManagerTests.swift

+47-2
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,38 @@ final class BuildSystemManagerTests: XCTestCase {
342342

343343
wait(for: [changedB], timeout: 10, enforceOrder: false)
344344
}
345+
346+
func testDependenciesUpdated() {
347+
let a = DocumentURI(string: "bsm:a.swift")
348+
let mainFiles = ManualMainFilesProvider()
349+
mainFiles.mainFiles = [a: Set([a])]
350+
351+
class DepUpdateDuringRegistrationBS: ManualBuildSystem {
352+
override func registerForChangeNotifications(for uri: DocumentURI, language: Language) {
353+
delegate?.filesDependenciesUpdated([uri])
354+
}
355+
}
356+
357+
let bs = DepUpdateDuringRegistrationBS()
358+
let bsm = BuildSystemManager(buildSystem: bs, mainFilesProvider: mainFiles)
359+
let del = BSMDelegate(bsm)
360+
361+
bs.map[a] = FileBuildSettings(compilerArguments: ["x"], language: .swift)
362+
let initial = expectation(description: "initial settings")
363+
del.expected = [(a, bs.map[a]!, initial, #file, #line)]
364+
365+
let depUpdate1 = expectation(description: "dependencies update during registration")
366+
del.expectedDependenciesUpdate = [(a, depUpdate1, #file, #line)]
367+
368+
bsm.registerForChangeNotifications(for: a, language: .swift)
369+
wait(for: [initial, depUpdate1], timeout: 10, enforceOrder: false)
370+
371+
let depUpdate2 = expectation(description: "dependencies update 2")
372+
del.expectedDependenciesUpdate = [(a, depUpdate2, #file, #line)]
373+
374+
bsm.filesDependenciesUpdated([a])
375+
wait(for: [depUpdate2], timeout: 10, enforceOrder: false)
376+
}
345377
}
346378

347379
// MARK: Helper Classes for Testing
@@ -359,7 +391,7 @@ private final class ManualMainFilesProvider: MainFilesProvider {
359391
}
360392

361393
/// A simple `BuildSystem` that wraps a dictionary, for testing.
362-
final class ManualBuildSystem: BuildSystem {
394+
class ManualBuildSystem: BuildSystem {
363395
var map: [DocumentURI: FileBuildSettings] = [:]
364396

365397
var delegate: BuildSystemDelegate? = nil
@@ -397,6 +429,7 @@ private final class BSMDelegate: BuildSystemDelegate {
397429
let queue: DispatchQueue = DispatchQueue(label: "\(BSMDelegate.self)")
398430
unowned let bsm: BuildSystemManager
399431
var expected: [(uri: DocumentURI, settings: FileBuildSettings?, expectation: XCTestExpectation, file: StaticString, line: UInt)] = []
432+
var expectedDependenciesUpdate: [(uri: DocumentURI, expectation: XCTestExpectation, file: StaticString, line: UInt)] = []
400433

401434
init(_ bsm: BuildSystemManager) {
402435
self.bsm = bsm
@@ -420,5 +453,17 @@ private final class BSMDelegate: BuildSystemDelegate {
420453
}
421454

422455
func buildTargetsChanged(_ changes: [BuildTargetEvent]) {}
423-
func filesDependenciesUpdated(_ changedFiles: Set<DocumentURI>) {}
456+
func filesDependenciesUpdated(_ changedFiles: Set<DocumentURI>) {
457+
queue.sync {
458+
for uri in changedFiles {
459+
guard let expected = expectedDependenciesUpdate.first(where: { $0.uri == uri }) else {
460+
XCTFail("unexpected filesDependenciesUpdated for \(uri)")
461+
continue
462+
}
463+
464+
XCTAssertEqual(uri, expected.uri, file: expected.file, line: expected.line)
465+
expected.expectation.fulfill()
466+
}
467+
}
468+
}
424469
}

Tests/SKCoreTests/XCTestManifests.swift

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ extension BuildSystemManagerTests {
2121
// `swift test --generate-linuxmain`
2222
// to regenerate.
2323
static let __allTests__BuildSystemManagerTests = [
24+
("testDependenciesUpdated", testDependenciesUpdated),
2425
("testMainFiles", testMainFiles),
2526
("testSettingsChangedAfterUnregister", testSettingsChangedAfterUnregister),
2627
("testSettingsHeaderChangeMainFile", testSettingsHeaderChangeMainFile),

0 commit comments

Comments
 (0)