Files
sourcekit-lsp/Sources/SourceKitLSP/SourceKitIndexDelegate.swift
2023-10-02 17:00:04 -07:00

79 lines
2.3 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 IndexStoreDB
import SKCore
import Dispatch
/// `IndexDelegate` for the SourceKit workspace.
///
/// *Public for testing*.
public final class SourceKitIndexDelegate: IndexDelegate {
/// Provides mutual exclusion for other members.
let queue: DispatchQueue = DispatchQueue(label: "\(SourceKitIndexDelegate.self)-queue")
/// Registered `MainFilesDelegate`s to notify when main files change.
var mainFilesDelegates: [MainFilesDelegate] = []
/// 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() {}
public func processingAddedPending(_ count: Int) {
queue.sync {
pendingUnitCount += count
}
}
public func processingCompleted(_ count: Int) {
queue.sync {
pendingUnitCount -= count
if pendingUnitCount == 0 {
_indexChanged()
}
if pendingUnitCount < 0 {
assertionFailure("pendingUnitCount = \(pendingUnitCount) < 0")
pendingUnitCount = 0
_indexChanged()
}
}
}
/// *Must be called on queue*.
func _indexChanged() {
for delegate in mainFilesDelegates {
Task {
await delegate.mainFilesChanged()
}
}
}
/// Register a delegate to receive notifications when main files change.
public func registerMainFileChanged(_ delegate: MainFilesDelegate) {
queue.sync {
mainFilesDelegates.append(delegate)
}
}
/// Un-register a delegate to receive notifications when main files change.
public func unregisterMainFileChanged(_ delegate: MainFilesDelegate) {
queue.sync {
mainFilesDelegates.removeAll(where: { $0 === delegate })
}
}
}