Files
sourcekit-lsp/Sources/SourceKitLSP/SourceKitIndexDelegate.swift
Alex Hoppen 33d803f1d1 Change methods that were only public for testing purposes to be @_spi(Testing)
Fixes #876
Fixes #877
rdar://116705648
rdar://116705669
2024-06-11 19:03:26 -07:00

79 lines
2.2 KiB
Swift

//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
import Dispatch
import IndexStoreDB
import LSPLogging
import SKCore
import SKSupport
import SwiftExtensions
/// `IndexDelegate` for the SourceKit workspace.
actor SourceKitIndexDelegate: IndexDelegate {
let queue = AsyncQueue<Serial>()
/// Registered `MainFilesDelegate`s to notify when main files change.
var mainFilesChangedCallbacks: [@Sendable () async -> Void] = []
/// The count of pending unit events. Whenever this transitions to 0, it represents a time where
/// the index finished processing known events. Of course, that may have already changed by the
/// time we are notified.
var pendingUnitCount: Int = 0
public init() {}
nonisolated public func processingAddedPending(_ count: Int) {
queue.async {
await self.addPending(count)
}
}
private func addPending(_ count: Int) {
pendingUnitCount += count
}
nonisolated public func processingCompleted(_ count: Int) {
queue.async {
await self.processCompleted(count)
}
}
private func processCompleted(_ count: Int) {
pendingUnitCount -= count
if pendingUnitCount == 0 {
indexChanged()
}
if pendingUnitCount < 0 {
assertionFailure("pendingUnitCount = \(pendingUnitCount) < 0")
pendingUnitCount = 0
indexChanged()
}
}
private func indexChanged() {
logger.debug("IndexStoreDB changed")
for callback in mainFilesChangedCallbacks {
queue.async {
await callback()
}
}
}
/// Register a delegate to receive notifications when main files change.
public func addMainFileChangedCallback(_ callback: @escaping @Sendable () async -> Void) {
mainFilesChangedCallbacks.append(callback)
}
}