@@ -248,21 +248,26 @@ package final class TestSourceKitLSPClient: MessageHandler, Sendable {
248248 /// - Note: This also returns any notifications sent before the call to
249249 /// `nextNotification`.
250250 package func nextNotification( timeout: Duration = . seconds( defaultTimeout) ) async throws -> any NotificationType {
251- return try await withThrowingTaskGroup ( of: ( any NotificationType ) . self) { taskGroup in
252- taskGroup. addTask {
253- for await notification in self . notifications {
254- return notification
255- }
256- throw NotificationTimeoutError ( )
257- }
258- taskGroup. addTask {
259- try await Task . sleep ( for: timeout)
260- throw NotificationTimeoutError ( )
251+ // The task that gets the next notification from `self.notifications`.
252+ let notificationYielder = Task {
253+ for await notification in self . notifications {
254+ return notification
261255 }
262- let result = try await taskGroup. next ( ) !
263- taskGroup. cancelAll ( )
264- return result
256+ throw NotificationTimeoutError ( )
257+ }
258+ // After `timeout`, we tell `notificationYielder` that we are no longer interested in its result by cancelling it.
259+ // We wait for `notificationYielder` to accept this cancellation instead of returning immediately to avoid a
260+ // situation where `notificationYielder` continues running, eats the first notification but it then never gets
261+ // delivered to the test because we already delivered a timeout.
262+ let cancellationTask = Task {
263+ try await Task . sleep ( for: timeout)
264+ notificationYielder. cancel ( )
265+ }
266+ defer {
267+ // We have received a value and don't need the cancellationTask anymore
268+ cancellationTask. cancel ( )
265269 }
270+ return try await notificationYielder. value
266271 }
267272
268273 /// Await the next diagnostic notification sent to the client.
0 commit comments