mirror of
https://github.com/apple/sourcekit-lsp.git
synced 2026-03-06 18:24:36 +01:00
Fix an issue in Debounce that added up debounce durations
If calls from `Debouncer` were scheduled every 0.5s but the debounce duration was 1s, we would always schedule the pending task and schedule a new one, never actually committing one. Debounce at most the debounce duration from the initially scheduled call.
This commit is contained in:
@@ -33,14 +33,15 @@ public actor Debouncer<Parameter> {
|
||||
private let makeCall: (Parameter) async -> Void
|
||||
|
||||
/// In the time between the call to `scheduleCall` and the call actually being committed (ie. in the time that the
|
||||
/// call can be debounced), the task that would commit the call (unless cancelled) and the parameter with which this
|
||||
/// call should be made.
|
||||
private var inProgressData: (Parameter, Task<Void, Never>)?
|
||||
/// call can be debounced), the task that would commit the call (unless cancelled), the parameter with which this
|
||||
/// call should be made and the time at which the call should be made. Keeping track of the time ensures that we don't
|
||||
/// indefinitely debounce if a new `scheduleCall` is made every 0.4s but we debounce for 0.5s.
|
||||
private var inProgressData: (Parameter, ContinuousClock.Instant, Task<Void, Never>)?
|
||||
|
||||
public init(
|
||||
debounceDuration: Duration,
|
||||
combineResults: @escaping (Parameter, Parameter) -> Parameter,
|
||||
_ makeCall: @escaping (Parameter) async -> Void
|
||||
_ makeCall: @Sendable @escaping (Parameter) async -> Void
|
||||
) {
|
||||
self.debounceDuration = debounceDuration
|
||||
self.combineParameters = combineResults
|
||||
@@ -52,13 +53,15 @@ public actor Debouncer<Parameter> {
|
||||
/// `debounceDuration` after the second `scheduleCall` call.
|
||||
public func scheduleCall(_ parameter: Parameter) {
|
||||
var parameter = parameter
|
||||
if let (inProgressParameter, inProgressTask) = inProgressData {
|
||||
var targetDate = ContinuousClock.now + debounceDuration
|
||||
if let (inProgressParameter, inProgressTargetDate, inProgressTask) = inProgressData {
|
||||
inProgressTask.cancel()
|
||||
parameter = combineParameters(inProgressParameter, parameter)
|
||||
targetDate = inProgressTargetDate
|
||||
}
|
||||
let task = Task {
|
||||
do {
|
||||
try await Task.sleep(for: debounceDuration)
|
||||
try await Task.sleep(until: targetDate)
|
||||
try Task.checkCancellation()
|
||||
} catch {
|
||||
return
|
||||
@@ -66,12 +69,12 @@ public actor Debouncer<Parameter> {
|
||||
inProgressData = nil
|
||||
await makeCall(parameter)
|
||||
}
|
||||
inProgressData = (parameter, task)
|
||||
inProgressData = (parameter, ContinuousClock.now + debounceDuration, task)
|
||||
}
|
||||
}
|
||||
|
||||
extension Debouncer<Void> {
|
||||
public init(debounceDuration: Duration, _ makeCall: @escaping () async -> Void) {
|
||||
public init(debounceDuration: Duration, _ makeCall: @Sendable @escaping () async -> Void) {
|
||||
self.init(debounceDuration: debounceDuration, combineResults: { _, _ in }, makeCall)
|
||||
}
|
||||
|
||||
|
||||
@@ -414,7 +414,6 @@ public final actor SemanticIndexManager {
|
||||
///
|
||||
/// If file's target is known to be up-to-date, this returns almost immediately.
|
||||
public func prepareFileForEditorFunctionality(_ uri: DocumentURI) async {
|
||||
// Should be kept in sync with `schedulePreparationForEditorFunctionality`.
|
||||
guard let target = await buildSystemManager.canonicalConfiguredTarget(for: uri) else {
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user