diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2020-06-26 16:08:58 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2020-06-26 16:08:58 +0100 |
commit | d86a2426a21b8e0dddaeffcdd9e153cd909a65f8 (patch) | |
tree | 4f89a2f03e332b70cfbe2cc2527aa4b42879f93c | |
parent | fa70882418088271e519c5820ae5cb17557a1f43 (diff) | |
parent | 9d15e8fc4f875f6da2cd2bd89c62bb96fa64ef1b (diff) |
Merge #5077
5077: Type safer requests r=matklad a=matklad
bors r+
🤖
Co-authored-by: Aleksey Kladov <[email protected]>
-rw-r--r-- | crates/rust-analyzer/src/global_state.rs | 53 | ||||
-rw-r--r-- | crates/rust-analyzer/src/lsp_utils.rs | 21 | ||||
-rw-r--r-- | crates/rust-analyzer/src/main_loop.rs | 40 | ||||
-rw-r--r-- | crates/rust-analyzer/src/reload.rs | 8 |
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 384e1f0d2..d1a161c1a 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 | ||
8 | use crossbeam_channel::{unbounded, Receiver, Sender}; | 8 | use crossbeam_channel::{unbounded, Receiver, Sender}; |
9 | use flycheck::FlycheckHandle; | 9 | use flycheck::FlycheckHandle; |
10 | use lsp_types::Url; | 10 | use lsp_types::{request::Request as _, Url}; |
11 | use parking_lot::RwLock; | 11 | use parking_lot::RwLock; |
12 | use ra_db::{CrateId, VfsPath}; | 12 | use ra_db::{CrateId, VfsPath}; |
13 | use ra_ide::{Analysis, AnalysisChange, AnalysisHost, FileId}; | 13 | use 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! |
58 | pub(crate) struct GlobalState { | 59 | pub(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 | ||
186 | impl Drop for GlobalState { | 227 | impl 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 @@ | |||
2 | use std::{error::Error, ops::Range}; | 2 | use std::{error::Error, ops::Range}; |
3 | 3 | ||
4 | use lsp_server::Notification; | 4 | use lsp_server::Notification; |
5 | use lsp_types::request::Request; | ||
6 | use ra_db::Canceled; | 5 | use ra_db::Canceled; |
7 | use ra_ide::LineIndex; | 6 | use ra_ide::LineIndex; |
8 | use serde::Serialize; | 7 | use serde::Serialize; |
@@ -43,9 +42,9 @@ impl Progress { | |||
43 | impl GlobalState { | 42 | impl 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 | ||
8 | use crossbeam_channel::{never, select, Receiver}; | 8 | use crossbeam_channel::{never, select, Receiver}; |
9 | use lsp_server::{Connection, Notification, Request, Response}; | 9 | use lsp_server::{Connection, Notification, Request, Response}; |
10 | use lsp_types::{notification::Notification as _, request::Request as _}; | 10 | use lsp_types::notification::Notification as _; |
11 | use ra_db::VfsPath; | 11 | use ra_db::VfsPath; |
12 | use ra_ide::{Canceled, FileId}; | 12 | use ra_ide::{Canceled, FileId}; |
13 | use ra_prof::profile; | 13 | use 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 | ||
4 | use crossbeam_channel::unbounded; | 4 | use crossbeam_channel::unbounded; |
5 | use flycheck::FlycheckHandle; | 5 | use flycheck::FlycheckHandle; |
6 | use lsp_types::request::Request; | ||
7 | use ra_db::{CrateGraph, SourceRoot, VfsPath}; | 6 | use ra_db::{CrateGraph, SourceRoot, VfsPath}; |
8 | use ra_ide::AnalysisChange; | 7 | use ra_ide::AnalysisChange; |
9 | use ra_project_model::{PackageRoot, ProcMacroClient, ProjectWorkspace}; | 8 | use 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(); |