aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/rust-analyzer/src/cargo_target_spec.rs2
-rw-r--r--crates/rust-analyzer/src/from_proto.rs4
-rw-r--r--crates/rust-analyzer/src/global_state.rs55
-rw-r--r--crates/rust-analyzer/src/handlers.rs142
-rw-r--r--crates/rust-analyzer/src/lib.rs22
-rw-r--r--crates/rust-analyzer/src/main_loop.rs151
-rw-r--r--crates/rust-analyzer/src/to_proto.rs8
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};
27use rustc_hash::FxHashMap; 28use rustc_hash::{FxHashMap, FxHashSet};
28 29
29fn create_flycheck(workspaces: &[ProjectWorkspace], config: &FlycheckConfig) -> Option<Flycheck> { 30fn 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)]
45pub(crate) enum Status {
46 Loading,
47 Ready,
48}
49
50impl 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)]
49pub(crate) struct GlobalState { 61pub(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.
64pub(crate) struct GlobalStateSnapshot { 79pub(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
73impl GlobalState { 88impl 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
223impl GlobalStateSnapshot { 242impl 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, &params.text_document.uri)?; 58 let id = from_proto::file_id(&snap, &params.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, &params.text_document.uri)?; 70 let file_id = from_proto::file_id(&snap, &params.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, &params.text_document.uri)?; 83 let file_id = from_proto::file_id(&snap, &params.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, &params.text_document.uri)?; 126 let file_id = from_proto::file_id(&snap, &params.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, &params.text_document.uri)?; 148 let file_id = from_proto::file_id(&snap, &params.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, &params.text_document.uri)?; 227 let file_id = from_proto::file_id(&snap, &params.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, &params.text_document.uri)?; 395 let file_id = from_proto::file_id(&snap, &params.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, &params.text_document.uri)?; 496 let file_id = from_proto::file_id(&snap, &params.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, &params.text_document.uri)?; 632 let file_id = from_proto::file_id(&snap, &params.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, &params.text_document.uri)?; 708 let file_id = from_proto::file_id(&snap, &params.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, &params.text_document.uri)?; 754 let file_id = from_proto::file_id(&snap, &params.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, &params.code_action_params.text_document.uri)?; 782 let file_id = from_proto::file_id(&snap, &params.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(&params.id, ':').unwrap(); 788 let (id_string, index) = split_delim(&params.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, &params.text_document.uri)?; 807 let file_id = from_proto::file_id(&snap, &params.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(&params.query, params.parse_only)??; 946 snap.analysis.structural_search_replace(&params.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, &params.text_document.uri)?; 978 let file_id = from_proto::file_id(&snap, &params.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, &params.text_document.uri)?; 1086 let file_id = from_proto::file_id(&snap, &params.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;
37pub type Result<T, E = Box<dyn std::error::Error + Send + Sync>> = std::result::Result<T, E>; 37pub type Result<T, E = Box<dyn std::error::Error + Send + Sync>> = std::result::Result<T, E>;
38pub use crate::{ 38pub 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};
42use std::fmt;
43 43
44pub fn from_json<T: DeserializeOwned>(what: &'static str, json: serde_json::Value) -> Result<T> { 44pub 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)]
51struct LspError {
52 code: i32,
53 message: String,
54}
55
56impl LspError {
57 fn new(code: i32, message: String) -> LspError {
58 LspError { code, message }
59 }
60}
61
62impl 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
68impl 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.
3use std::{ 3use 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
13use crossbeam_channel::{never, select, unbounded, RecvError, Sender}; 11use crossbeam_channel::{never, select, unbounded, RecvError, Sender};
14use lsp_server::{ 12use lsp_server::{Connection, ErrorCode, Message, Notification, Request, RequestId, Response};
15 Connection, ErrorCode, Message, Notification, ReqQueue, Request, RequestId, Response,
16};
17use lsp_types::{request::Request as _, NumberOrString, TextDocumentContentChangeEvent}; 13use lsp_types::{request::Request as _, NumberOrString, TextDocumentContentChangeEvent};
18use ra_db::VfsPath; 14use ra_db::VfsPath;
19use ra_flycheck::CheckTask; 15use ra_flycheck::CheckTask;
20use ra_ide::{Canceled, FileId, LineIndex}; 16use ra_ide::{Canceled, FileId, LineIndex};
21use ra_prof::profile; 17use ra_prof::profile;
22use ra_project_model::{PackageRoot, ProjectWorkspace}; 18use ra_project_model::{PackageRoot, ProjectWorkspace};
23use rustc_hash::FxHashSet;
24use serde::{de::DeserializeOwned, Serialize}; 19use serde::{de::DeserializeOwned, Serialize};
25use threadpool::ThreadPool; 20use 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)]
38pub struct LspError {
39 pub code: i32,
40 pub message: String,
41}
42
43impl 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
51impl 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
57impl Error for LspError {}
58
59pub fn main_loop(config: Config, connection: Connection) -> Result<()> { 32pub 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
247type ReqHandler = fn(&mut GlobalState, Response); 219pub(crate) type ReqHandler = fn(&mut GlobalState, Response);
220pub(crate) type ReqQueue = lsp_server::ReqQueue<(&'static str, Instant), ReqHandler>;
248const DO_NOTHING: ReqHandler = |_, _| (); 221const DO_NOTHING: ReqHandler = |_, _| ();
249type Incoming = lsp_server::Incoming<(&'static str, Instant)>;
250
251#[derive(Default)]
252struct LoopState {
253 req_queue: ReqQueue<(&'static str, Instant), ReqHandler>,
254 mem_docs: FxHashSet<VfsPath>,
255 status: Status,
256}
257
258#[derive(Eq, PartialEq)]
259enum Status {
260 Loading,
261 Ready,
262}
263
264impl Default for Status {
265 fn default() -> Self {
266 Status::Loading
267 }
268}
269 222
270fn loop_turn( 223fn 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
376fn on_task( 322fn 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
402fn on_request( 345fn 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(
469fn on_notification( 410fn 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(&params.text_document.uri) { 430 if let Ok(path) = from_proto::vfs_path(&params.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(&params.text_document.uri) { 446 if let Ok(path) = from_proto::vfs_path(&params.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(&params.text_document.uri) { 460 if let Ok(path) = from_proto::vfs_path(&params.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
734fn report_progress( 674fn 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