Skip to content

feat: add progress notifications #3

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 19, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions crates/emmylua_ls/src/context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub use file_diagnostic::FileDiagnostic;
use lsp_server::{Connection, ErrorCode, Message, RequestId, Response};
pub use snapshot::ServerContextSnapshot;
pub use status_bar::VsCodeStatusBar;
pub use status_bar::Task;
use std::{collections::HashMap, future::Future, sync::Arc};
use tokio::sync::{Mutex, RwLock};
use tokio_util::sync::CancellationToken;
Expand Down
99 changes: 85 additions & 14 deletions crates/emmylua_ls/src/context/status_bar.rs
Original file line number Diff line number Diff line change
@@ -1,34 +1,105 @@
use std::sync::Arc;

use lsp_types::{
NumberOrString, ProgressParams, ProgressParamsValue, WorkDoneProgress, WorkDoneProgressBegin,
WorkDoneProgressCreateParams, WorkDoneProgressEnd, WorkDoneProgressReport,
};
use serde::{Deserialize, Serialize};

use super::ClientProxy;


pub struct VsCodeStatusBar {
client: Arc<ClientProxy>
client: Arc<ClientProxy>,
}

#[derive(Clone, Copy)]
pub enum Task {
LoadWorkspace = 0,
DiagnoseWorkspace = 1,
}

fn get_task_name(task: &Task) -> &'static str {
match task {
Task::LoadWorkspace => "Load workspace",
Task::DiagnoseWorkspace => "Diagnose workspace",
}
}

impl VsCodeStatusBar {
pub fn new(client: Arc<ClientProxy>) -> Self {
Self {
client
}
Self { client }
}

pub fn set_server_status(&self, health: &str, loading: bool, message: &str) {
self.client.send_notification("emmy/setServerStatus", EmmyServerStatus {
health: health.to_string(),
loading,
message: message.to_string(),
});
self.client.send_notification(
"emmy/setServerStatus",
EmmyServerStatus {
health: health.to_string(),
loading,
message: message.to_string(),
},
);
}

pub fn start_task(&self, task: Task) {
self.client.send_notification(
"window/workDoneProgress/create",
WorkDoneProgressCreateParams {
token: NumberOrString::Number(task as i32),
},
);
self.client.send_notification(
"$/progress",
ProgressParams {
token: NumberOrString::Number(task as i32),
value: ProgressParamsValue::WorkDone(WorkDoneProgress::Begin(
WorkDoneProgressBegin {
title: get_task_name(&task).to_string(),
cancellable: Some(false),
message: Some(get_task_name(&task).to_string()),
percentage: None,
},
)),
},
)
}

pub fn update_task(&self, task: Task, percentage: Option<u32>, message: Option<String>) {
self.client.send_notification(
"$/progress",
ProgressParams {
token: NumberOrString::Number(task as i32),
value: ProgressParamsValue::WorkDone(WorkDoneProgress::Report(
WorkDoneProgressReport {
percentage,
cancellable: Some(false),
message,
},
)),
},
)
}

pub fn finish_task(&self, task: Task, message: Option<String>) {
self.client.send_notification(
"$/progress",
ProgressParams {
token: NumberOrString::Number(task as i32),
value: ProgressParamsValue::WorkDone(WorkDoneProgress::End(WorkDoneProgressEnd {
message,
})),
},
)
}

pub fn report_progress(&self, message: &str, percentage: f64) {
self.client.send_notification("emmy/progressReport", EmmyProgress {
text: message.to_string(),
percent: percentage,
});
self.client.send_notification(
"emmy/progressReport",
EmmyProgress {
text: message.to_string(),
percent: percentage,
},
);
}
}

Expand Down
36 changes: 31 additions & 5 deletions crates/emmylua_ls/src/handlers/initialized/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use std::{path::PathBuf, str::FromStr, sync::Arc};

use crate::{
cmd_args::CmdArgs,
context::{load_emmy_config, ClientProxy, ServerContextSnapshot, VsCodeStatusBar},
context::{load_emmy_config, ClientProxy, ServerContextSnapshot, Task, VsCodeStatusBar},
logger::init_logger,
};
use client_config::get_client_config;
Expand Down Expand Up @@ -103,7 +103,13 @@ pub async fn init_analysis(
info!("current config : {}", emmyrc_json);

status_bar.set_server_status("ok", true, "Load workspace");
status_bar.start_task(Task::LoadWorkspace);
status_bar.report_progress("Load workspace", 0.0);
status_bar.update_task(
Task::LoadWorkspace,
None,
Some("Loading workspace files".to_string()),
);

let mut workspace_folders = workspace_folders;
for workspace_root in &workspace_folders {
Expand All @@ -123,14 +129,28 @@ pub async fn init_analysis(
}

status_bar.report_progress("Collect files", 0.1);
status_bar.update_task(
Task::LoadWorkspace,
None,
Some(String::from("Collecting files")),
);
// load files
let files = collect_files(&workspace_folders, &emmyrc);
let files: Vec<(PathBuf, Option<String>)> =
files.into_iter().map(|file| file.into_tuple()).collect();

let file_count = files.len();
status_bar.report_progress(format!("Index {} files", file_count).as_str(), 0.5);
status_bar.update_task(
Task::LoadWorkspace,
None,
Some(format!("Indexing {} files", file_count)),
);
let file_ids = mut_analysis.update_files_by_path(files);
status_bar.finish_task(
Task::LoadWorkspace,
Some(String::from("Finished loading workspace files")),
);

drop(mut_analysis);

Expand Down Expand Up @@ -162,16 +182,22 @@ pub async fn init_analysis(
if file_count != 0 {
let text = format!("diagnose {} files", file_count);
let _p = Profile::new(text.as_str());
status_bar.start_task(Task::DiagnoseWorkspace);
while let Some(_) = rx.recv().await {
count += 1;

let message = format!("diagnostic {}/{}", count, file_count);
if client_id.is_vscode() {
status_bar.report_progress(
format!("diagnostic {}/{}", count, file_count).as_str(),
0.75,
);
status_bar.report_progress(message.as_str(), 0.75);
}
let percentage_done = count as u32 / file_count as u32;
status_bar.update_task(
Task::DiagnoseWorkspace,
Some(percentage_done),
Some(message),
);
if count == file_count {
status_bar.finish_task(Task::DiagnoseWorkspace, None);
break;
}
}
Expand Down
Loading