Skip to content

Commit

Permalink
feat: add a timer for changed event
Browse files Browse the repository at this point in the history
- zed din't send the did_save event
  • Loading branch information
washanhanzi committed Oct 12, 2024
1 parent b18fb79 commit ada8f6e
Show file tree
Hide file tree
Showing 12 changed files with 182 additions and 130 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ anyhow = "1.0.88"
clap = { version = "4.5.18", features = ["derive"] }
once_cell = "1.19.0"
semver = "1.0.23"
tracing = "0.1.40"

openssl = { version = '0.10', optional = true }

Expand Down
1 change: 1 addition & 0 deletions src/controller.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
pub mod appraiser;
mod cargo;
mod change_timer;
mod code_action;
mod hover;

Expand Down
138 changes: 66 additions & 72 deletions src/controller/appraiser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use crate::{

use super::{
cargo::{parse_cargo_output, CargoResolveOutput},
change_timer::ChangeTimer,
hover::hover,
};

Expand All @@ -41,6 +42,7 @@ pub enum CargoDocumentEvent {
Opened(CargoTomlPayload),
Saved(CargoTomlPayload),
Changed(CargoTomlPayload),
ChangeTimer(Ctx),
//reset state, String is path
Closed(Url),
//result from cargo command
Expand Down Expand Up @@ -74,16 +76,21 @@ impl Appraiser {
let tx_for_cargo = tx.clone();
tokio::spawn(async move {
while let Some(event) = cargo_rx.recv().await {
let output = parse_cargo_output(&event).await;
if let Err(e) = tx_for_cargo
.send(CargoDocumentEvent::CargoResolved(output))
.await
{
eprintln!("cargo resolved tx error: {}", e);
if let Some(output) = parse_cargo_output(&event).await {
if let Err(e) = tx_for_cargo
.send(CargoDocumentEvent::CargoResolved(output))
.await
{
eprintln!("cargo resolved tx error: {}", e);
}
}
}
});

//timer task
let timer = ChangeTimer::new(tx.clone(), 3000);
let timer_tx = timer.spawn();

//main loop
//render task sender
let render_tx = self.render_tx.clone();
Expand Down Expand Up @@ -149,7 +156,7 @@ impl Appraiser {
}
}
CargoDocumentEvent::Changed(msg) => {
let diff = state.partial_reconsile(&msg.uri, &msg.text);
let diff = state.reconsile(&msg.uri, &msg.text);
let doc = state.state(&msg.uri).unwrap();
for v in &diff.range_updated {
if let Some(node) = doc.symbol(v) {
Expand Down Expand Up @@ -182,77 +189,24 @@ impl Appraiser {
.await
.unwrap();
}
}
CargoDocumentEvent::Opened(msg) | CargoDocumentEvent::Saved(msg) => {
let diff = state.reconsile(&msg.uri, &msg.text);
let doc = state.state(&msg.uri).unwrap();

// Loop through both created and changed nodes
for v in &diff.created {
// Send to a dedicated render task
if let Some(n) = doc.symbol(v) {
render_tx
.send(DecorationEvent::DependencyLoading(
msg.uri.clone(),
v.to_string(),
n.range,
))
.await
.unwrap();
}
}

for v in diff.range_updated.iter().chain(diff.value_updated.iter()) {
// Send to a dedicated render task
if let Some(n) = doc.symbol(v) {
render_tx
.send(DecorationEvent::DependencyLoading(
msg.uri.clone(),
v.to_string(),
n.range,
))
.await
.unwrap();
}
}

for v in &diff.deleted {
render_tx
.send(DecorationEvent::DependencyRemove(
msg.uri.clone(),
v.to_string(),
))
.await
.unwrap();
}

//no change to resolve
if !doc.is_dirty() {
continue;
}

for v in doc.dirty_nodes.keys() {
if let Some(n) = doc.symbol(v) {
render_tx
.send(DecorationEvent::DependencyLoading(
msg.uri.clone(),
v.to_string(),
n.range,
))
.await
.unwrap();
}
}

//resolve cargo dependencies in another task
cargo_tx
timer_tx
.send(Ctx {
uri: msg.uri.clone(),
uri: msg.uri,
rev: doc.rev,
})
.await
.unwrap();
}
CargoDocumentEvent::Opened(msg) | CargoDocumentEvent::Saved(msg) => {
let _ = state.reconsile(&msg.uri, &msg.text);

start_resolve(&msg.uri, &mut state, &render_tx, &cargo_tx).await;
}
CargoDocumentEvent::ChangeTimer(ctx) => {
if state.check_rev(&ctx.uri, ctx.rev) {
start_resolve(&ctx.uri, &mut state, &render_tx, &cargo_tx).await;
}
}
CargoDocumentEvent::CargoResolved(mut output) => {
let Some(doc) = state.state_mut_with_rev(&output.ctx.uri, output.ctx.rev)
else {
Expand Down Expand Up @@ -359,3 +313,43 @@ impl Appraiser {
tx
}
}

async fn start_resolve(
uri: &Url,
state: &mut Workspace,
render_tx: &Sender<DecorationEvent>,
cargo_tx: &Sender<Ctx>,
) {
//start from here the resolve process
state.populate_dependencies(uri);
let doc = state.state(uri).unwrap();

//no change to resolve
if !doc.is_dirty() {
return;
}

for v in doc.dirty_nodes.keys() {
if let Some(n) = doc.symbol(v) {
render_tx
.send(DecorationEvent::DependencyLoading(
uri.clone(),
v.to_string(),
n.range,
))
.await
.unwrap();
}
}

//resolve cargo dependencies in another task
if let Err(e) = cargo_tx
.send(Ctx {
uri: uri.clone(),
rev: doc.rev,
})
.await
{
eprintln!("cargo resolve tx error: {}", e);
}
}
24 changes: 13 additions & 11 deletions src/controller/cargo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,20 @@ pub struct CargoResolveOutput {
pub summaries: HashMap<String, Vec<Summary>>,
}

pub async fn parse_cargo_output(ctx: &Ctx) -> CargoResolveOutput {
pub async fn parse_cargo_output(ctx: &Ctx) -> Option<CargoResolveOutput> {
//TODO refactor
let Ok(path) = ctx.uri.to_file_path() else {
return CargoResolveOutput {
ctx: ctx.clone(),
dependencies: HashMap::new(),
summaries: HashMap::new(),
};
return None;
};
let Ok(gctx) = cargo::util::context::GlobalContext::default() else {
return None;
};
let Ok(workspace) = cargo::core::Workspace::new(path.as_path(), &gctx) else {
return None;
};
let Ok(current) = workspace.current() else {
return None;
};
let gctx = cargo::util::context::GlobalContext::default().unwrap();
let workspace = cargo::core::Workspace::new(path.as_path(), &gctx).unwrap();
let current = workspace.current().unwrap();
let deps = current.dependencies();

let mut edge_kinds = HashSet::with_capacity(3);
Expand Down Expand Up @@ -102,12 +104,12 @@ pub async fn parse_cargo_output(ctx: &Ctx) -> CargoResolveOutput {
}
}

CargoResolveOutput {
Some(CargoResolveOutput {
ctx: ctx.clone(),
dependencies: res,
//TODO maybe reuse gctx
summaries: summaries_map(path.as_path()),
}
})
}

//TODO the current Vec<Summary> didn't include yanked
Expand Down
56 changes: 56 additions & 0 deletions src/controller/change_timer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
use std::time::Duration;

use tokio::sync::mpsc::{self, Sender};
use tokio::time::{sleep, Instant};
use tower_lsp::lsp_types::Url;

use super::{appraiser::Ctx, CargoDocumentEvent};

//change timer
pub struct ChangeTimer {
tx: Sender<CargoDocumentEvent>,
timeout: u64,
}

impl ChangeTimer {
pub fn new(tx: Sender<CargoDocumentEvent>, timeout: u64) -> Self {
Self { tx, timeout }
}

pub fn spawn(&self) -> Sender<Ctx> {
//create a tokio mpsc channel
let (internal_tx, mut internal_rx) = mpsc::channel::<Ctx>(32);
let tx = self.tx.clone();
let timeout = self.timeout;
tokio::spawn(async move {
let mut uri: Option<Url> = None;
let mut rev = 0;
let delay = sleep(Duration::from_millis(timeout));
tokio::pin!(delay);
loop {
tokio::select! {
Some(ctx) = internal_rx.recv() => {
uri = Some(ctx.uri.clone());
rev = ctx.rev;
// Reset the delay to 1 second after receiving a message
delay.as_mut().reset(Instant::now() + Duration::from_millis(timeout));
}
_ = &mut delay => {
if let Some(current_uri) = &uri {
let ctx = Ctx {
uri: current_uri.clone(),
rev,
};
if let Err(e) = tx.send(CargoDocumentEvent::ChangeTimer(ctx)).await {
eprintln!("Failed to send Ctx: {}", e);
}
}
// Reset the delay after it has elapsed
delay.as_mut().reset(Instant::now() + Duration::from_millis(timeout));
}
}
}
});
internal_tx
}
}
2 changes: 2 additions & 0 deletions src/entity.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
mod dependency;
mod manifest;
mod package;
mod symbol;
mod table;

pub use dependency::*;
pub use manifest::*;
pub use symbol::*;
pub use table::*;
6 changes: 6 additions & 0 deletions src/entity/symbol.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
pub struct SymbolDiff {
pub created: Vec<String>,
pub range_updated: Vec<String>,
pub value_updated: Vec<String>,
pub deleted: Vec<String>,
}
16 changes: 14 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,13 @@ impl LanguageServer for CargoAppraiser {
.send(CargoDocumentEvent::CodeAction(uri, params.range, tx))
.await
{
eprintln!("error sending code action event: {}", e);
self.client
.log_message(
MessageType::ERROR,
&format!("error sending code action event: {}", e),
)
.await;
return Ok(None);
};
match rx.await {
Ok(code_action) => return Ok(Some(code_action)),
Expand All @@ -230,7 +236,13 @@ impl LanguageServer for CargoAppraiser {
))
.await
{
eprintln!("error sending hover event: {}", e);
self.client
.log_message(
MessageType::ERROR,
&format!("error sending hover event: {}", e),
)
.await;
return Ok(None);
};
match rx.await {
Ok(hover) => return Ok(Some(hover)),
Expand Down
Loading

0 comments on commit ada8f6e

Please sign in to comment.