Fork of daniellemaywood.uk/gleam — Wasm codegen work
2

Configure Feed

Select the types of activity you want to include in your feed.

gleam / language-server / src / progress.rs
3.5 kB 103 lines
1use debug_ignore::DebugIgnore; 2use lsp_types::{ 3 InitializeParams, LspAny, ProgressParams, ProgressToken, WorkDoneProgressBegin, 4 WorkDoneProgressCreateParams, WorkDoneProgressEnd, 5}; 6 7const DOWNLOADING_TOKEN: &str = "downloading-dependencies"; 8 9pub trait ProgressReporter { 10 fn compilation_started(&self); 11 fn compilation_finished(&self); 12 fn dependency_downloading_started(&self); 13 fn dependency_downloading_finished(&self); 14} 15 16// Used to publish progress notifications to the client without waiting for 17// the usual request-response loop of the language server. 18#[derive(Debug, Clone)] 19pub struct ConnectionProgressReporter<'a> { 20 connection: DebugIgnore<&'a lsp_server::Connection>, 21} 22 23impl<'a> ConnectionProgressReporter<'a> { 24 pub fn new( 25 connection: &'a lsp_server::Connection, 26 // We don't actually need these but we take them anyway to ensure that 27 // this object is only created after the server has been initialised. 28 // If it was created before then the creation of the progress token 29 // would fail. 30 _initialise_params: &InitializeParams, 31 ) -> Self { 32 create_token(DOWNLOADING_TOKEN, connection); 33 Self { 34 connection: connection.into(), 35 } 36 } 37 38 fn send_notification(&self, token: &str, work_done: LspAny) { 39 let params = ProgressParams { 40 token: ProgressToken::String(token.to_string()), 41 value: work_done, 42 }; 43 let notification = lsp_server::Notification { 44 method: "$/progress".into(), 45 params: serde_json::to_value(params).expect("ProgressParams json"), 46 }; 47 self.connection 48 .sender 49 .send(lsp_server::Message::Notification(notification)) 50 .expect("send_work_done_notification send") 51 } 52} 53 54impl ProgressReporter for ConnectionProgressReporter<'_> { 55 fn compilation_started(&self) { 56 // Do nothing. This is only used for tests currently. 57 // In future we could make this emit a message to the client if compilation is taking a 58 // long time. 59 } 60 61 fn compilation_finished(&self) { 62 // Do nothing. This is only used for tests currently. 63 } 64 65 fn dependency_downloading_started(&self) { 66 let title = "Downloading Gleam dependencies"; 67 self.send_notification(DOWNLOADING_TOKEN, begin_message(title)); 68 } 69 70 fn dependency_downloading_finished(&self) { 71 self.send_notification(DOWNLOADING_TOKEN, end_message()); 72 } 73} 74 75fn end_message() -> LspAny { 76 serde_json::to_value(WorkDoneProgressEnd { message: None }) 77 .expect("Failed to serialize WorkDoneProgressEnd") 78} 79 80fn begin_message(title: &str) -> LspAny { 81 serde_json::to_value(WorkDoneProgressBegin { 82 title: title.into(), 83 cancellable: Some(false), 84 message: None, 85 percentage: None, 86 }) 87 .expect("Failed to serialize WorkDoneProgressBegin") 88} 89 90fn create_token(token: &str, connection: &lsp_server::Connection) { 91 let params = WorkDoneProgressCreateParams { 92 token: ProgressToken::String(token.into()), 93 }; 94 let request = lsp_server::Request { 95 id: format!("create-token--{token}").into(), 96 method: "window/workDoneProgress/create".into(), 97 params: serde_json::to_value(params).expect("WorkDoneProgressCreateParams json"), 98 }; 99 connection 100 .sender 101 .send(lsp_server::Message::Request(request)) 102 .expect("WorkDoneProgressCreate"); 103}