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