use lsp_types::{DidChangeTextDocumentParams, Uri};
use std::collections::HashMap;
use tokio::sync::mpsc;
use super::ServerContextSnapshot;
use crate::handlers::on_did_change_text_document;
pub struct DidChangeCoalescer {
tx: mpsc::UnboundedSender<DidChangeTextDocumentParams>,
}
impl DidChangeCoalescer {
pub fn new(context: ServerContextSnapshot) -> Self {
let (tx, rx) = mpsc::unbounded_channel();
tokio::spawn(Self::worker(rx, context));
Self { tx }
}
pub fn enqueue(&self, params: DidChangeTextDocumentParams) {
let _ = self.tx.send(params);
}
async fn worker(
mut rx: mpsc::UnboundedReceiver<DidChangeTextDocumentParams>,
context: ServerContextSnapshot,
) {
loop {
let first = match rx.recv().await {
Some(params) => params,
None => return, };
let mut latest: HashMap<Uri, DidChangeTextDocumentParams> = HashMap::new();
latest.insert(first.text_document.uri.clone(), first);
let mut drained_count = 1usize;
while let Ok(params) = rx.try_recv() {
drained_count += 1;
latest.insert(params.text_document.uri.clone(), params);
}
for (_uri, params) in latest {
on_did_change_text_document(context.clone(), params).await;
}
context
.debounced_analysis()
.finish_in_flight_changes(drained_count)
.await;
}
}
}