aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2020-06-26 16:07:14 +0100
committerAleksey Kladov <[email protected]>2020-06-26 16:07:14 +0100
commit9d15e8fc4f875f6da2cd2bd89c62bb96fa64ef1b (patch)
tree8d782ee4c736b57c8eaab0e65ee9746c3880a4e4 /crates
parent1893289e5c7cebeeb9705c031c996fc29d8c5b54 (diff)
Type safer requests
Diffstat (limited to 'crates')
-rw-r--r--crates/rust-analyzer/src/global_state.rs53
-rw-r--r--crates/rust-analyzer/src/lsp_utils.rs21
-rw-r--r--crates/rust-analyzer/src/main_loop.rs40
-rw-r--r--crates/rust-analyzer/src/reload.rs8
4 files changed, 73 insertions, 49 deletions
diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs
index 41659f99d..3c9752259 100644
--- a/crates/rust-analyzer/src/global_state.rs
+++ b/crates/rust-analyzer/src/global_state.rs
@@ -7,7 +7,7 @@ use std::{sync::Arc, time::Instant};
7 7
8use crossbeam_channel::{unbounded, Receiver, Sender}; 8use crossbeam_channel::{unbounded, Receiver, Sender};
9use flycheck::FlycheckHandle; 9use flycheck::FlycheckHandle;
10use lsp_types::Url; 10use lsp_types::{request::Request as _, Url};
11use parking_lot::RwLock; 11use parking_lot::RwLock;
12use ra_db::{CrateId, VfsPath}; 12use ra_db::{CrateId, VfsPath};
13use ra_ide::{Analysis, AnalysisChange, AnalysisHost, FileId}; 13use ra_ide::{Analysis, AnalysisChange, AnalysisHost, FileId};
@@ -18,6 +18,7 @@ use crate::{
18 diagnostics::{CheckFixes, DiagnosticCollection}, 18 diagnostics::{CheckFixes, DiagnosticCollection},
19 from_proto, 19 from_proto,
20 line_endings::LineEndings, 20 line_endings::LineEndings,
21 lsp_utils::notification_new,
21 main_loop::Task, 22 main_loop::Task,
22 reload::SourceRootConfig, 23 reload::SourceRootConfig,
23 request_metrics::{LatestRequests, RequestMetrics}, 24 request_metrics::{LatestRequests, RequestMetrics},
@@ -57,6 +58,7 @@ pub(crate) type ReqQueue = lsp_server::ReqQueue<(String, Instant), ReqHandler>;
57/// Note that this struct has more than on impl in various modules! 58/// Note that this struct has more than on impl in various modules!
58pub(crate) struct GlobalState { 59pub(crate) struct GlobalState {
59 sender: Sender<lsp_server::Message>, 60 sender: Sender<lsp_server::Message>,
61 req_queue: ReqQueue,
60 pub(crate) task_pool: Handle<TaskPool<Task>, Receiver<Task>>, 62 pub(crate) task_pool: Handle<TaskPool<Task>, Receiver<Task>>,
61 pub(crate) loader: Handle<Box<dyn vfs::loader::Handle>, Receiver<vfs::loader::Message>>, 63 pub(crate) loader: Handle<Box<dyn vfs::loader::Handle>, Receiver<vfs::loader::Message>>,
62 pub(crate) flycheck: Option<Handle<FlycheckHandle, Receiver<flycheck::Message>>>, 64 pub(crate) flycheck: Option<Handle<FlycheckHandle, Receiver<flycheck::Message>>>,
@@ -66,7 +68,6 @@ pub(crate) struct GlobalState {
66 pub(crate) mem_docs: FxHashSet<VfsPath>, 68 pub(crate) mem_docs: FxHashSet<VfsPath>,
67 pub(crate) vfs: Arc<RwLock<(vfs::Vfs, FxHashMap<FileId, LineEndings>)>>, 69 pub(crate) vfs: Arc<RwLock<(vfs::Vfs, FxHashMap<FileId, LineEndings>)>>,
68 pub(crate) status: Status, 70 pub(crate) status: Status,
69 pub(crate) req_queue: ReqQueue,
70 pub(crate) source_root_config: SourceRootConfig, 71 pub(crate) source_root_config: SourceRootConfig,
71 pub(crate) proc_macro_client: ProcMacroClient, 72 pub(crate) proc_macro_client: ProcMacroClient,
72 pub(crate) workspaces: Arc<Vec<ProjectWorkspace>>, 73 pub(crate) workspaces: Arc<Vec<ProjectWorkspace>>,
@@ -102,16 +103,16 @@ impl GlobalState {
102 let analysis_host = AnalysisHost::new(config.lru_capacity); 103 let analysis_host = AnalysisHost::new(config.lru_capacity);
103 GlobalState { 104 GlobalState {
104 sender, 105 sender,
106 req_queue: ReqQueue::default(),
105 task_pool, 107 task_pool,
106 loader, 108 loader,
109 flycheck: None,
107 config, 110 config,
108 analysis_host, 111 analysis_host,
109 flycheck: None,
110 diagnostics: Default::default(), 112 diagnostics: Default::default(),
111 mem_docs: FxHashSet::default(), 113 mem_docs: FxHashSet::default(),
112 vfs: Arc::new(RwLock::new((vfs::Vfs::default(), FxHashMap::default()))), 114 vfs: Arc::new(RwLock::new((vfs::Vfs::default(), FxHashMap::default()))),
113 status: Status::default(), 115 status: Status::default(),
114 req_queue: ReqQueue::default(),
115 source_root_config: SourceRootConfig::default(), 116 source_root_config: SourceRootConfig::default(),
116 proc_macro_client: ProcMacroClient::dummy(), 117 proc_macro_client: ProcMacroClient::dummy(),
117 workspaces: Arc::new(Vec::new()), 118 workspaces: Arc::new(Vec::new()),
@@ -168,8 +169,39 @@ impl GlobalState {
168 } 169 }
169 } 170 }
170 171
171 pub(crate) fn send(&mut self, message: lsp_server::Message) { 172 pub(crate) fn send_request<R: lsp_types::request::Request>(
172 self.sender.send(message).unwrap() 173 &mut self,
174 params: R::Params,
175 handler: ReqHandler,
176 ) {
177 let request = self.req_queue.outgoing.register(
178 lsp_types::request::WorkDoneProgressCreate::METHOD.to_string(),
179 params,
180 handler,
181 );
182 self.send(request.into());
183 }
184 pub(crate) fn complete_request(&mut self, response: lsp_server::Response) {
185 let handler = self.req_queue.outgoing.complete(response.id.clone());
186 handler(self, response)
187 }
188
189 pub(crate) fn send_notification<N: lsp_types::notification::Notification>(
190 &mut self,
191 params: N::Params,
192 ) {
193 let not = notification_new::<N>(params);
194 self.send(not.into());
195 }
196
197 pub(crate) fn register_request(
198 &mut self,
199 request: &lsp_server::Request,
200 request_received: Instant,
201 ) {
202 self.req_queue
203 .incoming
204 .register(request.id.clone(), (request.method.clone(), request_received));
173 } 205 }
174 pub(crate) fn respond(&mut self, response: lsp_server::Response) { 206 pub(crate) fn respond(&mut self, response: lsp_server::Response) {
175 if let Some((method, start)) = self.req_queue.incoming.complete(response.id.clone()) { 207 if let Some((method, start)) = self.req_queue.incoming.complete(response.id.clone()) {
@@ -181,6 +213,15 @@ impl GlobalState {
181 self.send(response.into()); 213 self.send(response.into());
182 } 214 }
183 } 215 }
216 pub(crate) fn cancel(&mut self, request_id: lsp_server::RequestId) {
217 if let Some(response) = self.req_queue.incoming.cancel(request_id) {
218 self.send(response.into());
219 }
220 }
221
222 fn send(&mut self, message: lsp_server::Message) {
223 self.sender.send(message).unwrap()
224 }
184} 225}
185 226
186impl Drop for GlobalState { 227impl Drop for GlobalState {
diff --git a/crates/rust-analyzer/src/lsp_utils.rs b/crates/rust-analyzer/src/lsp_utils.rs
index fd793a17c..99f4998a9 100644
--- a/crates/rust-analyzer/src/lsp_utils.rs
+++ b/crates/rust-analyzer/src/lsp_utils.rs
@@ -2,7 +2,6 @@
2use std::{error::Error, ops::Range}; 2use std::{error::Error, ops::Range};
3 3
4use lsp_server::Notification; 4use lsp_server::Notification;
5use lsp_types::request::Request;
6use ra_db::Canceled; 5use ra_db::Canceled;
7use ra_ide::LineIndex; 6use ra_ide::LineIndex;
8use serde::Serialize; 7use serde::Serialize;
@@ -43,9 +42,9 @@ impl Progress {
43impl GlobalState { 42impl GlobalState {
44 pub(crate) fn show_message(&mut self, typ: lsp_types::MessageType, message: String) { 43 pub(crate) fn show_message(&mut self, typ: lsp_types::MessageType, message: String) {
45 let message = message.into(); 44 let message = message.into();
46 let params = lsp_types::ShowMessageParams { typ, message }; 45 self.send_notification::<lsp_types::notification::ShowMessage>(
47 let not = notification_new::<lsp_types::notification::ShowMessage>(params); 46 lsp_types::ShowMessageParams { typ, message },
48 self.send(not.into()); 47 )
49 } 48 }
50 49
51 pub(crate) fn report_progress( 50 pub(crate) fn report_progress(
@@ -61,12 +60,10 @@ impl GlobalState {
61 let token = lsp_types::ProgressToken::String(format!("rustAnalyzer/{}", title)); 60 let token = lsp_types::ProgressToken::String(format!("rustAnalyzer/{}", title));
62 let work_done_progress = match state { 61 let work_done_progress = match state {
63 Progress::Begin => { 62 Progress::Begin => {
64 let work_done_progress_create = self.req_queue.outgoing.register( 63 self.send_request::<lsp_types::request::WorkDoneProgressCreate>(
65 lsp_types::request::WorkDoneProgressCreate::METHOD.to_string(),
66 lsp_types::WorkDoneProgressCreateParams { token: token.clone() }, 64 lsp_types::WorkDoneProgressCreateParams { token: token.clone() },
67 |_, _| (), 65 |_, _| (),
68 ); 66 );
69 self.send(work_done_progress_create.into());
70 67
71 lsp_types::WorkDoneProgress::Begin(lsp_types::WorkDoneProgressBegin { 68 lsp_types::WorkDoneProgress::Begin(lsp_types::WorkDoneProgressBegin {
72 title: title.into(), 69 title: title.into(),
@@ -86,12 +83,10 @@ impl GlobalState {
86 lsp_types::WorkDoneProgress::End(lsp_types::WorkDoneProgressEnd { message }) 83 lsp_types::WorkDoneProgress::End(lsp_types::WorkDoneProgressEnd { message })
87 } 84 }
88 }; 85 };
89 let notification = 86 self.send_notification::<lsp_types::notification::Progress>(lsp_types::ProgressParams {
90 notification_new::<lsp_types::notification::Progress>(lsp_types::ProgressParams { 87 token,
91 token, 88 value: lsp_types::ProgressParamsValue::WorkDone(work_done_progress),
92 value: lsp_types::ProgressParamsValue::WorkDone(work_done_progress), 89 });
93 });
94 self.send(notification.into());
95 } 90 }
96} 91}
97 92
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs
index ae3c7e30e..e5194fe41 100644
--- a/crates/rust-analyzer/src/main_loop.rs
+++ b/crates/rust-analyzer/src/main_loop.rs
@@ -7,7 +7,7 @@ use std::{
7 7
8use crossbeam_channel::{never, select, Receiver}; 8use crossbeam_channel::{never, select, Receiver};
9use lsp_server::{Connection, Notification, Request, Response}; 9use lsp_server::{Connection, Notification, Request, Response};
10use lsp_types::{notification::Notification as _, request::Request as _}; 10use lsp_types::notification::Notification as _;
11use ra_db::VfsPath; 11use ra_db::VfsPath;
12use ra_ide::{Canceled, FileId}; 12use ra_ide::{Canceled, FileId};
13use ra_prof::profile; 13use ra_prof::profile;
@@ -18,7 +18,7 @@ use crate::{
18 from_proto, 18 from_proto,
19 global_state::{file_id_to_url, url_to_file_id, GlobalState, Status}, 19 global_state::{file_id_to_url, url_to_file_id, GlobalState, Status},
20 handlers, lsp_ext, 20 handlers, lsp_ext,
21 lsp_utils::{apply_document_changes, is_canceled, notification_is, notification_new, Progress}, 21 lsp_utils::{apply_document_changes, is_canceled, notification_is, Progress},
22 Result, 22 Result,
23}; 23};
24 24
@@ -143,10 +143,7 @@ impl GlobalState {
143 lsp_server::Message::Notification(not) => { 143 lsp_server::Message::Notification(not) => {
144 self.on_notification(not)?; 144 self.on_notification(not)?;
145 } 145 }
146 lsp_server::Message::Response(resp) => { 146 lsp_server::Message::Response(resp) => self.complete_request(resp),
147 let handler = self.req_queue.outgoing.complete(resp.id.clone());
148 handler(self, resp)
149 }
150 }, 147 },
151 Event::Task(task) => { 148 Event::Task(task) => {
152 match task { 149 match task {
@@ -250,10 +247,9 @@ impl GlobalState {
250 for file_id in diagnostic_changes { 247 for file_id in diagnostic_changes {
251 let url = file_id_to_url(&self.vfs.read().0, file_id); 248 let url = file_id_to_url(&self.vfs.read().0, file_id);
252 let diagnostics = self.diagnostics.diagnostics_for(file_id).cloned().collect(); 249 let diagnostics = self.diagnostics.diagnostics_for(file_id).cloned().collect();
253 let params = 250 self.send_notification::<lsp_types::notification::PublishDiagnostics>(
254 lsp_types::PublishDiagnosticsParams { uri: url, diagnostics, version: None }; 251 lsp_types::PublishDiagnosticsParams { uri: url, diagnostics, version: None },
255 let not = notification_new::<lsp_types::notification::PublishDiagnostics>(params); 252 );
256 self.send(not.into());
257 } 253 }
258 } 254 }
259 255
@@ -271,7 +267,7 @@ impl GlobalState {
271 } 267 }
272 268
273 fn on_request(&mut self, request_received: Instant, req: Request) -> Result<()> { 269 fn on_request(&mut self, request_received: Instant, req: Request) -> Result<()> {
274 self.req_queue.incoming.register(req.id.clone(), (req.method.clone(), request_received)); 270 self.register_request(&req, request_received);
275 271
276 RequestDispatcher { req: Some(req), global_state: self } 272 RequestDispatcher { req: Some(req), global_state: self }
277 .on_sync::<lsp_ext::CollectGarbage>(|s, ()| Ok(s.analysis_host.collect_garbage()))? 273 .on_sync::<lsp_ext::CollectGarbage>(|s, ()| Ok(s.analysis_host.collect_garbage()))?
@@ -335,9 +331,7 @@ impl GlobalState {
335 lsp_types::NumberOrString::Number(id) => id.into(), 331 lsp_types::NumberOrString::Number(id) => id.into(),
336 lsp_types::NumberOrString::String(id) => id.into(), 332 lsp_types::NumberOrString::String(id) => id.into(),
337 }; 333 };
338 if let Some(response) = this.req_queue.incoming.cancel(id) { 334 this.cancel(id);
339 this.send(response.into());
340 }
341 Ok(()) 335 Ok(())
342 })? 336 })?
343 .on::<lsp_types::notification::DidOpenTextDocument>(|this, params| { 337 .on::<lsp_types::notification::DidOpenTextDocument>(|this, params| {
@@ -372,13 +366,13 @@ impl GlobalState {
372 this.loader.handle.invalidate(path.to_path_buf()); 366 this.loader.handle.invalidate(path.to_path_buf());
373 } 367 }
374 } 368 }
375 let params = lsp_types::PublishDiagnosticsParams { 369 this.send_notification::<lsp_types::notification::PublishDiagnostics>(
376 uri: params.text_document.uri, 370 lsp_types::PublishDiagnosticsParams {
377 diagnostics: Vec::new(), 371 uri: params.text_document.uri,
378 version: None, 372 diagnostics: Vec::new(),
379 }; 373 version: None,
380 let not = notification_new::<lsp_types::notification::PublishDiagnostics>(params); 374 },
381 this.send(not.into()); 375 );
382 Ok(()) 376 Ok(())
383 })? 377 })?
384 .on::<lsp_types::notification::DidSaveTextDocument>(|this, _params| { 378 .on::<lsp_types::notification::DidSaveTextDocument>(|this, _params| {
@@ -390,8 +384,7 @@ impl GlobalState {
390 .on::<lsp_types::notification::DidChangeConfiguration>(|this, _params| { 384 .on::<lsp_types::notification::DidChangeConfiguration>(|this, _params| {
391 // As stated in https://github.com/microsoft/language-server-protocol/issues/676, 385 // As stated in https://github.com/microsoft/language-server-protocol/issues/676,
392 // this notification's parameters should be ignored and the actual config queried separately. 386 // this notification's parameters should be ignored and the actual config queried separately.
393 let request = this.req_queue.outgoing.register( 387 this.send_request::<lsp_types::request::WorkspaceConfiguration>(
394 lsp_types::request::WorkspaceConfiguration::METHOD.to_string(),
395 lsp_types::ConfigurationParams { 388 lsp_types::ConfigurationParams {
396 items: vec![lsp_types::ConfigurationItem { 389 items: vec![lsp_types::ConfigurationItem {
397 scope_uri: None, 390 scope_uri: None,
@@ -419,7 +412,6 @@ impl GlobalState {
419 } 412 }
420 }, 413 },
421 ); 414 );
422 this.send(request.into());
423 415
424 return Ok(()); 416 return Ok(());
425 })? 417 })?
diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs
index fece6176e..a1850b286 100644
--- a/crates/rust-analyzer/src/reload.rs
+++ b/crates/rust-analyzer/src/reload.rs
@@ -3,7 +3,6 @@ use std::sync::Arc;
3 3
4use crossbeam_channel::unbounded; 4use crossbeam_channel::unbounded;
5use flycheck::FlycheckHandle; 5use flycheck::FlycheckHandle;
6use lsp_types::request::Request;
7use ra_db::{CrateGraph, SourceRoot, VfsPath}; 6use ra_db::{CrateGraph, SourceRoot, VfsPath};
8use ra_ide::AnalysisChange; 7use ra_ide::AnalysisChange;
9use ra_project_model::{PackageRoot, ProcMacroClient, ProjectWorkspace}; 8use ra_project_model::{PackageRoot, ProcMacroClient, ProjectWorkspace};
@@ -78,13 +77,10 @@ impl GlobalState {
78 method: "workspace/didChangeWatchedFiles".to_string(), 77 method: "workspace/didChangeWatchedFiles".to_string(),
79 register_options: Some(serde_json::to_value(registration_options).unwrap()), 78 register_options: Some(serde_json::to_value(registration_options).unwrap()),
80 }; 79 };
81 let params = lsp_types::RegistrationParams { registrations: vec![registration] }; 80 self.send_request::<lsp_types::request::RegisterCapability>(
82 let request = self.req_queue.outgoing.register( 81 lsp_types::RegistrationParams { registrations: vec![registration] },
83 lsp_types::request::RegisterCapability::METHOD.to_string(),
84 params,
85 |_, _| (), 82 |_, _| (),
86 ); 83 );
87 self.send(request.into());
88 } 84 }
89 85
90 let mut change = AnalysisChange::new(); 86 let mut change = AnalysisChange::new();