diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/rust-analyzer/src/cargo_target_spec.rs | 2 | ||||
-rw-r--r-- | crates/rust-analyzer/src/from_proto.rs | 4 | ||||
-rw-r--r-- | crates/rust-analyzer/src/global_state.rs | 55 | ||||
-rw-r--r-- | crates/rust-analyzer/src/handlers.rs | 142 | ||||
-rw-r--r-- | crates/rust-analyzer/src/lib.rs | 22 | ||||
-rw-r--r-- | crates/rust-analyzer/src/main_loop.rs | 151 | ||||
-rw-r--r-- | crates/rust-analyzer/src/to_proto.rs | 8 |
7 files changed, 177 insertions, 207 deletions
diff --git a/crates/rust-analyzer/src/cargo_target_spec.rs b/crates/rust-analyzer/src/cargo_target_spec.rs index e98d0f868..e4dd5d92d 100644 --- a/crates/rust-analyzer/src/cargo_target_spec.rs +++ b/crates/rust-analyzer/src/cargo_target_spec.rs | |||
@@ -94,7 +94,7 @@ impl CargoTargetSpec { | |||
94 | global_state_snapshot: &GlobalStateSnapshot, | 94 | global_state_snapshot: &GlobalStateSnapshot, |
95 | file_id: FileId, | 95 | file_id: FileId, |
96 | ) -> Result<Option<CargoTargetSpec>> { | 96 | ) -> Result<Option<CargoTargetSpec>> { |
97 | let crate_id = match global_state_snapshot.analysis().crate_for(file_id)?.first() { | 97 | let crate_id = match global_state_snapshot.analysis.crate_for(file_id)?.first() { |
98 | Some(crate_id) => *crate_id, | 98 | Some(crate_id) => *crate_id, |
99 | None => return Ok(None), | 99 | None => return Ok(None), |
100 | }; | 100 | }; |
diff --git a/crates/rust-analyzer/src/from_proto.rs b/crates/rust-analyzer/src/from_proto.rs index 40d440c67..15b281103 100644 --- a/crates/rust-analyzer/src/from_proto.rs +++ b/crates/rust-analyzer/src/from_proto.rs | |||
@@ -37,7 +37,7 @@ pub(crate) fn file_position( | |||
37 | tdpp: lsp_types::TextDocumentPositionParams, | 37 | tdpp: lsp_types::TextDocumentPositionParams, |
38 | ) -> Result<FilePosition> { | 38 | ) -> Result<FilePosition> { |
39 | let file_id = file_id(world, &tdpp.text_document.uri)?; | 39 | let file_id = file_id(world, &tdpp.text_document.uri)?; |
40 | let line_index = world.analysis().file_line_index(file_id)?; | 40 | let line_index = world.analysis.file_line_index(file_id)?; |
41 | let offset = offset(&*line_index, tdpp.position); | 41 | let offset = offset(&*line_index, tdpp.position); |
42 | Ok(FilePosition { file_id, offset }) | 42 | Ok(FilePosition { file_id, offset }) |
43 | } | 43 | } |
@@ -48,7 +48,7 @@ pub(crate) fn file_range( | |||
48 | range: lsp_types::Range, | 48 | range: lsp_types::Range, |
49 | ) -> Result<FileRange> { | 49 | ) -> Result<FileRange> { |
50 | let file_id = file_id(world, &text_document_identifier.uri)?; | 50 | let file_id = file_id(world, &text_document_identifier.uri)?; |
51 | let line_index = world.analysis().file_line_index(file_id)?; | 51 | let line_index = world.analysis.file_line_index(file_id)?; |
52 | let range = text_range(&line_index, range); | 52 | let range = text_range(&line_index, range); |
53 | Ok(FileRange { file_id, range }) | 53 | Ok(FileRange { file_id, range }) |
54 | } | 54 | } |
diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs index 9a75cb2ab..87f3fe4db 100644 --- a/crates/rust-analyzer/src/global_state.rs +++ b/crates/rust-analyzer/src/global_state.rs | |||
@@ -20,11 +20,12 @@ use crate::{ | |||
20 | diagnostics::{CheckFixes, DiagnosticCollection}, | 20 | diagnostics::{CheckFixes, DiagnosticCollection}, |
21 | from_proto, | 21 | from_proto, |
22 | line_endings::LineEndings, | 22 | line_endings::LineEndings, |
23 | main_loop::ReqQueue, | ||
23 | request_metrics::{LatestRequests, RequestMetrics}, | 24 | request_metrics::{LatestRequests, RequestMetrics}, |
24 | to_proto::url_from_abs_path, | 25 | to_proto::url_from_abs_path, |
25 | Result, | 26 | Result, |
26 | }; | 27 | }; |
27 | use rustc_hash::FxHashMap; | 28 | use rustc_hash::{FxHashMap, FxHashSet}; |
28 | 29 | ||
29 | fn create_flycheck(workspaces: &[ProjectWorkspace], config: &FlycheckConfig) -> Option<Flycheck> { | 30 | fn create_flycheck(workspaces: &[ProjectWorkspace], config: &FlycheckConfig) -> Option<Flycheck> { |
30 | // FIXME: Figure out the multi-workspace situation | 31 | // FIXME: Figure out the multi-workspace situation |
@@ -40,34 +41,48 @@ fn create_flycheck(workspaces: &[ProjectWorkspace], config: &FlycheckConfig) -> | |||
40 | }) | 41 | }) |
41 | } | 42 | } |
42 | 43 | ||
44 | #[derive(Eq, PartialEq)] | ||
45 | pub(crate) enum Status { | ||
46 | Loading, | ||
47 | Ready, | ||
48 | } | ||
49 | |||
50 | impl Default for Status { | ||
51 | fn default() -> Self { | ||
52 | Status::Loading | ||
53 | } | ||
54 | } | ||
55 | |||
43 | /// `GlobalState` is the primary mutable state of the language server | 56 | /// `GlobalState` is the primary mutable state of the language server |
44 | /// | 57 | /// |
45 | /// The most interesting components are `vfs`, which stores a consistent | 58 | /// The most interesting components are `vfs`, which stores a consistent |
46 | /// snapshot of the file systems, and `analysis_host`, which stores our | 59 | /// snapshot of the file systems, and `analysis_host`, which stores our |
47 | /// incremental salsa database. | 60 | /// incremental salsa database. |
48 | #[derive(Debug)] | ||
49 | pub(crate) struct GlobalState { | 61 | pub(crate) struct GlobalState { |
50 | pub(crate) config: Config, | 62 | pub(crate) config: Config, |
51 | pub(crate) workspaces: Arc<Vec<ProjectWorkspace>>, | ||
52 | pub(crate) analysis_host: AnalysisHost, | 63 | pub(crate) analysis_host: AnalysisHost, |
53 | pub(crate) loader: Box<dyn vfs::loader::Handle>, | 64 | pub(crate) loader: Box<dyn vfs::loader::Handle>, |
54 | pub(crate) task_receiver: Receiver<vfs::loader::Message>, | 65 | pub(crate) task_receiver: Receiver<vfs::loader::Message>, |
55 | pub(crate) flycheck: Option<Flycheck>, | 66 | pub(crate) flycheck: Option<Flycheck>, |
56 | pub(crate) diagnostics: DiagnosticCollection, | 67 | pub(crate) diagnostics: DiagnosticCollection, |
57 | pub(crate) proc_macro_client: ProcMacroClient, | 68 | pub(crate) mem_docs: FxHashSet<VfsPath>, |
58 | pub(crate) vfs: Arc<RwLock<(vfs::Vfs, FxHashMap<FileId, LineEndings>)>>, | 69 | pub(crate) vfs: Arc<RwLock<(vfs::Vfs, FxHashMap<FileId, LineEndings>)>>, |
59 | pub(crate) latest_requests: Arc<RwLock<LatestRequests>>, | 70 | pub(crate) status: Status, |
71 | pub(crate) req_queue: ReqQueue, | ||
72 | latest_requests: Arc<RwLock<LatestRequests>>, | ||
60 | source_root_config: SourceRootConfig, | 73 | source_root_config: SourceRootConfig, |
74 | _proc_macro_client: ProcMacroClient, | ||
75 | workspaces: Arc<Vec<ProjectWorkspace>>, | ||
61 | } | 76 | } |
62 | 77 | ||
63 | /// An immutable snapshot of the world's state at a point in time. | 78 | /// An immutable snapshot of the world's state at a point in time. |
64 | pub(crate) struct GlobalStateSnapshot { | 79 | pub(crate) struct GlobalStateSnapshot { |
65 | pub(crate) config: Config, | 80 | pub(crate) config: Config, |
66 | pub(crate) workspaces: Arc<Vec<ProjectWorkspace>>, | ||
67 | pub(crate) analysis: Analysis, | 81 | pub(crate) analysis: Analysis, |
68 | pub(crate) check_fixes: CheckFixes, | 82 | pub(crate) check_fixes: CheckFixes, |
69 | pub(crate) latest_requests: Arc<RwLock<LatestRequests>>, | 83 | pub(crate) latest_requests: Arc<RwLock<LatestRequests>>, |
70 | vfs: Arc<RwLock<(vfs::Vfs, FxHashMap<FileId, LineEndings>)>>, | 84 | vfs: Arc<RwLock<(vfs::Vfs, FxHashMap<FileId, LineEndings>)>>, |
85 | workspaces: Arc<Vec<ProjectWorkspace>>, | ||
71 | } | 86 | } |
72 | 87 | ||
73 | impl GlobalState { | 88 | impl GlobalState { |
@@ -75,6 +90,7 @@ impl GlobalState { | |||
75 | workspaces: Vec<ProjectWorkspace>, | 90 | workspaces: Vec<ProjectWorkspace>, |
76 | lru_capacity: Option<usize>, | 91 | lru_capacity: Option<usize>, |
77 | config: Config, | 92 | config: Config, |
93 | req_queue: ReqQueue, | ||
78 | ) -> GlobalState { | 94 | ) -> GlobalState { |
79 | let mut change = AnalysisChange::new(); | 95 | let mut change = AnalysisChange::new(); |
80 | 96 | ||
@@ -133,22 +149,25 @@ impl GlobalState { | |||
133 | analysis_host.apply_change(change); | 149 | analysis_host.apply_change(change); |
134 | let mut res = GlobalState { | 150 | let mut res = GlobalState { |
135 | config, | 151 | config, |
136 | workspaces: Arc::new(workspaces), | ||
137 | analysis_host, | 152 | analysis_host, |
138 | loader, | 153 | loader, |
139 | vfs: Arc::new(RwLock::new((vfs, FxHashMap::default()))), | ||
140 | task_receiver, | 154 | task_receiver, |
141 | latest_requests: Default::default(), | ||
142 | flycheck, | 155 | flycheck, |
143 | diagnostics: Default::default(), | 156 | diagnostics: Default::default(), |
144 | proc_macro_client, | 157 | mem_docs: FxHashSet::default(), |
158 | vfs: Arc::new(RwLock::new((vfs, FxHashMap::default()))), | ||
159 | status: Status::default(), | ||
160 | req_queue, | ||
161 | latest_requests: Default::default(), | ||
145 | source_root_config: project_folders.source_root_config, | 162 | source_root_config: project_folders.source_root_config, |
163 | _proc_macro_client: proc_macro_client, | ||
164 | workspaces: Arc::new(workspaces), | ||
146 | }; | 165 | }; |
147 | res.process_changes(); | 166 | res.process_changes(); |
148 | res | 167 | res |
149 | } | 168 | } |
150 | 169 | ||
151 | pub fn update_configuration(&mut self, config: Config) { | 170 | pub(crate) fn update_configuration(&mut self, config: Config) { |
152 | self.analysis_host.update_lru_capacity(config.lru_capacity); | 171 | self.analysis_host.update_lru_capacity(config.lru_capacity); |
153 | if config.check != self.config.check { | 172 | if config.check != self.config.check { |
154 | self.flycheck = | 173 | self.flycheck = |
@@ -158,7 +177,7 @@ impl GlobalState { | |||
158 | self.config = config; | 177 | self.config = config; |
159 | } | 178 | } |
160 | 179 | ||
161 | pub fn process_changes(&mut self) -> bool { | 180 | pub(crate) fn process_changes(&mut self) -> bool { |
162 | let change = { | 181 | let change = { |
163 | let mut change = AnalysisChange::new(); | 182 | let mut change = AnalysisChange::new(); |
164 | let (vfs, line_endings_map) = &mut *self.vfs.write(); | 183 | let (vfs, line_endings_map) = &mut *self.vfs.write(); |
@@ -196,7 +215,7 @@ impl GlobalState { | |||
196 | true | 215 | true |
197 | } | 216 | } |
198 | 217 | ||
199 | pub fn snapshot(&self) -> GlobalStateSnapshot { | 218 | pub(crate) fn snapshot(&self) -> GlobalStateSnapshot { |
200 | GlobalStateSnapshot { | 219 | GlobalStateSnapshot { |
201 | config: self.config.clone(), | 220 | config: self.config.clone(), |
202 | workspaces: Arc::clone(&self.workspaces), | 221 | workspaces: Arc::clone(&self.workspaces), |
@@ -207,11 +226,11 @@ impl GlobalState { | |||
207 | } | 226 | } |
208 | } | 227 | } |
209 | 228 | ||
210 | pub fn maybe_collect_garbage(&mut self) { | 229 | pub(crate) fn maybe_collect_garbage(&mut self) { |
211 | self.analysis_host.maybe_collect_garbage() | 230 | self.analysis_host.maybe_collect_garbage() |
212 | } | 231 | } |
213 | 232 | ||
214 | pub fn collect_garbage(&mut self) { | 233 | pub(crate) fn collect_garbage(&mut self) { |
215 | self.analysis_host.collect_garbage() | 234 | self.analysis_host.collect_garbage() |
216 | } | 235 | } |
217 | 236 | ||
@@ -221,10 +240,6 @@ impl GlobalState { | |||
221 | } | 240 | } |
222 | 241 | ||
223 | impl GlobalStateSnapshot { | 242 | impl GlobalStateSnapshot { |
224 | pub(crate) fn analysis(&self) -> &Analysis { | ||
225 | &self.analysis | ||
226 | } | ||
227 | |||
228 | pub(crate) fn url_to_file_id(&self, url: &Url) -> Result<FileId> { | 243 | pub(crate) fn url_to_file_id(&self, url: &Url) -> Result<FileId> { |
229 | let path = from_proto::abs_path(url)?; | 244 | let path = from_proto::abs_path(url)?; |
230 | let path = path.into(); | 245 | let path = path.into(); |
@@ -253,7 +268,7 @@ impl GlobalStateSnapshot { | |||
253 | &self, | 268 | &self, |
254 | crate_id: CrateId, | 269 | crate_id: CrateId, |
255 | ) -> Option<(&CargoWorkspace, Target)> { | 270 | ) -> Option<(&CargoWorkspace, Target)> { |
256 | let file_id = self.analysis().crate_root(crate_id).ok()?; | 271 | let file_id = self.analysis.crate_root(crate_id).ok()?; |
257 | let path = self.vfs.read().0.file_path(file_id); | 272 | let path = self.vfs.read().0.file_path(file_id); |
258 | let path = path.as_path()?; | 273 | let path = path.as_path()?; |
259 | self.workspaces.iter().find_map(|ws| match ws { | 274 | self.workspaces.iter().find_map(|ws| match ws { |
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs index b38755b79..b2ff9a157 100644 --- a/crates/rust-analyzer/src/handlers.rs +++ b/crates/rust-analyzer/src/handlers.rs | |||
@@ -56,9 +56,9 @@ pub(crate) fn handle_syntax_tree( | |||
56 | ) -> Result<String> { | 56 | ) -> Result<String> { |
57 | let _p = profile("handle_syntax_tree"); | 57 | let _p = profile("handle_syntax_tree"); |
58 | let id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; | 58 | let id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; |
59 | let line_index = snap.analysis().file_line_index(id)?; | 59 | let line_index = snap.analysis.file_line_index(id)?; |
60 | let text_range = params.range.map(|r| from_proto::text_range(&line_index, r)); | 60 | let text_range = params.range.map(|r| from_proto::text_range(&line_index, r)); |
61 | let res = snap.analysis().syntax_tree(id, text_range)?; | 61 | let res = snap.analysis.syntax_tree(id, text_range)?; |
62 | Ok(res) | 62 | Ok(res) |
63 | } | 63 | } |
64 | 64 | ||
@@ -68,10 +68,10 @@ pub(crate) fn handle_expand_macro( | |||
68 | ) -> Result<Option<lsp_ext::ExpandedMacro>> { | 68 | ) -> Result<Option<lsp_ext::ExpandedMacro>> { |
69 | let _p = profile("handle_expand_macro"); | 69 | let _p = profile("handle_expand_macro"); |
70 | let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; | 70 | let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; |
71 | let line_index = snap.analysis().file_line_index(file_id)?; | 71 | let line_index = snap.analysis.file_line_index(file_id)?; |
72 | let offset = from_proto::offset(&line_index, params.position); | 72 | let offset = from_proto::offset(&line_index, params.position); |
73 | 73 | ||
74 | let res = snap.analysis().expand_macro(FilePosition { file_id, offset })?; | 74 | let res = snap.analysis.expand_macro(FilePosition { file_id, offset })?; |
75 | Ok(res.map(|it| lsp_ext::ExpandedMacro { name: it.name, expansion: it.expansion })) | 75 | Ok(res.map(|it| lsp_ext::ExpandedMacro { name: it.name, expansion: it.expansion })) |
76 | } | 76 | } |
77 | 77 | ||
@@ -81,7 +81,7 @@ pub(crate) fn handle_selection_range( | |||
81 | ) -> Result<Option<Vec<lsp_types::SelectionRange>>> { | 81 | ) -> Result<Option<Vec<lsp_types::SelectionRange>>> { |
82 | let _p = profile("handle_selection_range"); | 82 | let _p = profile("handle_selection_range"); |
83 | let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; | 83 | let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; |
84 | let line_index = snap.analysis().file_line_index(file_id)?; | 84 | let line_index = snap.analysis.file_line_index(file_id)?; |
85 | let res: Result<Vec<lsp_types::SelectionRange>> = params | 85 | let res: Result<Vec<lsp_types::SelectionRange>> = params |
86 | .positions | 86 | .positions |
87 | .into_iter() | 87 | .into_iter() |
@@ -93,7 +93,7 @@ pub(crate) fn handle_selection_range( | |||
93 | loop { | 93 | loop { |
94 | ranges.push(range); | 94 | ranges.push(range); |
95 | let frange = FileRange { file_id, range }; | 95 | let frange = FileRange { file_id, range }; |
96 | let next = snap.analysis().extend_selection(frange)?; | 96 | let next = snap.analysis.extend_selection(frange)?; |
97 | if next == range { | 97 | if next == range { |
98 | break; | 98 | break; |
99 | } else { | 99 | } else { |
@@ -124,13 +124,13 @@ pub(crate) fn handle_matching_brace( | |||
124 | ) -> Result<Vec<Position>> { | 124 | ) -> Result<Vec<Position>> { |
125 | let _p = profile("handle_matching_brace"); | 125 | let _p = profile("handle_matching_brace"); |
126 | let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; | 126 | let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; |
127 | let line_index = snap.analysis().file_line_index(file_id)?; | 127 | let line_index = snap.analysis.file_line_index(file_id)?; |
128 | let res = params | 128 | let res = params |
129 | .positions | 129 | .positions |
130 | .into_iter() | 130 | .into_iter() |
131 | .map(|position| { | 131 | .map(|position| { |
132 | let offset = from_proto::offset(&line_index, position); | 132 | let offset = from_proto::offset(&line_index, position); |
133 | let offset = match snap.analysis().matching_brace(FilePosition { file_id, offset }) { | 133 | let offset = match snap.analysis.matching_brace(FilePosition { file_id, offset }) { |
134 | Ok(Some(matching_brace_offset)) => matching_brace_offset, | 134 | Ok(Some(matching_brace_offset)) => matching_brace_offset, |
135 | Err(_) | Ok(None) => offset, | 135 | Err(_) | Ok(None) => offset, |
136 | }; | 136 | }; |
@@ -146,12 +146,12 @@ pub(crate) fn handle_join_lines( | |||
146 | ) -> Result<Vec<lsp_types::TextEdit>> { | 146 | ) -> Result<Vec<lsp_types::TextEdit>> { |
147 | let _p = profile("handle_join_lines"); | 147 | let _p = profile("handle_join_lines"); |
148 | let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; | 148 | let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; |
149 | let line_index = snap.analysis().file_line_index(file_id)?; | 149 | let line_index = snap.analysis.file_line_index(file_id)?; |
150 | let line_endings = snap.file_line_endings(file_id); | 150 | let line_endings = snap.file_line_endings(file_id); |
151 | let mut res = TextEdit::default(); | 151 | let mut res = TextEdit::default(); |
152 | for range in params.ranges { | 152 | for range in params.ranges { |
153 | let range = from_proto::text_range(&line_index, range); | 153 | let range = from_proto::text_range(&line_index, range); |
154 | let edit = snap.analysis().join_lines(FileRange { file_id, range })?; | 154 | let edit = snap.analysis.join_lines(FileRange { file_id, range })?; |
155 | match res.union(edit) { | 155 | match res.union(edit) { |
156 | Ok(()) => (), | 156 | Ok(()) => (), |
157 | Err(_edit) => { | 157 | Err(_edit) => { |
@@ -169,11 +169,11 @@ pub(crate) fn handle_on_enter( | |||
169 | ) -> Result<Option<Vec<lsp_ext::SnippetTextEdit>>> { | 169 | ) -> Result<Option<Vec<lsp_ext::SnippetTextEdit>>> { |
170 | let _p = profile("handle_on_enter"); | 170 | let _p = profile("handle_on_enter"); |
171 | let position = from_proto::file_position(&snap, params)?; | 171 | let position = from_proto::file_position(&snap, params)?; |
172 | let edit = match snap.analysis().on_enter(position)? { | 172 | let edit = match snap.analysis.on_enter(position)? { |
173 | None => return Ok(None), | 173 | None => return Ok(None), |
174 | Some(it) => it, | 174 | Some(it) => it, |
175 | }; | 175 | }; |
176 | let line_index = snap.analysis().file_line_index(position.file_id)?; | 176 | let line_index = snap.analysis.file_line_index(position.file_id)?; |
177 | let line_endings = snap.file_line_endings(position.file_id); | 177 | let line_endings = snap.file_line_endings(position.file_id); |
178 | let edit = to_proto::snippet_text_edit_vec(&line_index, line_endings, true, edit); | 178 | let edit = to_proto::snippet_text_edit_vec(&line_index, line_endings, true, edit); |
179 | Ok(Some(edit)) | 179 | Ok(Some(edit)) |
@@ -186,7 +186,7 @@ pub(crate) fn handle_on_type_formatting( | |||
186 | ) -> Result<Option<Vec<lsp_types::TextEdit>>> { | 186 | ) -> Result<Option<Vec<lsp_types::TextEdit>>> { |
187 | let _p = profile("handle_on_type_formatting"); | 187 | let _p = profile("handle_on_type_formatting"); |
188 | let mut position = from_proto::file_position(&snap, params.text_document_position)?; | 188 | let mut position = from_proto::file_position(&snap, params.text_document_position)?; |
189 | let line_index = snap.analysis().file_line_index(position.file_id)?; | 189 | let line_index = snap.analysis.file_line_index(position.file_id)?; |
190 | let line_endings = snap.file_line_endings(position.file_id); | 190 | let line_endings = snap.file_line_endings(position.file_id); |
191 | 191 | ||
192 | // in `ra_ide`, the `on_type` invariant is that | 192 | // in `ra_ide`, the `on_type` invariant is that |
@@ -194,7 +194,7 @@ pub(crate) fn handle_on_type_formatting( | |||
194 | position.offset -= TextSize::of('.'); | 194 | position.offset -= TextSize::of('.'); |
195 | let char_typed = params.ch.chars().next().unwrap_or('\0'); | 195 | let char_typed = params.ch.chars().next().unwrap_or('\0'); |
196 | assert!({ | 196 | assert!({ |
197 | let text = snap.analysis().file_text(position.file_id)?; | 197 | let text = snap.analysis.file_text(position.file_id)?; |
198 | text[usize::from(position.offset)..].starts_with(char_typed) | 198 | text[usize::from(position.offset)..].starts_with(char_typed) |
199 | }); | 199 | }); |
200 | 200 | ||
@@ -206,7 +206,7 @@ pub(crate) fn handle_on_type_formatting( | |||
206 | return Ok(None); | 206 | return Ok(None); |
207 | } | 207 | } |
208 | 208 | ||
209 | let edit = snap.analysis().on_char_typed(position, char_typed)?; | 209 | let edit = snap.analysis.on_char_typed(position, char_typed)?; |
210 | let mut edit = match edit { | 210 | let mut edit = match edit { |
211 | Some(it) => it, | 211 | Some(it) => it, |
212 | None => return Ok(None), | 212 | None => return Ok(None), |
@@ -225,11 +225,11 @@ pub(crate) fn handle_document_symbol( | |||
225 | ) -> Result<Option<lsp_types::DocumentSymbolResponse>> { | 225 | ) -> Result<Option<lsp_types::DocumentSymbolResponse>> { |
226 | let _p = profile("handle_document_symbol"); | 226 | let _p = profile("handle_document_symbol"); |
227 | let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; | 227 | let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; |
228 | let line_index = snap.analysis().file_line_index(file_id)?; | 228 | let line_index = snap.analysis.file_line_index(file_id)?; |
229 | 229 | ||
230 | let mut parents: Vec<(DocumentSymbol, Option<usize>)> = Vec::new(); | 230 | let mut parents: Vec<(DocumentSymbol, Option<usize>)> = Vec::new(); |
231 | 231 | ||
232 | for symbol in snap.analysis().file_structure(file_id)? { | 232 | for symbol in snap.analysis.file_structure(file_id)? { |
233 | let doc_symbol = DocumentSymbol { | 233 | let doc_symbol = DocumentSymbol { |
234 | name: symbol.label, | 234 | name: symbol.label, |
235 | detail: symbol.detail, | 235 | detail: symbol.detail, |
@@ -317,7 +317,7 @@ pub(crate) fn handle_workspace_symbol( | |||
317 | 317 | ||
318 | fn exec_query(snap: &GlobalStateSnapshot, query: Query) -> Result<Vec<SymbolInformation>> { | 318 | fn exec_query(snap: &GlobalStateSnapshot, query: Query) -> Result<Vec<SymbolInformation>> { |
319 | let mut res = Vec::new(); | 319 | let mut res = Vec::new(); |
320 | for nav in snap.analysis().symbol_search(query)? { | 320 | for nav in snap.analysis.symbol_search(query)? { |
321 | let info = SymbolInformation { | 321 | let info = SymbolInformation { |
322 | name: nav.name().to_string(), | 322 | name: nav.name().to_string(), |
323 | kind: to_proto::symbol_kind(nav.kind()), | 323 | kind: to_proto::symbol_kind(nav.kind()), |
@@ -337,7 +337,7 @@ pub(crate) fn handle_goto_definition( | |||
337 | ) -> Result<Option<lsp_types::GotoDefinitionResponse>> { | 337 | ) -> Result<Option<lsp_types::GotoDefinitionResponse>> { |
338 | let _p = profile("handle_goto_definition"); | 338 | let _p = profile("handle_goto_definition"); |
339 | let position = from_proto::file_position(&snap, params.text_document_position_params)?; | 339 | let position = from_proto::file_position(&snap, params.text_document_position_params)?; |
340 | let nav_info = match snap.analysis().goto_definition(position)? { | 340 | let nav_info = match snap.analysis.goto_definition(position)? { |
341 | None => return Ok(None), | 341 | None => return Ok(None), |
342 | Some(it) => it, | 342 | Some(it) => it, |
343 | }; | 343 | }; |
@@ -352,7 +352,7 @@ pub(crate) fn handle_goto_implementation( | |||
352 | ) -> Result<Option<lsp_types::request::GotoImplementationResponse>> { | 352 | ) -> Result<Option<lsp_types::request::GotoImplementationResponse>> { |
353 | let _p = profile("handle_goto_implementation"); | 353 | let _p = profile("handle_goto_implementation"); |
354 | let position = from_proto::file_position(&snap, params.text_document_position_params)?; | 354 | let position = from_proto::file_position(&snap, params.text_document_position_params)?; |
355 | let nav_info = match snap.analysis().goto_implementation(position)? { | 355 | let nav_info = match snap.analysis.goto_implementation(position)? { |
356 | None => return Ok(None), | 356 | None => return Ok(None), |
357 | Some(it) => it, | 357 | Some(it) => it, |
358 | }; | 358 | }; |
@@ -367,7 +367,7 @@ pub(crate) fn handle_goto_type_definition( | |||
367 | ) -> Result<Option<lsp_types::request::GotoTypeDefinitionResponse>> { | 367 | ) -> Result<Option<lsp_types::request::GotoTypeDefinitionResponse>> { |
368 | let _p = profile("handle_goto_type_definition"); | 368 | let _p = profile("handle_goto_type_definition"); |
369 | let position = from_proto::file_position(&snap, params.text_document_position_params)?; | 369 | let position = from_proto::file_position(&snap, params.text_document_position_params)?; |
370 | let nav_info = match snap.analysis().goto_type_definition(position)? { | 370 | let nav_info = match snap.analysis.goto_type_definition(position)? { |
371 | None => return Ok(None), | 371 | None => return Ok(None), |
372 | Some(it) => it, | 372 | Some(it) => it, |
373 | }; | 373 | }; |
@@ -382,7 +382,7 @@ pub(crate) fn handle_parent_module( | |||
382 | ) -> Result<Option<lsp_types::GotoDefinitionResponse>> { | 382 | ) -> Result<Option<lsp_types::GotoDefinitionResponse>> { |
383 | let _p = profile("handle_parent_module"); | 383 | let _p = profile("handle_parent_module"); |
384 | let position = from_proto::file_position(&snap, params)?; | 384 | let position = from_proto::file_position(&snap, params)?; |
385 | let navs = snap.analysis().parent_module(position)?; | 385 | let navs = snap.analysis.parent_module(position)?; |
386 | let res = to_proto::goto_definition_response(&snap, None, navs)?; | 386 | let res = to_proto::goto_definition_response(&snap, None, navs)?; |
387 | Ok(Some(res)) | 387 | Ok(Some(res)) |
388 | } | 388 | } |
@@ -393,11 +393,11 @@ pub(crate) fn handle_runnables( | |||
393 | ) -> Result<Vec<lsp_ext::Runnable>> { | 393 | ) -> Result<Vec<lsp_ext::Runnable>> { |
394 | let _p = profile("handle_runnables"); | 394 | let _p = profile("handle_runnables"); |
395 | let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; | 395 | let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; |
396 | let line_index = snap.analysis().file_line_index(file_id)?; | 396 | let line_index = snap.analysis.file_line_index(file_id)?; |
397 | let offset = params.position.map(|it| from_proto::offset(&line_index, it)); | 397 | let offset = params.position.map(|it| from_proto::offset(&line_index, it)); |
398 | let mut res = Vec::new(); | 398 | let mut res = Vec::new(); |
399 | let cargo_spec = CargoTargetSpec::for_file(&snap, file_id)?; | 399 | let cargo_spec = CargoTargetSpec::for_file(&snap, file_id)?; |
400 | for runnable in snap.analysis().runnables(file_id)? { | 400 | for runnable in snap.analysis.runnables(file_id)? { |
401 | if let Some(offset) = offset { | 401 | if let Some(offset) = offset { |
402 | if !runnable.nav.full_range().contains_inclusive(offset) { | 402 | if !runnable.nav.full_range().contains_inclusive(offset) { |
403 | continue; | 403 | continue; |
@@ -456,7 +456,7 @@ pub(crate) fn handle_completion( | |||
456 | let mut res = false; | 456 | let mut res = false; |
457 | if let Some(ctx) = params.context { | 457 | if let Some(ctx) = params.context { |
458 | if ctx.trigger_character.unwrap_or_default() == ":" { | 458 | if ctx.trigger_character.unwrap_or_default() == ":" { |
459 | let source_file = snap.analysis().parse(position.file_id)?; | 459 | let source_file = snap.analysis.parse(position.file_id)?; |
460 | let syntax = source_file.syntax(); | 460 | let syntax = source_file.syntax(); |
461 | let text = syntax.text(); | 461 | let text = syntax.text(); |
462 | if let Some(next_char) = text.char_at(position.offset) { | 462 | if let Some(next_char) = text.char_at(position.offset) { |
@@ -474,11 +474,11 @@ pub(crate) fn handle_completion( | |||
474 | return Ok(None); | 474 | return Ok(None); |
475 | } | 475 | } |
476 | 476 | ||
477 | let items = match snap.analysis().completions(&snap.config.completion, position)? { | 477 | let items = match snap.analysis.completions(&snap.config.completion, position)? { |
478 | None => return Ok(None), | 478 | None => return Ok(None), |
479 | Some(items) => items, | 479 | Some(items) => items, |
480 | }; | 480 | }; |
481 | let line_index = snap.analysis().file_line_index(position.file_id)?; | 481 | let line_index = snap.analysis.file_line_index(position.file_id)?; |
482 | let line_endings = snap.file_line_endings(position.file_id); | 482 | let line_endings = snap.file_line_endings(position.file_id); |
483 | let items: Vec<CompletionItem> = items | 483 | let items: Vec<CompletionItem> = items |
484 | .into_iter() | 484 | .into_iter() |
@@ -494,9 +494,9 @@ pub(crate) fn handle_folding_range( | |||
494 | ) -> Result<Option<Vec<FoldingRange>>> { | 494 | ) -> Result<Option<Vec<FoldingRange>>> { |
495 | let _p = profile("handle_folding_range"); | 495 | let _p = profile("handle_folding_range"); |
496 | let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; | 496 | let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; |
497 | let folds = snap.analysis().folding_ranges(file_id)?; | 497 | let folds = snap.analysis.folding_ranges(file_id)?; |
498 | let text = snap.analysis().file_text(file_id)?; | 498 | let text = snap.analysis.file_text(file_id)?; |
499 | let line_index = snap.analysis().file_line_index(file_id)?; | 499 | let line_index = snap.analysis.file_line_index(file_id)?; |
500 | let line_folding_only = snap.config.client_caps.line_folding_only; | 500 | let line_folding_only = snap.config.client_caps.line_folding_only; |
501 | let res = folds | 501 | let res = folds |
502 | .into_iter() | 502 | .into_iter() |
@@ -511,7 +511,7 @@ pub(crate) fn handle_signature_help( | |||
511 | ) -> Result<Option<lsp_types::SignatureHelp>> { | 511 | ) -> Result<Option<lsp_types::SignatureHelp>> { |
512 | let _p = profile("handle_signature_help"); | 512 | let _p = profile("handle_signature_help"); |
513 | let position = from_proto::file_position(&snap, params.text_document_position_params)?; | 513 | let position = from_proto::file_position(&snap, params.text_document_position_params)?; |
514 | let call_info = match snap.analysis().call_info(position)? { | 514 | let call_info = match snap.analysis.call_info(position)? { |
515 | None => return Ok(None), | 515 | None => return Ok(None), |
516 | Some(it) => it, | 516 | Some(it) => it, |
517 | }; | 517 | }; |
@@ -535,7 +535,7 @@ pub(crate) fn handle_hover( | |||
535 | ) -> Result<Option<lsp_ext::Hover>> { | 535 | ) -> Result<Option<lsp_ext::Hover>> { |
536 | let _p = profile("handle_hover"); | 536 | let _p = profile("handle_hover"); |
537 | let position = from_proto::file_position(&snap, params.text_document_position_params)?; | 537 | let position = from_proto::file_position(&snap, params.text_document_position_params)?; |
538 | let info = match snap.analysis().hover(position)? { | 538 | let info = match snap.analysis.hover(position)? { |
539 | None => return Ok(None), | 539 | None => return Ok(None), |
540 | Some(info) => info, | 540 | Some(info) => info, |
541 | }; | 541 | }; |
@@ -562,13 +562,13 @@ pub(crate) fn handle_prepare_rename( | |||
562 | let _p = profile("handle_prepare_rename"); | 562 | let _p = profile("handle_prepare_rename"); |
563 | let position = from_proto::file_position(&snap, params)?; | 563 | let position = from_proto::file_position(&snap, params)?; |
564 | 564 | ||
565 | let optional_change = snap.analysis().rename(position, "dummy")?; | 565 | let optional_change = snap.analysis.rename(position, "dummy")?; |
566 | let range = match optional_change { | 566 | let range = match optional_change { |
567 | None => return Ok(None), | 567 | None => return Ok(None), |
568 | Some(it) => it.range, | 568 | Some(it) => it.range, |
569 | }; | 569 | }; |
570 | 570 | ||
571 | let line_index = snap.analysis().file_line_index(position.file_id)?; | 571 | let line_index = snap.analysis.file_line_index(position.file_id)?; |
572 | let range = to_proto::range(&line_index, range); | 572 | let range = to_proto::range(&line_index, range); |
573 | Ok(Some(PrepareRenameResponse::Range(range))) | 573 | Ok(Some(PrepareRenameResponse::Range(range))) |
574 | } | 574 | } |
@@ -588,7 +588,7 @@ pub(crate) fn handle_rename( | |||
588 | .into()); | 588 | .into()); |
589 | } | 589 | } |
590 | 590 | ||
591 | let optional_change = snap.analysis().rename(position, &*params.new_name)?; | 591 | let optional_change = snap.analysis.rename(position, &*params.new_name)?; |
592 | let source_change = match optional_change { | 592 | let source_change = match optional_change { |
593 | None => return Ok(None), | 593 | None => return Ok(None), |
594 | Some(it) => it.info, | 594 | Some(it) => it.info, |
@@ -604,7 +604,7 @@ pub(crate) fn handle_references( | |||
604 | let _p = profile("handle_references"); | 604 | let _p = profile("handle_references"); |
605 | let position = from_proto::file_position(&snap, params.text_document_position)?; | 605 | let position = from_proto::file_position(&snap, params.text_document_position)?; |
606 | 606 | ||
607 | let refs = match snap.analysis().find_all_refs(position, None)? { | 607 | let refs = match snap.analysis.find_all_refs(position, None)? { |
608 | None => return Ok(None), | 608 | None => return Ok(None), |
609 | Some(refs) => refs, | 609 | Some(refs) => refs, |
610 | }; | 610 | }; |
@@ -630,10 +630,10 @@ pub(crate) fn handle_formatting( | |||
630 | ) -> Result<Option<Vec<lsp_types::TextEdit>>> { | 630 | ) -> Result<Option<Vec<lsp_types::TextEdit>>> { |
631 | let _p = profile("handle_formatting"); | 631 | let _p = profile("handle_formatting"); |
632 | let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; | 632 | let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; |
633 | let file = snap.analysis().file_text(file_id)?; | 633 | let file = snap.analysis.file_text(file_id)?; |
634 | let crate_ids = snap.analysis().crate_for(file_id)?; | 634 | let crate_ids = snap.analysis.crate_for(file_id)?; |
635 | 635 | ||
636 | let file_line_index = snap.analysis().file_line_index(file_id)?; | 636 | let file_line_index = snap.analysis.file_line_index(file_id)?; |
637 | let end_position = to_proto::position(&file_line_index, TextSize::of(file.as_str())); | 637 | let end_position = to_proto::position(&file_line_index, TextSize::of(file.as_str())); |
638 | 638 | ||
639 | let mut rustfmt = match &snap.config.rustfmt { | 639 | let mut rustfmt = match &snap.config.rustfmt { |
@@ -642,7 +642,7 @@ pub(crate) fn handle_formatting( | |||
642 | cmd.args(extra_args); | 642 | cmd.args(extra_args); |
643 | if let Some(&crate_id) = crate_ids.first() { | 643 | if let Some(&crate_id) = crate_ids.first() { |
644 | // Assume all crates are in the same edition | 644 | // Assume all crates are in the same edition |
645 | let edition = snap.analysis().crate_edition(crate_id)?; | 645 | let edition = snap.analysis.crate_edition(crate_id)?; |
646 | cmd.arg("--edition"); | 646 | cmd.arg("--edition"); |
647 | cmd.arg(edition.to_string()); | 647 | cmd.arg(edition.to_string()); |
648 | } | 648 | } |
@@ -706,9 +706,9 @@ fn handle_fixes( | |||
706 | res: &mut Vec<lsp_ext::CodeAction>, | 706 | res: &mut Vec<lsp_ext::CodeAction>, |
707 | ) -> Result<()> { | 707 | ) -> Result<()> { |
708 | let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; | 708 | let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; |
709 | let line_index = snap.analysis().file_line_index(file_id)?; | 709 | let line_index = snap.analysis.file_line_index(file_id)?; |
710 | let range = from_proto::text_range(&line_index, params.range); | 710 | let range = from_proto::text_range(&line_index, params.range); |
711 | let diagnostics = snap.analysis().diagnostics(file_id)?; | 711 | let diagnostics = snap.analysis.diagnostics(file_id)?; |
712 | 712 | ||
713 | let fixes_from_diagnostics = diagnostics | 713 | let fixes_from_diagnostics = diagnostics |
714 | .into_iter() | 714 | .into_iter() |
@@ -752,7 +752,7 @@ pub(crate) fn handle_code_action( | |||
752 | } | 752 | } |
753 | 753 | ||
754 | let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; | 754 | let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; |
755 | let line_index = snap.analysis().file_line_index(file_id)?; | 755 | let line_index = snap.analysis.file_line_index(file_id)?; |
756 | let range = from_proto::text_range(&line_index, params.range); | 756 | let range = from_proto::text_range(&line_index, params.range); |
757 | let frange = FileRange { file_id, range }; | 757 | let frange = FileRange { file_id, range }; |
758 | let mut res: Vec<lsp_ext::CodeAction> = Vec::new(); | 758 | let mut res: Vec<lsp_ext::CodeAction> = Vec::new(); |
@@ -761,12 +761,12 @@ pub(crate) fn handle_code_action( | |||
761 | 761 | ||
762 | if snap.config.client_caps.resolve_code_action { | 762 | if snap.config.client_caps.resolve_code_action { |
763 | for (index, assist) in | 763 | for (index, assist) in |
764 | snap.analysis().unresolved_assists(&snap.config.assist, frange)?.into_iter().enumerate() | 764 | snap.analysis.unresolved_assists(&snap.config.assist, frange)?.into_iter().enumerate() |
765 | { | 765 | { |
766 | res.push(to_proto::unresolved_code_action(&snap, assist, index)?); | 766 | res.push(to_proto::unresolved_code_action(&snap, assist, index)?); |
767 | } | 767 | } |
768 | } else { | 768 | } else { |
769 | for assist in snap.analysis().resolved_assists(&snap.config.assist, frange)?.into_iter() { | 769 | for assist in snap.analysis.resolved_assists(&snap.config.assist, frange)?.into_iter() { |
770 | res.push(to_proto::resolved_code_action(&snap, assist)?); | 770 | res.push(to_proto::resolved_code_action(&snap, assist)?); |
771 | } | 771 | } |
772 | } | 772 | } |
@@ -780,11 +780,11 @@ pub(crate) fn handle_resolve_code_action( | |||
780 | ) -> Result<Option<lsp_ext::SnippetWorkspaceEdit>> { | 780 | ) -> Result<Option<lsp_ext::SnippetWorkspaceEdit>> { |
781 | let _p = profile("handle_resolve_code_action"); | 781 | let _p = profile("handle_resolve_code_action"); |
782 | let file_id = from_proto::file_id(&snap, ¶ms.code_action_params.text_document.uri)?; | 782 | let file_id = from_proto::file_id(&snap, ¶ms.code_action_params.text_document.uri)?; |
783 | let line_index = snap.analysis().file_line_index(file_id)?; | 783 | let line_index = snap.analysis.file_line_index(file_id)?; |
784 | let range = from_proto::text_range(&line_index, params.code_action_params.range); | 784 | let range = from_proto::text_range(&line_index, params.code_action_params.range); |
785 | let frange = FileRange { file_id, range }; | 785 | let frange = FileRange { file_id, range }; |
786 | 786 | ||
787 | let assists = snap.analysis().resolved_assists(&snap.config.assist, frange)?; | 787 | let assists = snap.analysis.resolved_assists(&snap.config.assist, frange)?; |
788 | let (id_string, index) = split_delim(¶ms.id, ':').unwrap(); | 788 | let (id_string, index) = split_delim(¶ms.id, ':').unwrap(); |
789 | let index = index.parse::<usize>().unwrap(); | 789 | let index = index.parse::<usize>().unwrap(); |
790 | let assist = &assists[index]; | 790 | let assist = &assists[index]; |
@@ -805,12 +805,12 @@ pub(crate) fn handle_code_lens( | |||
805 | } | 805 | } |
806 | 806 | ||
807 | let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; | 807 | let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; |
808 | let line_index = snap.analysis().file_line_index(file_id)?; | 808 | let line_index = snap.analysis.file_line_index(file_id)?; |
809 | let cargo_spec = CargoTargetSpec::for_file(&snap, file_id)?; | 809 | let cargo_spec = CargoTargetSpec::for_file(&snap, file_id)?; |
810 | 810 | ||
811 | if snap.config.lens.runnable() { | 811 | if snap.config.lens.runnable() { |
812 | // Gather runnables | 812 | // Gather runnables |
813 | for runnable in snap.analysis().runnables(file_id)? { | 813 | for runnable in snap.analysis.runnables(file_id)? { |
814 | if should_skip_target(&runnable, cargo_spec.as_ref()) { | 814 | if should_skip_target(&runnable, cargo_spec.as_ref()) { |
815 | continue; | 815 | continue; |
816 | } | 816 | } |
@@ -838,7 +838,7 @@ pub(crate) fn handle_code_lens( | |||
838 | if snap.config.lens.impementations { | 838 | if snap.config.lens.impementations { |
839 | // Handle impls | 839 | // Handle impls |
840 | lenses.extend( | 840 | lenses.extend( |
841 | snap.analysis() | 841 | snap.analysis |
842 | .file_structure(file_id)? | 842 | .file_structure(file_id)? |
843 | .into_iter() | 843 | .into_iter() |
844 | .filter(|it| match it.kind { | 844 | .filter(|it| match it.kind { |
@@ -916,10 +916,10 @@ pub(crate) fn handle_document_highlight( | |||
916 | ) -> Result<Option<Vec<DocumentHighlight>>> { | 916 | ) -> Result<Option<Vec<DocumentHighlight>>> { |
917 | let _p = profile("handle_document_highlight"); | 917 | let _p = profile("handle_document_highlight"); |
918 | let position = from_proto::file_position(&snap, params.text_document_position_params)?; | 918 | let position = from_proto::file_position(&snap, params.text_document_position_params)?; |
919 | let line_index = snap.analysis().file_line_index(position.file_id)?; | 919 | let line_index = snap.analysis.file_line_index(position.file_id)?; |
920 | 920 | ||
921 | let refs = match snap | 921 | let refs = match snap |
922 | .analysis() | 922 | .analysis |
923 | .find_all_refs(position, Some(SearchScope::single_file(position.file_id)))? | 923 | .find_all_refs(position, Some(SearchScope::single_file(position.file_id)))? |
924 | { | 924 | { |
925 | None => return Ok(None), | 925 | None => return Ok(None), |
@@ -943,7 +943,7 @@ pub(crate) fn handle_ssr( | |||
943 | ) -> Result<lsp_types::WorkspaceEdit> { | 943 | ) -> Result<lsp_types::WorkspaceEdit> { |
944 | let _p = profile("handle_ssr"); | 944 | let _p = profile("handle_ssr"); |
945 | let source_change = | 945 | let source_change = |
946 | snap.analysis().structural_search_replace(¶ms.query, params.parse_only)??; | 946 | snap.analysis.structural_search_replace(¶ms.query, params.parse_only)??; |
947 | to_proto::workspace_edit(&snap, source_change) | 947 | to_proto::workspace_edit(&snap, source_change) |
948 | } | 948 | } |
949 | 949 | ||
@@ -952,9 +952,9 @@ pub(crate) fn publish_diagnostics( | |||
952 | file_id: FileId, | 952 | file_id: FileId, |
953 | ) -> Result<DiagnosticTask> { | 953 | ) -> Result<DiagnosticTask> { |
954 | let _p = profile("publish_diagnostics"); | 954 | let _p = profile("publish_diagnostics"); |
955 | let line_index = snap.analysis().file_line_index(file_id)?; | 955 | let line_index = snap.analysis.file_line_index(file_id)?; |
956 | let diagnostics: Vec<Diagnostic> = snap | 956 | let diagnostics: Vec<Diagnostic> = snap |
957 | .analysis() | 957 | .analysis |
958 | .diagnostics(file_id)? | 958 | .diagnostics(file_id)? |
959 | .into_iter() | 959 | .into_iter() |
960 | .map(|d| Diagnostic { | 960 | .map(|d| Diagnostic { |
@@ -976,9 +976,9 @@ pub(crate) fn handle_inlay_hints( | |||
976 | ) -> Result<Vec<InlayHint>> { | 976 | ) -> Result<Vec<InlayHint>> { |
977 | let _p = profile("handle_inlay_hints"); | 977 | let _p = profile("handle_inlay_hints"); |
978 | let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; | 978 | let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; |
979 | let analysis = snap.analysis(); | 979 | let line_index = snap.analysis.file_line_index(file_id)?; |
980 | let line_index = analysis.file_line_index(file_id)?; | 980 | Ok(snap |
981 | Ok(analysis | 981 | .analysis |
982 | .inlay_hints(file_id, &snap.config.inlay_hints)? | 982 | .inlay_hints(file_id, &snap.config.inlay_hints)? |
983 | .into_iter() | 983 | .into_iter() |
984 | .map(|it| to_proto::inlay_int(&line_index, it)) | 984 | .map(|it| to_proto::inlay_int(&line_index, it)) |
@@ -992,7 +992,7 @@ pub(crate) fn handle_call_hierarchy_prepare( | |||
992 | let _p = profile("handle_call_hierarchy_prepare"); | 992 | let _p = profile("handle_call_hierarchy_prepare"); |
993 | let position = from_proto::file_position(&snap, params.text_document_position_params)?; | 993 | let position = from_proto::file_position(&snap, params.text_document_position_params)?; |
994 | 994 | ||
995 | let nav_info = match snap.analysis().call_hierarchy(position)? { | 995 | let nav_info = match snap.analysis.call_hierarchy(position)? { |
996 | None => return Ok(None), | 996 | None => return Ok(None), |
997 | Some(it) => it, | 997 | Some(it) => it, |
998 | }; | 998 | }; |
@@ -1018,7 +1018,7 @@ pub(crate) fn handle_call_hierarchy_incoming( | |||
1018 | let frange = from_proto::file_range(&snap, doc, item.range)?; | 1018 | let frange = from_proto::file_range(&snap, doc, item.range)?; |
1019 | let fpos = FilePosition { file_id: frange.file_id, offset: frange.range.start() }; | 1019 | let fpos = FilePosition { file_id: frange.file_id, offset: frange.range.start() }; |
1020 | 1020 | ||
1021 | let call_items = match snap.analysis().incoming_calls(fpos)? { | 1021 | let call_items = match snap.analysis.incoming_calls(fpos)? { |
1022 | None => return Ok(None), | 1022 | None => return Ok(None), |
1023 | Some(it) => it, | 1023 | Some(it) => it, |
1024 | }; | 1024 | }; |
@@ -1027,7 +1027,7 @@ pub(crate) fn handle_call_hierarchy_incoming( | |||
1027 | 1027 | ||
1028 | for call_item in call_items.into_iter() { | 1028 | for call_item in call_items.into_iter() { |
1029 | let file_id = call_item.target.file_id(); | 1029 | let file_id = call_item.target.file_id(); |
1030 | let line_index = snap.analysis().file_line_index(file_id)?; | 1030 | let line_index = snap.analysis.file_line_index(file_id)?; |
1031 | let item = to_proto::call_hierarchy_item(&snap, call_item.target)?; | 1031 | let item = to_proto::call_hierarchy_item(&snap, call_item.target)?; |
1032 | res.push(CallHierarchyIncomingCall { | 1032 | res.push(CallHierarchyIncomingCall { |
1033 | from: item, | 1033 | from: item, |
@@ -1053,7 +1053,7 @@ pub(crate) fn handle_call_hierarchy_outgoing( | |||
1053 | let frange = from_proto::file_range(&snap, doc, item.range)?; | 1053 | let frange = from_proto::file_range(&snap, doc, item.range)?; |
1054 | let fpos = FilePosition { file_id: frange.file_id, offset: frange.range.start() }; | 1054 | let fpos = FilePosition { file_id: frange.file_id, offset: frange.range.start() }; |
1055 | 1055 | ||
1056 | let call_items = match snap.analysis().outgoing_calls(fpos)? { | 1056 | let call_items = match snap.analysis.outgoing_calls(fpos)? { |
1057 | None => return Ok(None), | 1057 | None => return Ok(None), |
1058 | Some(it) => it, | 1058 | Some(it) => it, |
1059 | }; | 1059 | }; |
@@ -1062,7 +1062,7 @@ pub(crate) fn handle_call_hierarchy_outgoing( | |||
1062 | 1062 | ||
1063 | for call_item in call_items.into_iter() { | 1063 | for call_item in call_items.into_iter() { |
1064 | let file_id = call_item.target.file_id(); | 1064 | let file_id = call_item.target.file_id(); |
1065 | let line_index = snap.analysis().file_line_index(file_id)?; | 1065 | let line_index = snap.analysis.file_line_index(file_id)?; |
1066 | let item = to_proto::call_hierarchy_item(&snap, call_item.target)?; | 1066 | let item = to_proto::call_hierarchy_item(&snap, call_item.target)?; |
1067 | res.push(CallHierarchyOutgoingCall { | 1067 | res.push(CallHierarchyOutgoingCall { |
1068 | to: item, | 1068 | to: item, |
@@ -1084,10 +1084,10 @@ pub(crate) fn handle_semantic_tokens( | |||
1084 | let _p = profile("handle_semantic_tokens"); | 1084 | let _p = profile("handle_semantic_tokens"); |
1085 | 1085 | ||
1086 | let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; | 1086 | let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; |
1087 | let text = snap.analysis().file_text(file_id)?; | 1087 | let text = snap.analysis.file_text(file_id)?; |
1088 | let line_index = snap.analysis().file_line_index(file_id)?; | 1088 | let line_index = snap.analysis.file_line_index(file_id)?; |
1089 | 1089 | ||
1090 | let highlights = snap.analysis().highlight(file_id)?; | 1090 | let highlights = snap.analysis.highlight(file_id)?; |
1091 | let semantic_tokens = to_proto::semantic_tokens(&text, &line_index, highlights); | 1091 | let semantic_tokens = to_proto::semantic_tokens(&text, &line_index, highlights); |
1092 | Ok(Some(semantic_tokens.into())) | 1092 | Ok(Some(semantic_tokens.into())) |
1093 | } | 1093 | } |
@@ -1099,10 +1099,10 @@ pub(crate) fn handle_semantic_tokens_range( | |||
1099 | let _p = profile("handle_semantic_tokens_range"); | 1099 | let _p = profile("handle_semantic_tokens_range"); |
1100 | 1100 | ||
1101 | let frange = from_proto::file_range(&snap, params.text_document, params.range)?; | 1101 | let frange = from_proto::file_range(&snap, params.text_document, params.range)?; |
1102 | let text = snap.analysis().file_text(frange.file_id)?; | 1102 | let text = snap.analysis.file_text(frange.file_id)?; |
1103 | let line_index = snap.analysis().file_line_index(frange.file_id)?; | 1103 | let line_index = snap.analysis.file_line_index(frange.file_id)?; |
1104 | 1104 | ||
1105 | let highlights = snap.analysis().highlight_range(frange)?; | 1105 | let highlights = snap.analysis.highlight_range(frange)?; |
1106 | let semantic_tokens = to_proto::semantic_tokens(&text, &line_index, highlights); | 1106 | let semantic_tokens = to_proto::semantic_tokens(&text, &line_index, highlights); |
1107 | Ok(Some(semantic_tokens.into())) | 1107 | Ok(Some(semantic_tokens.into())) |
1108 | } | 1108 | } |
@@ -1178,9 +1178,9 @@ fn show_impl_command_link( | |||
1178 | position: &FilePosition, | 1178 | position: &FilePosition, |
1179 | ) -> Option<lsp_ext::CommandLinkGroup> { | 1179 | ) -> Option<lsp_ext::CommandLinkGroup> { |
1180 | if snap.config.hover.implementations { | 1180 | if snap.config.hover.implementations { |
1181 | if let Some(nav_data) = snap.analysis().goto_implementation(*position).unwrap_or(None) { | 1181 | if let Some(nav_data) = snap.analysis.goto_implementation(*position).unwrap_or(None) { |
1182 | let uri = to_proto::url(snap, position.file_id); | 1182 | let uri = to_proto::url(snap, position.file_id); |
1183 | let line_index = snap.analysis().file_line_index(position.file_id).ok()?; | 1183 | let line_index = snap.analysis.file_line_index(position.file_id).ok()?; |
1184 | let position = to_proto::position(&line_index, position.offset); | 1184 | let position = to_proto::position(&line_index, position.offset); |
1185 | let locations: Vec<_> = nav_data | 1185 | let locations: Vec<_> = nav_data |
1186 | .info | 1186 | .info |
diff --git a/crates/rust-analyzer/src/lib.rs b/crates/rust-analyzer/src/lib.rs index 9757a16a3..d6cd04303 100644 --- a/crates/rust-analyzer/src/lib.rs +++ b/crates/rust-analyzer/src/lib.rs | |||
@@ -37,12 +37,32 @@ use serde::de::DeserializeOwned; | |||
37 | pub type Result<T, E = Box<dyn std::error::Error + Send + Sync>> = std::result::Result<T, E>; | 37 | pub type Result<T, E = Box<dyn std::error::Error + Send + Sync>> = std::result::Result<T, E>; |
38 | pub use crate::{ | 38 | pub use crate::{ |
39 | caps::server_capabilities, | 39 | caps::server_capabilities, |
40 | main_loop::LspError, | ||
41 | main_loop::{main_loop, show_message}, | 40 | main_loop::{main_loop, show_message}, |
42 | }; | 41 | }; |
42 | use std::fmt; | ||
43 | 43 | ||
44 | pub fn from_json<T: DeserializeOwned>(what: &'static str, json: serde_json::Value) -> Result<T> { | 44 | pub fn from_json<T: DeserializeOwned>(what: &'static str, json: serde_json::Value) -> Result<T> { |
45 | let res = T::deserialize(&json) | 45 | let res = T::deserialize(&json) |
46 | .map_err(|e| format!("Failed to deserialize {}: {}; {}", what, e, json))?; | 46 | .map_err(|e| format!("Failed to deserialize {}: {}; {}", what, e, json))?; |
47 | Ok(res) | 47 | Ok(res) |
48 | } | 48 | } |
49 | |||
50 | #[derive(Debug)] | ||
51 | struct LspError { | ||
52 | code: i32, | ||
53 | message: String, | ||
54 | } | ||
55 | |||
56 | impl LspError { | ||
57 | fn new(code: i32, message: String) -> LspError { | ||
58 | LspError { code, message } | ||
59 | } | ||
60 | } | ||
61 | |||
62 | impl fmt::Display for LspError { | ||
63 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
64 | write!(f, "Language Server request failed with {}. ({})", self.code, self.message) | ||
65 | } | ||
66 | } | ||
67 | |||
68 | impl std::error::Error for LspError {} | ||
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index c8819c3b0..eb9e7f913 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs | |||
@@ -1,9 +1,7 @@ | |||
1 | //! The main loop of `rust-analyzer` responsible for dispatching LSP | 1 | //! The main loop of `rust-analyzer` responsible for dispatching LSP |
2 | //! requests/replies and notifications back to the client. | 2 | //! requests/replies and notifications back to the client. |
3 | use std::{ | 3 | use std::{ |
4 | env, | 4 | env, fmt, |
5 | error::Error, | ||
6 | fmt, | ||
7 | ops::Range, | 5 | ops::Range, |
8 | panic, | 6 | panic, |
9 | sync::Arc, | 7 | sync::Arc, |
@@ -11,16 +9,13 @@ use std::{ | |||
11 | }; | 9 | }; |
12 | 10 | ||
13 | use crossbeam_channel::{never, select, unbounded, RecvError, Sender}; | 11 | use crossbeam_channel::{never, select, unbounded, RecvError, Sender}; |
14 | use lsp_server::{ | 12 | use lsp_server::{Connection, ErrorCode, Message, Notification, Request, RequestId, Response}; |
15 | Connection, ErrorCode, Message, Notification, ReqQueue, Request, RequestId, Response, | ||
16 | }; | ||
17 | use lsp_types::{request::Request as _, NumberOrString, TextDocumentContentChangeEvent}; | 13 | use lsp_types::{request::Request as _, NumberOrString, TextDocumentContentChangeEvent}; |
18 | use ra_db::VfsPath; | 14 | use ra_db::VfsPath; |
19 | use ra_flycheck::CheckTask; | 15 | use ra_flycheck::CheckTask; |
20 | use ra_ide::{Canceled, FileId, LineIndex}; | 16 | use ra_ide::{Canceled, FileId, LineIndex}; |
21 | use ra_prof::profile; | 17 | use ra_prof::profile; |
22 | use ra_project_model::{PackageRoot, ProjectWorkspace}; | 18 | use ra_project_model::{PackageRoot, ProjectWorkspace}; |
23 | use rustc_hash::FxHashSet; | ||
24 | use serde::{de::DeserializeOwned, Serialize}; | 19 | use serde::{de::DeserializeOwned, Serialize}; |
25 | use threadpool::ThreadPool; | 20 | use threadpool::ThreadPool; |
26 | 21 | ||
@@ -28,34 +23,12 @@ use crate::{ | |||
28 | config::{Config, FilesWatcher, LinkedProject}, | 23 | config::{Config, FilesWatcher, LinkedProject}, |
29 | diagnostics::DiagnosticTask, | 24 | diagnostics::DiagnosticTask, |
30 | from_proto, | 25 | from_proto, |
31 | global_state::{file_id_to_url, GlobalState, GlobalStateSnapshot}, | 26 | global_state::{file_id_to_url, GlobalState, GlobalStateSnapshot, Status}, |
32 | handlers, lsp_ext, | 27 | handlers, lsp_ext, |
33 | request_metrics::RequestMetrics, | 28 | request_metrics::RequestMetrics, |
34 | Result, | 29 | LspError, Result, |
35 | }; | 30 | }; |
36 | 31 | ||
37 | #[derive(Debug)] | ||
38 | pub struct LspError { | ||
39 | pub code: i32, | ||
40 | pub message: String, | ||
41 | } | ||
42 | |||
43 | impl LspError { | ||
44 | pub const UNKNOWN_FILE: i32 = -32900; | ||
45 | |||
46 | pub fn new(code: i32, message: String) -> LspError { | ||
47 | LspError { code, message } | ||
48 | } | ||
49 | } | ||
50 | |||
51 | impl fmt::Display for LspError { | ||
52 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
53 | write!(f, "Language Server request failed with {}. ({})", self.code, self.message) | ||
54 | } | ||
55 | } | ||
56 | |||
57 | impl Error for LspError {} | ||
58 | |||
59 | pub fn main_loop(config: Config, connection: Connection) -> Result<()> { | 32 | pub fn main_loop(config: Config, connection: Connection) -> Result<()> { |
60 | log::info!("initial config: {:#?}", config); | 33 | log::info!("initial config: {:#?}", config); |
61 | 34 | ||
@@ -78,7 +51,6 @@ pub fn main_loop(config: Config, connection: Connection) -> Result<()> { | |||
78 | SetThreadPriority(thread, thread_priority_above_normal); | 51 | SetThreadPriority(thread, thread_priority_above_normal); |
79 | } | 52 | } |
80 | 53 | ||
81 | let mut loop_state = LoopState::default(); | ||
82 | let mut global_state = { | 54 | let mut global_state = { |
83 | let workspaces = { | 55 | let workspaces = { |
84 | if config.linked_projects.is_empty() && config.notifications.cargo_toml_not_found { | 56 | if config.linked_projects.is_empty() && config.notifications.cargo_toml_not_found { |
@@ -116,6 +88,8 @@ pub fn main_loop(config: Config, connection: Connection) -> Result<()> { | |||
116 | .collect::<Vec<_>>() | 88 | .collect::<Vec<_>>() |
117 | }; | 89 | }; |
118 | 90 | ||
91 | let mut req_queue = ReqQueue::default(); | ||
92 | |||
119 | if let FilesWatcher::Client = config.files.watcher { | 93 | if let FilesWatcher::Client = config.files.watcher { |
120 | let registration_options = lsp_types::DidChangeWatchedFilesRegistrationOptions { | 94 | let registration_options = lsp_types::DidChangeWatchedFilesRegistrationOptions { |
121 | watchers: workspaces | 95 | watchers: workspaces |
@@ -132,7 +106,7 @@ pub fn main_loop(config: Config, connection: Connection) -> Result<()> { | |||
132 | register_options: Some(serde_json::to_value(registration_options).unwrap()), | 106 | register_options: Some(serde_json::to_value(registration_options).unwrap()), |
133 | }; | 107 | }; |
134 | let params = lsp_types::RegistrationParams { registrations: vec![registration] }; | 108 | let params = lsp_types::RegistrationParams { registrations: vec![registration] }; |
135 | let request = loop_state.req_queue.outgoing.register( | 109 | let request = req_queue.outgoing.register( |
136 | lsp_types::request::RegisterCapability::METHOD.to_string(), | 110 | lsp_types::request::RegisterCapability::METHOD.to_string(), |
137 | params, | 111 | params, |
138 | DO_NOTHING, | 112 | DO_NOTHING, |
@@ -140,7 +114,7 @@ pub fn main_loop(config: Config, connection: Connection) -> Result<()> { | |||
140 | connection.sender.send(request.into()).unwrap(); | 114 | connection.sender.send(request.into()).unwrap(); |
141 | } | 115 | } |
142 | 116 | ||
143 | GlobalState::new(workspaces, config.lru_capacity, config) | 117 | GlobalState::new(workspaces, config.lru_capacity, config, req_queue) |
144 | }; | 118 | }; |
145 | 119 | ||
146 | let pool = ThreadPool::default(); | 120 | let pool = ThreadPool::default(); |
@@ -172,15 +146,13 @@ pub fn main_loop(config: Config, connection: Connection) -> Result<()> { | |||
172 | }; | 146 | }; |
173 | } | 147 | } |
174 | assert!(!global_state.vfs.read().0.has_changes()); | 148 | assert!(!global_state.vfs.read().0.has_changes()); |
175 | loop_turn(&pool, &task_sender, &connection, &mut global_state, &mut loop_state, event)?; | 149 | loop_turn(&pool, &task_sender, &connection, &mut global_state, event)?; |
176 | assert!(!global_state.vfs.read().0.has_changes()); | 150 | assert!(!global_state.vfs.read().0.has_changes()); |
177 | } | 151 | } |
178 | } | 152 | } |
179 | global_state.analysis_host.request_cancellation(); | 153 | global_state.analysis_host.request_cancellation(); |
180 | log::info!("waiting for tasks to finish..."); | 154 | log::info!("waiting for tasks to finish..."); |
181 | task_receiver.into_iter().for_each(|task| { | 155 | task_receiver.into_iter().for_each(|task| on_task(task, &connection.sender, &mut global_state)); |
182 | on_task(task, &connection.sender, &mut loop_state.req_queue.incoming, &mut global_state) | ||
183 | }); | ||
184 | log::info!("...tasks have finished"); | 156 | log::info!("...tasks have finished"); |
185 | log::info!("joining threadpool..."); | 157 | log::info!("joining threadpool..."); |
186 | pool.join(); | 158 | pool.join(); |
@@ -244,35 +216,15 @@ impl fmt::Debug for Event { | |||
244 | } | 216 | } |
245 | } | 217 | } |
246 | 218 | ||
247 | type ReqHandler = fn(&mut GlobalState, Response); | 219 | pub(crate) type ReqHandler = fn(&mut GlobalState, Response); |
220 | pub(crate) type ReqQueue = lsp_server::ReqQueue<(&'static str, Instant), ReqHandler>; | ||
248 | const DO_NOTHING: ReqHandler = |_, _| (); | 221 | const DO_NOTHING: ReqHandler = |_, _| (); |
249 | type Incoming = lsp_server::Incoming<(&'static str, Instant)>; | ||
250 | |||
251 | #[derive(Default)] | ||
252 | struct LoopState { | ||
253 | req_queue: ReqQueue<(&'static str, Instant), ReqHandler>, | ||
254 | mem_docs: FxHashSet<VfsPath>, | ||
255 | status: Status, | ||
256 | } | ||
257 | |||
258 | #[derive(Eq, PartialEq)] | ||
259 | enum Status { | ||
260 | Loading, | ||
261 | Ready, | ||
262 | } | ||
263 | |||
264 | impl Default for Status { | ||
265 | fn default() -> Self { | ||
266 | Status::Loading | ||
267 | } | ||
268 | } | ||
269 | 222 | ||
270 | fn loop_turn( | 223 | fn loop_turn( |
271 | pool: &ThreadPool, | 224 | pool: &ThreadPool, |
272 | task_sender: &Sender<Task>, | 225 | task_sender: &Sender<Task>, |
273 | connection: &Connection, | 226 | connection: &Connection, |
274 | global_state: &mut GlobalState, | 227 | global_state: &mut GlobalState, |
275 | loop_state: &mut LoopState, | ||
276 | event: Event, | 228 | event: Event, |
277 | ) -> Result<()> { | 229 | ) -> Result<()> { |
278 | let loop_start = Instant::now(); | 230 | let loop_start = Instant::now(); |
@@ -288,7 +240,7 @@ fn loop_turn( | |||
288 | let mut became_ready = false; | 240 | let mut became_ready = false; |
289 | match event { | 241 | match event { |
290 | Event::Task(task) => { | 242 | Event::Task(task) => { |
291 | on_task(task, &connection.sender, &mut loop_state.req_queue.incoming, global_state); | 243 | on_task(task, &connection.sender, global_state); |
292 | global_state.maybe_collect_garbage(); | 244 | global_state.maybe_collect_garbage(); |
293 | } | 245 | } |
294 | Event::Vfs(task) => match task { | 246 | Event::Vfs(task) => match task { |
@@ -296,35 +248,29 @@ fn loop_turn( | |||
296 | let vfs = &mut global_state.vfs.write().0; | 248 | let vfs = &mut global_state.vfs.write().0; |
297 | for (path, contents) in files { | 249 | for (path, contents) in files { |
298 | let path = VfsPath::from(path); | 250 | let path = VfsPath::from(path); |
299 | if !loop_state.mem_docs.contains(&path) { | 251 | if !global_state.mem_docs.contains(&path) { |
300 | vfs.set_file_contents(path, contents) | 252 | vfs.set_file_contents(path, contents) |
301 | } | 253 | } |
302 | } | 254 | } |
303 | } | 255 | } |
304 | vfs::loader::Message::Progress { n_total, n_done } => { | 256 | vfs::loader::Message::Progress { n_total, n_done } => { |
305 | if n_done == n_total { | 257 | if n_done == n_total { |
306 | loop_state.status = Status::Ready; | 258 | global_state.status = Status::Ready; |
307 | became_ready = true; | 259 | became_ready = true; |
308 | } | 260 | } |
309 | report_progress(loop_state, &connection.sender, n_done, n_total, "roots scanned") | 261 | report_progress(global_state, &connection.sender, n_done, n_total, "roots scanned") |
310 | } | 262 | } |
311 | }, | 263 | }, |
312 | Event::CheckWatcher(task) => on_check_task(task, global_state, task_sender)?, | 264 | Event::CheckWatcher(task) => on_check_task(task, global_state, task_sender)?, |
313 | Event::Msg(msg) => match msg { | 265 | Event::Msg(msg) => match msg { |
314 | Message::Request(req) => on_request( | 266 | Message::Request(req) => { |
315 | global_state, | 267 | on_request(global_state, pool, task_sender, &connection.sender, loop_start, req)? |
316 | &mut loop_state.req_queue.incoming, | 268 | } |
317 | pool, | ||
318 | task_sender, | ||
319 | &connection.sender, | ||
320 | loop_start, | ||
321 | req, | ||
322 | )?, | ||
323 | Message::Notification(not) => { | 269 | Message::Notification(not) => { |
324 | on_notification(&connection.sender, global_state, loop_state, not)?; | 270 | on_notification(&connection.sender, global_state, not)?; |
325 | } | 271 | } |
326 | Message::Response(resp) => { | 272 | Message::Response(resp) => { |
327 | let handler = loop_state.req_queue.outgoing.complete(resp.id.clone()); | 273 | let handler = global_state.req_queue.outgoing.complete(resp.id.clone()); |
328 | handler(global_state, resp) | 274 | handler(global_state, resp) |
329 | } | 275 | } |
330 | }, | 276 | }, |
@@ -338,8 +284,8 @@ fn loop_turn( | |||
338 | } | 284 | } |
339 | } | 285 | } |
340 | 286 | ||
341 | if loop_state.status == Status::Ready && (state_changed || became_ready) { | 287 | if global_state.status == Status::Ready && (state_changed || became_ready) { |
342 | let subscriptions = loop_state | 288 | let subscriptions = global_state |
343 | .mem_docs | 289 | .mem_docs |
344 | .iter() | 290 | .iter() |
345 | .map(|path| global_state.vfs.read().0.file_id(&path).unwrap()) | 291 | .map(|path| global_state.vfs.read().0.file_id(&path).unwrap()) |
@@ -354,7 +300,7 @@ fn loop_turn( | |||
354 | pool.execute({ | 300 | pool.execute({ |
355 | let subs = subscriptions; | 301 | let subs = subscriptions; |
356 | let snap = global_state.snapshot(); | 302 | let snap = global_state.snapshot(); |
357 | move || snap.analysis().prime_caches(subs).unwrap_or_else(|_: Canceled| ()) | 303 | move || snap.analysis.prime_caches(subs).unwrap_or_else(|_: Canceled| ()) |
358 | }); | 304 | }); |
359 | } | 305 | } |
360 | 306 | ||
@@ -373,18 +319,15 @@ fn loop_turn( | |||
373 | Ok(()) | 319 | Ok(()) |
374 | } | 320 | } |
375 | 321 | ||
376 | fn on_task( | 322 | fn on_task(task: Task, msg_sender: &Sender<Message>, global_state: &mut GlobalState) { |
377 | task: Task, | ||
378 | msg_sender: &Sender<Message>, | ||
379 | incoming_requests: &mut Incoming, | ||
380 | state: &mut GlobalState, | ||
381 | ) { | ||
382 | match task { | 323 | match task { |
383 | Task::Respond(response) => { | 324 | Task::Respond(response) => { |
384 | if let Some((method, start)) = incoming_requests.complete(response.id.clone()) { | 325 | if let Some((method, start)) = |
326 | global_state.req_queue.incoming.complete(response.id.clone()) | ||
327 | { | ||
385 | let duration = start.elapsed(); | 328 | let duration = start.elapsed(); |
386 | log::info!("handled req#{} in {:?}", response.id, duration); | 329 | log::info!("handled req#{} in {:?}", response.id, duration); |
387 | state.complete_request(RequestMetrics { | 330 | global_state.complete_request(RequestMetrics { |
388 | id: response.id.clone(), | 331 | id: response.id.clone(), |
389 | method: method.to_string(), | 332 | method: method.to_string(), |
390 | duration, | 333 | duration, |
@@ -395,13 +338,12 @@ fn on_task( | |||
395 | Task::Notify(n) => { | 338 | Task::Notify(n) => { |
396 | msg_sender.send(n.into()).unwrap(); | 339 | msg_sender.send(n.into()).unwrap(); |
397 | } | 340 | } |
398 | Task::Diagnostic(task) => on_diagnostic_task(task, msg_sender, state), | 341 | Task::Diagnostic(task) => on_diagnostic_task(task, msg_sender, global_state), |
399 | } | 342 | } |
400 | } | 343 | } |
401 | 344 | ||
402 | fn on_request( | 345 | fn on_request( |
403 | global_state: &mut GlobalState, | 346 | global_state: &mut GlobalState, |
404 | incoming_requests: &mut Incoming, | ||
405 | pool: &ThreadPool, | 347 | pool: &ThreadPool, |
406 | task_sender: &Sender<Task>, | 348 | task_sender: &Sender<Task>, |
407 | msg_sender: &Sender<Message>, | 349 | msg_sender: &Sender<Message>, |
@@ -414,7 +356,6 @@ fn on_request( | |||
414 | global_state, | 356 | global_state, |
415 | task_sender, | 357 | task_sender, |
416 | msg_sender, | 358 | msg_sender, |
417 | incoming_requests, | ||
418 | request_received, | 359 | request_received, |
419 | }; | 360 | }; |
420 | pool_dispatcher | 361 | pool_dispatcher |
@@ -469,7 +410,6 @@ fn on_request( | |||
469 | fn on_notification( | 410 | fn on_notification( |
470 | msg_sender: &Sender<Message>, | 411 | msg_sender: &Sender<Message>, |
471 | global_state: &mut GlobalState, | 412 | global_state: &mut GlobalState, |
472 | loop_state: &mut LoopState, | ||
473 | not: Notification, | 413 | not: Notification, |
474 | ) -> Result<()> { | 414 | ) -> Result<()> { |
475 | let not = match notification_cast::<lsp_types::notification::Cancel>(not) { | 415 | let not = match notification_cast::<lsp_types::notification::Cancel>(not) { |
@@ -478,7 +418,7 @@ fn on_notification( | |||
478 | NumberOrString::Number(id) => id.into(), | 418 | NumberOrString::Number(id) => id.into(), |
479 | NumberOrString::String(id) => id.into(), | 419 | NumberOrString::String(id) => id.into(), |
480 | }; | 420 | }; |
481 | if let Some(response) = loop_state.req_queue.incoming.cancel(id) { | 421 | if let Some(response) = global_state.req_queue.incoming.cancel(id) { |
482 | msg_sender.send(response.into()).unwrap() | 422 | msg_sender.send(response.into()).unwrap() |
483 | } | 423 | } |
484 | return Ok(()); | 424 | return Ok(()); |
@@ -488,7 +428,7 @@ fn on_notification( | |||
488 | let not = match notification_cast::<lsp_types::notification::DidOpenTextDocument>(not) { | 428 | let not = match notification_cast::<lsp_types::notification::DidOpenTextDocument>(not) { |
489 | Ok(params) => { | 429 | Ok(params) => { |
490 | if let Ok(path) = from_proto::vfs_path(¶ms.text_document.uri) { | 430 | if let Ok(path) = from_proto::vfs_path(¶ms.text_document.uri) { |
491 | if !loop_state.mem_docs.insert(path.clone()) { | 431 | if !global_state.mem_docs.insert(path.clone()) { |
492 | log::error!("duplicate DidOpenTextDocument: {}", path) | 432 | log::error!("duplicate DidOpenTextDocument: {}", path) |
493 | } | 433 | } |
494 | global_state | 434 | global_state |
@@ -504,7 +444,7 @@ fn on_notification( | |||
504 | let not = match notification_cast::<lsp_types::notification::DidChangeTextDocument>(not) { | 444 | let not = match notification_cast::<lsp_types::notification::DidChangeTextDocument>(not) { |
505 | Ok(params) => { | 445 | Ok(params) => { |
506 | if let Ok(path) = from_proto::vfs_path(¶ms.text_document.uri) { | 446 | if let Ok(path) = from_proto::vfs_path(¶ms.text_document.uri) { |
507 | assert!(loop_state.mem_docs.contains(&path)); | 447 | assert!(global_state.mem_docs.contains(&path)); |
508 | let vfs = &mut global_state.vfs.write().0; | 448 | let vfs = &mut global_state.vfs.write().0; |
509 | let file_id = vfs.file_id(&path).unwrap(); | 449 | let file_id = vfs.file_id(&path).unwrap(); |
510 | let mut text = String::from_utf8(vfs.file_contents(file_id).to_vec()).unwrap(); | 450 | let mut text = String::from_utf8(vfs.file_contents(file_id).to_vec()).unwrap(); |
@@ -518,7 +458,7 @@ fn on_notification( | |||
518 | let not = match notification_cast::<lsp_types::notification::DidCloseTextDocument>(not) { | 458 | let not = match notification_cast::<lsp_types::notification::DidCloseTextDocument>(not) { |
519 | Ok(params) => { | 459 | Ok(params) => { |
520 | if let Ok(path) = from_proto::vfs_path(¶ms.text_document.uri) { | 460 | if let Ok(path) = from_proto::vfs_path(¶ms.text_document.uri) { |
521 | if !loop_state.mem_docs.remove(&path) { | 461 | if !global_state.mem_docs.remove(&path) { |
522 | log::error!("orphan DidCloseTextDocument: {}", path) | 462 | log::error!("orphan DidCloseTextDocument: {}", path) |
523 | } | 463 | } |
524 | if let Some(path) = path.as_path() { | 464 | if let Some(path) = path.as_path() { |
@@ -549,7 +489,7 @@ fn on_notification( | |||
549 | Ok(_) => { | 489 | Ok(_) => { |
550 | // As stated in https://github.com/microsoft/language-server-protocol/issues/676, | 490 | // As stated in https://github.com/microsoft/language-server-protocol/issues/676, |
551 | // this notification's parameters should be ignored and the actual config queried separately. | 491 | // this notification's parameters should be ignored and the actual config queried separately. |
552 | let request = loop_state.req_queue.outgoing.register( | 492 | let request = global_state.req_queue.outgoing.register( |
553 | lsp_types::request::WorkspaceConfiguration::METHOD.to_string(), | 493 | lsp_types::request::WorkspaceConfiguration::METHOD.to_string(), |
554 | lsp_types::ConfigurationParams { | 494 | lsp_types::ConfigurationParams { |
555 | items: vec![lsp_types::ConfigurationItem { | 495 | items: vec![lsp_types::ConfigurationItem { |
@@ -732,7 +672,7 @@ fn on_diagnostic_task(task: DiagnosticTask, msg_sender: &Sender<Message>, state: | |||
732 | } | 672 | } |
733 | 673 | ||
734 | fn report_progress( | 674 | fn report_progress( |
735 | loop_state: &mut LoopState, | 675 | global_state: &mut GlobalState, |
736 | sender: &Sender<Message>, | 676 | sender: &Sender<Message>, |
737 | done: usize, | 677 | done: usize, |
738 | total: usize, | 678 | total: usize, |
@@ -742,7 +682,7 @@ fn report_progress( | |||
742 | let message = Some(format!("{}/{} {}", done, total, message)); | 682 | let message = Some(format!("{}/{} {}", done, total, message)); |
743 | let percentage = Some(100.0 * done as f64 / total.max(1) as f64); | 683 | let percentage = Some(100.0 * done as f64 / total.max(1) as f64); |
744 | let work_done_progress = if done == 0 { | 684 | let work_done_progress = if done == 0 { |
745 | let work_done_progress_create = loop_state.req_queue.outgoing.register( | 685 | let work_done_progress_create = global_state.req_queue.outgoing.register( |
746 | lsp_types::request::WorkDoneProgressCreate::METHOD.to_string(), | 686 | lsp_types::request::WorkDoneProgressCreate::METHOD.to_string(), |
747 | lsp_types::WorkDoneProgressCreateParams { token: token.clone() }, | 687 | lsp_types::WorkDoneProgressCreateParams { token: token.clone() }, |
748 | DO_NOTHING, | 688 | DO_NOTHING, |
@@ -777,7 +717,6 @@ struct PoolDispatcher<'a> { | |||
777 | req: Option<Request>, | 717 | req: Option<Request>, |
778 | pool: &'a ThreadPool, | 718 | pool: &'a ThreadPool, |
779 | global_state: &'a mut GlobalState, | 719 | global_state: &'a mut GlobalState, |
780 | incoming_requests: &'a mut Incoming, | ||
781 | msg_sender: &'a Sender<Message>, | 720 | msg_sender: &'a Sender<Message>, |
782 | task_sender: &'a Sender<Task>, | 721 | task_sender: &'a Sender<Task>, |
783 | request_received: Instant, | 722 | request_received: Instant, |
@@ -806,7 +745,7 @@ impl<'a> PoolDispatcher<'a> { | |||
806 | result_to_task::<R>(id, result) | 745 | result_to_task::<R>(id, result) |
807 | }) | 746 | }) |
808 | .map_err(|_| format!("sync task {:?} panicked", R::METHOD))?; | 747 | .map_err(|_| format!("sync task {:?} panicked", R::METHOD))?; |
809 | on_task(task, self.msg_sender, self.incoming_requests, self.global_state); | 748 | on_task(task, self.msg_sender, self.global_state); |
810 | Ok(self) | 749 | Ok(self) |
811 | } | 750 | } |
812 | 751 | ||
@@ -853,7 +792,10 @@ impl<'a> PoolDispatcher<'a> { | |||
853 | return None; | 792 | return None; |
854 | } | 793 | } |
855 | }; | 794 | }; |
856 | self.incoming_requests.register(id.clone(), (R::METHOD, self.request_received)); | 795 | self.global_state |
796 | .req_queue | ||
797 | .incoming | ||
798 | .register(id.clone(), (R::METHOD, self.request_received)); | ||
857 | Some((id, params)) | 799 | Some((id, params)) |
858 | } | 800 | } |
859 | 801 | ||
@@ -882,14 +824,7 @@ where | |||
882 | let response = match result { | 824 | let response = match result { |
883 | Ok(resp) => Response::new_ok(id, &resp), | 825 | Ok(resp) => Response::new_ok(id, &resp), |
884 | Err(e) => match e.downcast::<LspError>() { | 826 | Err(e) => match e.downcast::<LspError>() { |
885 | Ok(lsp_error) => { | 827 | Ok(lsp_error) => Response::new_err(id, lsp_error.code, lsp_error.message), |
886 | if lsp_error.code == LspError::UNKNOWN_FILE { | ||
887 | // Work-around for https://github.com/rust-analyzer/rust-analyzer/issues/1521 | ||
888 | Response::new_ok(id, ()) | ||
889 | } else { | ||
890 | Response::new_err(id, lsp_error.code, lsp_error.message) | ||
891 | } | ||
892 | } | ||
893 | Err(e) => { | 828 | Err(e) => { |
894 | if is_canceled(&e) { | 829 | if is_canceled(&e) { |
895 | Response::new_err( | 830 | Response::new_err( |
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs index 88d1c0d8a..f6cb8e4bb 100644 --- a/crates/rust-analyzer/src/to_proto.rs +++ b/crates/rust-analyzer/src/to_proto.rs | |||
@@ -440,7 +440,7 @@ pub(crate) fn location( | |||
440 | frange: FileRange, | 440 | frange: FileRange, |
441 | ) -> Result<lsp_types::Location> { | 441 | ) -> Result<lsp_types::Location> { |
442 | let url = url(snap, frange.file_id); | 442 | let url = url(snap, frange.file_id); |
443 | let line_index = snap.analysis().file_line_index(frange.file_id)?; | 443 | let line_index = snap.analysis.file_line_index(frange.file_id)?; |
444 | let range = range(&line_index, frange.range); | 444 | let range = range(&line_index, frange.range); |
445 | let loc = lsp_types::Location::new(url, range); | 445 | let loc = lsp_types::Location::new(url, range); |
446 | Ok(loc) | 446 | Ok(loc) |
@@ -453,7 +453,7 @@ pub(crate) fn location_link( | |||
453 | ) -> Result<lsp_types::LocationLink> { | 453 | ) -> Result<lsp_types::LocationLink> { |
454 | let origin_selection_range = match src { | 454 | let origin_selection_range = match src { |
455 | Some(src) => { | 455 | Some(src) => { |
456 | let line_index = snap.analysis().file_line_index(src.file_id)?; | 456 | let line_index = snap.analysis.file_line_index(src.file_id)?; |
457 | let range = range(&line_index, src.range); | 457 | let range = range(&line_index, src.range); |
458 | Some(range) | 458 | Some(range) |
459 | } | 459 | } |
@@ -473,7 +473,7 @@ fn location_info( | |||
473 | snap: &GlobalStateSnapshot, | 473 | snap: &GlobalStateSnapshot, |
474 | target: NavigationTarget, | 474 | target: NavigationTarget, |
475 | ) -> Result<(lsp_types::Url, lsp_types::Range, lsp_types::Range)> { | 475 | ) -> Result<(lsp_types::Url, lsp_types::Range, lsp_types::Range)> { |
476 | let line_index = snap.analysis().file_line_index(target.file_id())?; | 476 | let line_index = snap.analysis.file_line_index(target.file_id())?; |
477 | 477 | ||
478 | let target_uri = url(snap, target.file_id()); | 478 | let target_uri = url(snap, target.file_id()); |
479 | let target_range = range(&line_index, target.full_range()); | 479 | let target_range = range(&line_index, target.full_range()); |
@@ -516,7 +516,7 @@ pub(crate) fn snippet_text_document_edit( | |||
516 | source_file_edit: SourceFileEdit, | 516 | source_file_edit: SourceFileEdit, |
517 | ) -> Result<lsp_ext::SnippetTextDocumentEdit> { | 517 | ) -> Result<lsp_ext::SnippetTextDocumentEdit> { |
518 | let text_document = versioned_text_document_identifier(snap, source_file_edit.file_id, None); | 518 | let text_document = versioned_text_document_identifier(snap, source_file_edit.file_id, None); |
519 | let line_index = snap.analysis().file_line_index(source_file_edit.file_id)?; | 519 | let line_index = snap.analysis.file_line_index(source_file_edit.file_id)?; |
520 | let line_endings = snap.file_line_endings(source_file_edit.file_id); | 520 | let line_endings = snap.file_line_endings(source_file_edit.file_id); |
521 | let edits = source_file_edit | 521 | let edits = source_file_edit |
522 | .edit | 522 | .edit |