aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/rust-analyzer/src/cargo_target_spec.rs4
-rw-r--r--crates/rust-analyzer/src/from_proto.rs8
-rw-r--r--crates/rust-analyzer/src/global_state.rs (renamed from crates/rust-analyzer/src/world.rs)18
-rw-r--r--crates/rust-analyzer/src/lib.rs2
-rw-r--r--crates/rust-analyzer/src/main_loop.rs88
-rw-r--r--crates/rust-analyzer/src/main_loop/handlers.rs357
-rw-r--r--crates/rust-analyzer/src/to_proto.rs87
7 files changed, 291 insertions, 273 deletions
diff --git a/crates/rust-analyzer/src/cargo_target_spec.rs b/crates/rust-analyzer/src/cargo_target_spec.rs
index 008518a08..44f856f6b 100644
--- a/crates/rust-analyzer/src/cargo_target_spec.rs
+++ b/crates/rust-analyzer/src/cargo_target_spec.rs
@@ -4,7 +4,7 @@ use ra_cfg::CfgExpr;
4use ra_ide::{FileId, RunnableKind, TestId}; 4use ra_ide::{FileId, RunnableKind, TestId};
5use ra_project_model::{self, ProjectWorkspace, TargetKind}; 5use ra_project_model::{self, ProjectWorkspace, TargetKind};
6 6
7use crate::{world::WorldSnapshot, Result}; 7use crate::{global_state::GlobalStateSnapshot, Result};
8 8
9/// Abstract representation of Cargo target. 9/// Abstract representation of Cargo target.
10/// 10///
@@ -89,7 +89,7 @@ impl CargoTargetSpec {
89 } 89 }
90 90
91 pub(crate) fn for_file( 91 pub(crate) fn for_file(
92 world: &WorldSnapshot, 92 world: &GlobalStateSnapshot,
93 file_id: FileId, 93 file_id: FileId,
94 ) -> Result<Option<CargoTargetSpec>> { 94 ) -> Result<Option<CargoTargetSpec>> {
95 let &crate_id = match world.analysis().crate_for(file_id)?.first() { 95 let &crate_id = match world.analysis().crate_for(file_id)?.first() {
diff --git a/crates/rust-analyzer/src/from_proto.rs b/crates/rust-analyzer/src/from_proto.rs
index 4bb16a496..206673829 100644
--- a/crates/rust-analyzer/src/from_proto.rs
+++ b/crates/rust-analyzer/src/from_proto.rs
@@ -3,7 +3,7 @@ use ra_db::{FileId, FilePosition, FileRange};
3use ra_ide::{LineCol, LineIndex}; 3use ra_ide::{LineCol, LineIndex};
4use ra_syntax::{TextRange, TextSize}; 4use ra_syntax::{TextRange, TextSize};
5 5
6use crate::{world::WorldSnapshot, Result}; 6use crate::{global_state::GlobalStateSnapshot, Result};
7 7
8pub(crate) fn offset(line_index: &LineIndex, position: lsp_types::Position) -> TextSize { 8pub(crate) fn offset(line_index: &LineIndex, position: lsp_types::Position) -> TextSize {
9 let line_col = LineCol { line: position.line as u32, col_utf16: position.character as u32 }; 9 let line_col = LineCol { line: position.line as u32, col_utf16: position.character as u32 };
@@ -16,12 +16,12 @@ pub(crate) fn text_range(line_index: &LineIndex, range: lsp_types::Range) -> Tex
16 TextRange::new(start, end) 16 TextRange::new(start, end)
17} 17}
18 18
19pub(crate) fn file_id(world: &WorldSnapshot, url: &lsp_types::Url) -> Result<FileId> { 19pub(crate) fn file_id(world: &GlobalStateSnapshot, url: &lsp_types::Url) -> Result<FileId> {
20 world.uri_to_file_id(url) 20 world.uri_to_file_id(url)
21} 21}
22 22
23pub(crate) fn file_position( 23pub(crate) fn file_position(
24 world: &WorldSnapshot, 24 world: &GlobalStateSnapshot,
25 tdpp: lsp_types::TextDocumentPositionParams, 25 tdpp: lsp_types::TextDocumentPositionParams,
26) -> Result<FilePosition> { 26) -> Result<FilePosition> {
27 let file_id = file_id(world, &tdpp.text_document.uri)?; 27 let file_id = file_id(world, &tdpp.text_document.uri)?;
@@ -31,7 +31,7 @@ pub(crate) fn file_position(
31} 31}
32 32
33pub(crate) fn file_range( 33pub(crate) fn file_range(
34 world: &WorldSnapshot, 34 world: &GlobalStateSnapshot,
35 text_document_identifier: lsp_types::TextDocumentIdentifier, 35 text_document_identifier: lsp_types::TextDocumentIdentifier,
36 range: lsp_types::Range, 36 range: lsp_types::Range,
37) -> Result<FileRange> { 37) -> Result<FileRange> {
diff --git a/crates/rust-analyzer/src/world.rs b/crates/rust-analyzer/src/global_state.rs
index c1010e86a..0bebb5bf6 100644
--- a/crates/rust-analyzer/src/world.rs
+++ b/crates/rust-analyzer/src/global_state.rs
@@ -50,13 +50,13 @@ fn create_flycheck(workspaces: &[ProjectWorkspace], config: &FlycheckConfig) ->
50 }) 50 })
51} 51}
52 52
53/// `WorldState` is the primary mutable state of the language server 53/// `GlobalState` is the primary mutable state of the language server
54/// 54///
55/// The most interesting components are `vfs`, which stores a consistent 55/// The most interesting components are `vfs`, which stores a consistent
56/// snapshot of the file systems, and `analysis_host`, which stores our 56/// snapshot of the file systems, and `analysis_host`, which stores our
57/// incremental salsa database. 57/// incremental salsa database.
58#[derive(Debug)] 58#[derive(Debug)]
59pub struct WorldState { 59pub struct GlobalState {
60 pub config: Config, 60 pub config: Config,
61 pub local_roots: Vec<PathBuf>, 61 pub local_roots: Vec<PathBuf>,
62 pub workspaces: Arc<Vec<ProjectWorkspace>>, 62 pub workspaces: Arc<Vec<ProjectWorkspace>>,
@@ -70,7 +70,7 @@ pub struct WorldState {
70} 70}
71 71
72/// An immutable snapshot of the world's state at a point in time. 72/// An immutable snapshot of the world's state at a point in time.
73pub struct WorldSnapshot { 73pub struct GlobalStateSnapshot {
74 pub config: Config, 74 pub config: Config,
75 pub workspaces: Arc<Vec<ProjectWorkspace>>, 75 pub workspaces: Arc<Vec<ProjectWorkspace>>,
76 pub analysis: Analysis, 76 pub analysis: Analysis,
@@ -79,14 +79,14 @@ pub struct WorldSnapshot {
79 vfs: Arc<RwLock<Vfs>>, 79 vfs: Arc<RwLock<Vfs>>,
80} 80}
81 81
82impl WorldState { 82impl GlobalState {
83 pub fn new( 83 pub fn new(
84 workspaces: Vec<ProjectWorkspace>, 84 workspaces: Vec<ProjectWorkspace>,
85 lru_capacity: Option<usize>, 85 lru_capacity: Option<usize>,
86 exclude_globs: &[Glob], 86 exclude_globs: &[Glob],
87 watch: Watch, 87 watch: Watch,
88 config: Config, 88 config: Config,
89 ) -> WorldState { 89 ) -> GlobalState {
90 let mut change = AnalysisChange::new(); 90 let mut change = AnalysisChange::new();
91 91
92 let extern_dirs: FxHashSet<_> = 92 let extern_dirs: FxHashSet<_> =
@@ -180,7 +180,7 @@ impl WorldState {
180 180
181 let mut analysis_host = AnalysisHost::new(lru_capacity); 181 let mut analysis_host = AnalysisHost::new(lru_capacity);
182 analysis_host.apply_change(change); 182 analysis_host.apply_change(change);
183 WorldState { 183 GlobalState {
184 config, 184 config,
185 local_roots, 185 local_roots,
186 workspaces: Arc::new(workspaces), 186 workspaces: Arc::new(workspaces),
@@ -255,8 +255,8 @@ impl WorldState {
255 self.analysis_host.apply_change(change); 255 self.analysis_host.apply_change(change);
256 } 256 }
257 257
258 pub fn snapshot(&self) -> WorldSnapshot { 258 pub fn snapshot(&self) -> GlobalStateSnapshot {
259 WorldSnapshot { 259 GlobalStateSnapshot {
260 config: self.config.clone(), 260 config: self.config.clone(),
261 workspaces: Arc::clone(&self.workspaces), 261 workspaces: Arc::clone(&self.workspaces),
262 analysis: self.analysis_host.analysis(), 262 analysis: self.analysis_host.analysis(),
@@ -279,7 +279,7 @@ impl WorldState {
279 } 279 }
280} 280}
281 281
282impl WorldSnapshot { 282impl GlobalStateSnapshot {
283 pub fn analysis(&self) -> &Analysis { 283 pub fn analysis(&self) -> &Analysis {
284 &self.analysis 284 &self.analysis
285 } 285 }
diff --git a/crates/rust-analyzer/src/lib.rs b/crates/rust-analyzer/src/lib.rs
index 57d0e9218..609cb69d3 100644
--- a/crates/rust-analyzer/src/lib.rs
+++ b/crates/rust-analyzer/src/lib.rs
@@ -26,7 +26,7 @@ mod main_loop;
26mod markdown; 26mod markdown;
27pub mod lsp_ext; 27pub mod lsp_ext;
28pub mod config; 28pub mod config;
29mod world; 29mod global_state;
30mod diagnostics; 30mod diagnostics;
31mod semantic_tokens; 31mod semantic_tokens;
32 32
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs
index 2e5499485..35f2d7001 100644
--- a/crates/rust-analyzer/src/main_loop.rs
+++ b/crates/rust-analyzer/src/main_loop.rs
@@ -38,12 +38,13 @@ use threadpool::ThreadPool;
38use crate::{ 38use crate::{
39 config::{Config, FilesWatcher}, 39 config::{Config, FilesWatcher},
40 diagnostics::{to_proto::url_from_path_with_drive_lowercasing, DiagnosticTask}, 40 diagnostics::{to_proto::url_from_path_with_drive_lowercasing, DiagnosticTask},
41 from_proto, lsp_ext, 41 from_proto,
42 global_state::{GlobalState, GlobalStateSnapshot},
43 lsp_ext,
42 main_loop::{ 44 main_loop::{
43 pending_requests::{PendingRequest, PendingRequests}, 45 pending_requests::{PendingRequest, PendingRequests},
44 subscriptions::Subscriptions, 46 subscriptions::Subscriptions,
45 }, 47 },
46 world::{WorldSnapshot, WorldState},
47 Result, 48 Result,
48}; 49};
49 50
@@ -92,7 +93,7 @@ pub fn main_loop(ws_roots: Vec<PathBuf>, config: Config, connection: Connection)
92 } 93 }
93 94
94 let mut loop_state = LoopState::default(); 95 let mut loop_state = LoopState::default();
95 let mut world_state = { 96 let mut global_state = {
96 let workspaces = { 97 let workspaces = {
97 // FIXME: support dynamic workspace loading. 98 // FIXME: support dynamic workspace loading.
98 let project_roots: FxHashSet<_> = ws_roots 99 let project_roots: FxHashSet<_> = ws_roots
@@ -163,7 +164,7 @@ pub fn main_loop(ws_roots: Vec<PathBuf>, config: Config, connection: Connection)
163 connection.sender.send(request.into()).unwrap(); 164 connection.sender.send(request.into()).unwrap();
164 } 165 }
165 166
166 WorldState::new( 167 GlobalState::new(
167 workspaces, 168 workspaces,
168 config.lru_capacity, 169 config.lru_capacity,
169 &globs, 170 &globs,
@@ -172,7 +173,7 @@ pub fn main_loop(ws_roots: Vec<PathBuf>, config: Config, connection: Connection)
172 ) 173 )
173 }; 174 };
174 175
175 loop_state.roots_total = world_state.vfs.read().n_roots(); 176 loop_state.roots_total = global_state.vfs.read().n_roots();
176 177
177 let pool = ThreadPool::default(); 178 let pool = ThreadPool::default();
178 let (task_sender, task_receiver) = unbounded::<Task>(); 179 let (task_sender, task_receiver) = unbounded::<Task>();
@@ -190,12 +191,12 @@ pub fn main_loop(ws_roots: Vec<PathBuf>, config: Config, connection: Connection)
190 Err(RecvError) => return Err("client exited without shutdown".into()), 191 Err(RecvError) => return Err("client exited without shutdown".into()),
191 }, 192 },
192 recv(task_receiver) -> task => Event::Task(task.unwrap()), 193 recv(task_receiver) -> task => Event::Task(task.unwrap()),
193 recv(world_state.task_receiver) -> task => match task { 194 recv(global_state.task_receiver) -> task => match task {
194 Ok(task) => Event::Vfs(task), 195 Ok(task) => Event::Vfs(task),
195 Err(RecvError) => return Err("vfs died".into()), 196 Err(RecvError) => return Err("vfs died".into()),
196 }, 197 },
197 recv(libdata_receiver) -> data => Event::Lib(data.unwrap()), 198 recv(libdata_receiver) -> data => Event::Lib(data.unwrap()),
198 recv(world_state.flycheck.as_ref().map_or(&never(), |it| &it.task_recv)) -> task => match task { 199 recv(global_state.flycheck.as_ref().map_or(&never(), |it| &it.task_recv)) -> task => match task {
199 Ok(task) => Event::CheckWatcher(task), 200 Ok(task) => Event::CheckWatcher(task),
200 Err(RecvError) => return Err("check watcher died".into()), 201 Err(RecvError) => return Err("check watcher died".into()),
201 } 202 }
@@ -210,16 +211,16 @@ pub fn main_loop(ws_roots: Vec<PathBuf>, config: Config, connection: Connection)
210 &task_sender, 211 &task_sender,
211 &libdata_sender, 212 &libdata_sender,
212 &connection, 213 &connection,
213 &mut world_state, 214 &mut global_state,
214 &mut loop_state, 215 &mut loop_state,
215 event, 216 event,
216 )?; 217 )?;
217 } 218 }
218 } 219 }
219 world_state.analysis_host.request_cancellation(); 220 global_state.analysis_host.request_cancellation();
220 log::info!("waiting for tasks to finish..."); 221 log::info!("waiting for tasks to finish...");
221 task_receiver.into_iter().for_each(|task| { 222 task_receiver.into_iter().for_each(|task| {
222 on_task(task, &connection.sender, &mut loop_state.pending_requests, &mut world_state) 223 on_task(task, &connection.sender, &mut loop_state.pending_requests, &mut global_state)
223 }); 224 });
224 libdata_receiver.into_iter().for_each(drop); 225 libdata_receiver.into_iter().for_each(drop);
225 log::info!("...tasks have finished"); 226 log::info!("...tasks have finished");
@@ -228,7 +229,7 @@ pub fn main_loop(ws_roots: Vec<PathBuf>, config: Config, connection: Connection)
228 drop(pool); 229 drop(pool);
229 log::info!("...threadpool has finished"); 230 log::info!("...threadpool has finished");
230 231
231 let vfs = Arc::try_unwrap(world_state.vfs).expect("all snapshots should be dead"); 232 let vfs = Arc::try_unwrap(global_state.vfs).expect("all snapshots should be dead");
232 drop(vfs); 233 drop(vfs);
233 234
234 Ok(()) 235 Ok(())
@@ -319,7 +320,7 @@ fn loop_turn(
319 task_sender: &Sender<Task>, 320 task_sender: &Sender<Task>,
320 libdata_sender: &Sender<LibraryData>, 321 libdata_sender: &Sender<LibraryData>,
321 connection: &Connection, 322 connection: &Connection,
322 world_state: &mut WorldState, 323 global_state: &mut GlobalState,
323 loop_state: &mut LoopState, 324 loop_state: &mut LoopState,
324 event: Event, 325 event: Event,
325) -> Result<()> { 326) -> Result<()> {
@@ -335,22 +336,22 @@ fn loop_turn(
335 336
336 match event { 337 match event {
337 Event::Task(task) => { 338 Event::Task(task) => {
338 on_task(task, &connection.sender, &mut loop_state.pending_requests, world_state); 339 on_task(task, &connection.sender, &mut loop_state.pending_requests, global_state);
339 world_state.maybe_collect_garbage(); 340 global_state.maybe_collect_garbage();
340 } 341 }
341 Event::Vfs(task) => { 342 Event::Vfs(task) => {
342 world_state.vfs.write().handle_task(task); 343 global_state.vfs.write().handle_task(task);
343 } 344 }
344 Event::Lib(lib) => { 345 Event::Lib(lib) => {
345 world_state.add_lib(lib); 346 global_state.add_lib(lib);
346 world_state.maybe_collect_garbage(); 347 global_state.maybe_collect_garbage();
347 loop_state.in_flight_libraries -= 1; 348 loop_state.in_flight_libraries -= 1;
348 loop_state.roots_scanned += 1; 349 loop_state.roots_scanned += 1;
349 } 350 }
350 Event::CheckWatcher(task) => on_check_task(task, world_state, task_sender)?, 351 Event::CheckWatcher(task) => on_check_task(task, global_state, task_sender)?,
351 Event::Msg(msg) => match msg { 352 Event::Msg(msg) => match msg {
352 Message::Request(req) => on_request( 353 Message::Request(req) => on_request(
353 world_state, 354 global_state,
354 &mut loop_state.pending_requests, 355 &mut loop_state.pending_requests,
355 pool, 356 pool,
356 task_sender, 357 task_sender,
@@ -359,7 +360,7 @@ fn loop_turn(
359 req, 360 req,
360 )?, 361 )?,
361 Message::Notification(not) => { 362 Message::Notification(not) => {
362 on_notification(&connection.sender, world_state, loop_state, not)?; 363 on_notification(&connection.sender, global_state, loop_state, not)?;
363 } 364 }
364 Message::Response(resp) => { 365 Message::Response(resp) => {
365 let removed = loop_state.pending_responses.remove(&resp.id); 366 let removed = loop_state.pending_responses.remove(&resp.id);
@@ -378,9 +379,9 @@ fn loop_turn(
378 } 379 }
379 (None, Some(configs)) => { 380 (None, Some(configs)) => {
380 if let Some(new_config) = configs.get(0) { 381 if let Some(new_config) = configs.get(0) {
381 let mut config = world_state.config.clone(); 382 let mut config = global_state.config.clone();
382 config.update(&new_config); 383 config.update(&new_config);
383 world_state.update_configuration(config); 384 global_state.update_configuration(config);
384 } 385 }
385 } 386 }
386 (None, None) => { 387 (None, None) => {
@@ -393,7 +394,7 @@ fn loop_turn(
393 }; 394 };
394 395
395 let mut state_changed = false; 396 let mut state_changed = false;
396 if let Some(changes) = world_state.process_changes(&mut loop_state.roots_scanned) { 397 if let Some(changes) = global_state.process_changes(&mut loop_state.roots_scanned) {
397 state_changed = true; 398 state_changed = true;
398 loop_state.pending_libraries.extend(changes); 399 loop_state.pending_libraries.extend(changes);
399 } 400 }
@@ -415,7 +416,7 @@ fn loop_turn(
415 } 416 }
416 417
417 let show_progress = 418 let show_progress =
418 !loop_state.workspace_loaded && world_state.config.client_caps.work_done_progress; 419 !loop_state.workspace_loaded && global_state.config.client_caps.work_done_progress;
419 420
420 if !loop_state.workspace_loaded 421 if !loop_state.workspace_loaded
421 && loop_state.roots_scanned == loop_state.roots_total 422 && loop_state.roots_scanned == loop_state.roots_total
@@ -424,7 +425,7 @@ fn loop_turn(
424 { 425 {
425 state_changed = true; 426 state_changed = true;
426 loop_state.workspace_loaded = true; 427 loop_state.workspace_loaded = true;
427 if let Some(flycheck) = &world_state.flycheck { 428 if let Some(flycheck) = &global_state.flycheck {
428 flycheck.update(); 429 flycheck.update();
429 } 430 }
430 } 431 }
@@ -436,13 +437,13 @@ fn loop_turn(
436 if state_changed && loop_state.workspace_loaded { 437 if state_changed && loop_state.workspace_loaded {
437 update_file_notifications_on_threadpool( 438 update_file_notifications_on_threadpool(
438 pool, 439 pool,
439 world_state.snapshot(), 440 global_state.snapshot(),
440 task_sender.clone(), 441 task_sender.clone(),
441 loop_state.subscriptions.subscriptions(), 442 loop_state.subscriptions.subscriptions(),
442 ); 443 );
443 pool.execute({ 444 pool.execute({
444 let subs = loop_state.subscriptions.subscriptions(); 445 let subs = loop_state.subscriptions.subscriptions();
445 let snap = world_state.snapshot(); 446 let snap = global_state.snapshot();
446 move || snap.analysis().prime_caches(subs).unwrap_or_else(|_: Canceled| ()) 447 move || snap.analysis().prime_caches(subs).unwrap_or_else(|_: Canceled| ())
447 }); 448 });
448 } 449 }
@@ -466,7 +467,7 @@ fn on_task(
466 task: Task, 467 task: Task,
467 msg_sender: &Sender<Message>, 468 msg_sender: &Sender<Message>,
468 pending_requests: &mut PendingRequests, 469 pending_requests: &mut PendingRequests,
469 state: &mut WorldState, 470 state: &mut GlobalState,
470) { 471) {
471 match task { 472 match task {
472 Task::Respond(response) => { 473 Task::Respond(response) => {
@@ -484,7 +485,7 @@ fn on_task(
484} 485}
485 486
486fn on_request( 487fn on_request(
487 world: &mut WorldState, 488 global_state: &mut GlobalState,
488 pending_requests: &mut PendingRequests, 489 pending_requests: &mut PendingRequests,
489 pool: &ThreadPool, 490 pool: &ThreadPool,
490 task_sender: &Sender<Task>, 491 task_sender: &Sender<Task>,
@@ -495,7 +496,7 @@ fn on_request(
495 let mut pool_dispatcher = PoolDispatcher { 496 let mut pool_dispatcher = PoolDispatcher {
496 req: Some(req), 497 req: Some(req),
497 pool, 498 pool,
498 world, 499 global_state,
499 task_sender, 500 task_sender,
500 msg_sender, 501 msg_sender,
501 pending_requests, 502 pending_requests,
@@ -551,7 +552,7 @@ fn on_request(
551 552
552fn on_notification( 553fn on_notification(
553 msg_sender: &Sender<Message>, 554 msg_sender: &Sender<Message>,
554 state: &mut WorldState, 555 state: &mut GlobalState,
555 loop_state: &mut LoopState, 556 loop_state: &mut LoopState,
556 not: Notification, 557 not: Notification,
557) -> Result<()> { 558) -> Result<()> {
@@ -725,7 +726,7 @@ fn apply_document_changes(
725 726
726fn on_check_task( 727fn on_check_task(
727 task: CheckTask, 728 task: CheckTask,
728 world_state: &mut WorldState, 729 global_state: &mut GlobalState,
729 task_sender: &Sender<Task>, 730 task_sender: &Sender<Task>,
730) -> Result<()> { 731) -> Result<()> {
731 match task { 732 match task {
@@ -744,7 +745,7 @@ fn on_check_task(
744 .uri 745 .uri
745 .to_file_path() 746 .to_file_path()
746 .map_err(|()| format!("invalid uri: {}", diag.location.uri))?; 747 .map_err(|()| format!("invalid uri: {}", diag.location.uri))?;
747 let file_id = match world_state.vfs.read().path2file(&path) { 748 let file_id = match global_state.vfs.read().path2file(&path) {
748 Some(file) => FileId(file.0), 749 Some(file) => FileId(file.0),
749 None => { 750 None => {
750 log::error!( 751 log::error!(
@@ -764,7 +765,7 @@ fn on_check_task(
764 } 765 }
765 766
766 CheckTask::Status(status) => { 767 CheckTask::Status(status) => {
767 if world_state.config.client_caps.work_done_progress { 768 if global_state.config.client_caps.work_done_progress {
768 let progress = match status { 769 let progress = match status {
769 Status::Being => { 770 Status::Being => {
770 lsp_types::WorkDoneProgress::Begin(lsp_types::WorkDoneProgressBegin { 771 lsp_types::WorkDoneProgress::Begin(lsp_types::WorkDoneProgressBegin {
@@ -803,7 +804,7 @@ fn on_check_task(
803 Ok(()) 804 Ok(())
804} 805}
805 806
806fn on_diagnostic_task(task: DiagnosticTask, msg_sender: &Sender<Message>, state: &mut WorldState) { 807fn on_diagnostic_task(task: DiagnosticTask, msg_sender: &Sender<Message>, state: &mut GlobalState) {
807 let subscriptions = state.diagnostics.handle_task(task); 808 let subscriptions = state.diagnostics.handle_task(task);
808 809
809 for file_id in subscriptions { 810 for file_id in subscriptions {
@@ -878,7 +879,7 @@ fn send_startup_progress(sender: &Sender<Message>, loop_state: &mut LoopState) {
878struct PoolDispatcher<'a> { 879struct PoolDispatcher<'a> {
879 req: Option<Request>, 880 req: Option<Request>,
880 pool: &'a ThreadPool, 881 pool: &'a ThreadPool,
881 world: &'a mut WorldState, 882 global_state: &'a mut GlobalState,
882 pending_requests: &'a mut PendingRequests, 883 pending_requests: &'a mut PendingRequests,
883 msg_sender: &'a Sender<Message>, 884 msg_sender: &'a Sender<Message>,
884 task_sender: &'a Sender<Task>, 885 task_sender: &'a Sender<Task>,
@@ -889,7 +890,7 @@ impl<'a> PoolDispatcher<'a> {
889 /// Dispatches the request onto the current thread 890 /// Dispatches the request onto the current thread
890 fn on_sync<R>( 891 fn on_sync<R>(
891 &mut self, 892 &mut self,
892 f: fn(&mut WorldState, R::Params) -> Result<R::Result>, 893 f: fn(&mut GlobalState, R::Params) -> Result<R::Result>,
893 ) -> Result<&mut Self> 894 ) -> Result<&mut Self>
894 where 895 where
895 R: lsp_types::request::Request + 'static, 896 R: lsp_types::request::Request + 'static,
@@ -902,18 +903,21 @@ impl<'a> PoolDispatcher<'a> {
902 return Ok(self); 903 return Ok(self);
903 } 904 }
904 }; 905 };
905 let world = panic::AssertUnwindSafe(&mut *self.world); 906 let world = panic::AssertUnwindSafe(&mut *self.global_state);
906 let task = panic::catch_unwind(move || { 907 let task = panic::catch_unwind(move || {
907 let result = f(world.0, params); 908 let result = f(world.0, params);
908 result_to_task::<R>(id, result) 909 result_to_task::<R>(id, result)
909 }) 910 })
910 .map_err(|_| format!("sync task {:?} panicked", R::METHOD))?; 911 .map_err(|_| format!("sync task {:?} panicked", R::METHOD))?;
911 on_task(task, self.msg_sender, self.pending_requests, self.world); 912 on_task(task, self.msg_sender, self.pending_requests, self.global_state);
912 Ok(self) 913 Ok(self)
913 } 914 }
914 915
915 /// Dispatches the request onto thread pool 916 /// Dispatches the request onto thread pool
916 fn on<R>(&mut self, f: fn(WorldSnapshot, R::Params) -> Result<R::Result>) -> Result<&mut Self> 917 fn on<R>(
918 &mut self,
919 f: fn(GlobalStateSnapshot, R::Params) -> Result<R::Result>,
920 ) -> Result<&mut Self>
917 where 921 where
918 R: lsp_types::request::Request + 'static, 922 R: lsp_types::request::Request + 'static,
919 R::Params: DeserializeOwned + Send + 'static, 923 R::Params: DeserializeOwned + Send + 'static,
@@ -927,7 +931,7 @@ impl<'a> PoolDispatcher<'a> {
927 }; 931 };
928 932
929 self.pool.execute({ 933 self.pool.execute({
930 let world = self.world.snapshot(); 934 let world = self.global_state.snapshot();
931 let sender = self.task_sender.clone(); 935 let sender = self.task_sender.clone();
932 move || { 936 move || {
933 let result = f(world, params); 937 let result = f(world, params);
@@ -1011,7 +1015,7 @@ where
1011 1015
1012fn update_file_notifications_on_threadpool( 1016fn update_file_notifications_on_threadpool(
1013 pool: &ThreadPool, 1017 pool: &ThreadPool,
1014 world: WorldSnapshot, 1018 world: GlobalStateSnapshot,
1015 task_sender: Sender<Task>, 1019 task_sender: Sender<Task>,
1016 subscriptions: Vec<FileId>, 1020 subscriptions: Vec<FileId>,
1017) { 1021) {
diff --git a/crates/rust-analyzer/src/main_loop/handlers.rs b/crates/rust-analyzer/src/main_loop/handlers.rs
index 7fd691764..1bb8e4473 100644
--- a/crates/rust-analyzer/src/main_loop/handlers.rs
+++ b/crates/rust-analyzer/src/main_loop/handlers.rs
@@ -32,17 +32,16 @@ use crate::{
32 config::RustfmtConfig, 32 config::RustfmtConfig,
33 diagnostics::DiagnosticTask, 33 diagnostics::DiagnosticTask,
34 from_json, from_proto, 34 from_json, from_proto,
35 global_state::GlobalStateSnapshot,
35 lsp_ext::{self, InlayHint, InlayHintsParams}, 36 lsp_ext::{self, InlayHint, InlayHintsParams},
36 to_proto, 37 to_proto, LspError, Result,
37 world::WorldSnapshot,
38 LspError, Result,
39}; 38};
40 39
41pub fn handle_analyzer_status(world: WorldSnapshot, _: ()) -> Result<String> { 40pub fn handle_analyzer_status(snap: GlobalStateSnapshot, _: ()) -> Result<String> {
42 let _p = profile("handle_analyzer_status"); 41 let _p = profile("handle_analyzer_status");
43 let mut buf = world.status(); 42 let mut buf = snap.status();
44 format_to!(buf, "\n\nrequests:\n"); 43 format_to!(buf, "\n\nrequests:\n");
45 let requests = world.latest_requests.read(); 44 let requests = snap.latest_requests.read();
46 for (is_last, r) in requests.iter() { 45 for (is_last, r) in requests.iter() {
47 let mark = if is_last { "*" } else { " " }; 46 let mark = if is_last { "*" } else { " " };
48 format_to!(buf, "{}{:4} {:<36}{}ms\n", mark, r.id, r.method, r.duration.as_millis()); 47 format_to!(buf, "{}{:4} {:<36}{}ms\n", mark, r.id, r.method, r.duration.as_millis());
@@ -51,37 +50,37 @@ pub fn handle_analyzer_status(world: WorldSnapshot, _: ()) -> Result<String> {
51} 50}
52 51
53pub fn handle_syntax_tree( 52pub fn handle_syntax_tree(
54 world: WorldSnapshot, 53 snap: GlobalStateSnapshot,
55 params: lsp_ext::SyntaxTreeParams, 54 params: lsp_ext::SyntaxTreeParams,
56) -> Result<String> { 55) -> Result<String> {
57 let _p = profile("handle_syntax_tree"); 56 let _p = profile("handle_syntax_tree");
58 let id = from_proto::file_id(&world, &params.text_document.uri)?; 57 let id = from_proto::file_id(&snap, &params.text_document.uri)?;
59 let line_index = world.analysis().file_line_index(id)?; 58 let line_index = snap.analysis().file_line_index(id)?;
60 let text_range = params.range.map(|r| from_proto::text_range(&line_index, r)); 59 let text_range = params.range.map(|r| from_proto::text_range(&line_index, r));
61 let res = world.analysis().syntax_tree(id, text_range)?; 60 let res = snap.analysis().syntax_tree(id, text_range)?;
62 Ok(res) 61 Ok(res)
63} 62}
64 63
65pub fn handle_expand_macro( 64pub fn handle_expand_macro(
66 world: WorldSnapshot, 65 snap: GlobalStateSnapshot,
67 params: lsp_ext::ExpandMacroParams, 66 params: lsp_ext::ExpandMacroParams,
68) -> Result<Option<lsp_ext::ExpandedMacro>> { 67) -> Result<Option<lsp_ext::ExpandedMacro>> {
69 let _p = profile("handle_expand_macro"); 68 let _p = profile("handle_expand_macro");
70 let file_id = from_proto::file_id(&world, &params.text_document.uri)?; 69 let file_id = from_proto::file_id(&snap, &params.text_document.uri)?;
71 let line_index = world.analysis().file_line_index(file_id)?; 70 let line_index = snap.analysis().file_line_index(file_id)?;
72 let offset = from_proto::offset(&line_index, params.position); 71 let offset = from_proto::offset(&line_index, params.position);
73 72
74 let res = world.analysis().expand_macro(FilePosition { file_id, offset })?; 73 let res = snap.analysis().expand_macro(FilePosition { file_id, offset })?;
75 Ok(res.map(|it| lsp_ext::ExpandedMacro { name: it.name, expansion: it.expansion })) 74 Ok(res.map(|it| lsp_ext::ExpandedMacro { name: it.name, expansion: it.expansion }))
76} 75}
77 76
78pub fn handle_selection_range( 77pub fn handle_selection_range(
79 world: WorldSnapshot, 78 snap: GlobalStateSnapshot,
80 params: lsp_types::SelectionRangeParams, 79 params: lsp_types::SelectionRangeParams,
81) -> Result<Option<Vec<lsp_types::SelectionRange>>> { 80) -> Result<Option<Vec<lsp_types::SelectionRange>>> {
82 let _p = profile("handle_selection_range"); 81 let _p = profile("handle_selection_range");
83 let file_id = from_proto::file_id(&world, &params.text_document.uri)?; 82 let file_id = from_proto::file_id(&snap, &params.text_document.uri)?;
84 let line_index = world.analysis().file_line_index(file_id)?; 83 let line_index = snap.analysis().file_line_index(file_id)?;
85 let res: Result<Vec<lsp_types::SelectionRange>> = params 84 let res: Result<Vec<lsp_types::SelectionRange>> = params
86 .positions 85 .positions
87 .into_iter() 86 .into_iter()
@@ -93,7 +92,7 @@ pub fn handle_selection_range(
93 loop { 92 loop {
94 ranges.push(range); 93 ranges.push(range);
95 let frange = FileRange { file_id, range }; 94 let frange = FileRange { file_id, range };
96 let next = world.analysis().extend_selection(frange)?; 95 let next = snap.analysis().extend_selection(frange)?;
97 if next == range { 96 if next == range {
98 break; 97 break;
99 } else { 98 } else {
@@ -119,18 +118,18 @@ pub fn handle_selection_range(
119} 118}
120 119
121pub fn handle_matching_brace( 120pub fn handle_matching_brace(
122 world: WorldSnapshot, 121 snap: GlobalStateSnapshot,
123 params: lsp_ext::MatchingBraceParams, 122 params: lsp_ext::MatchingBraceParams,
124) -> Result<Vec<Position>> { 123) -> Result<Vec<Position>> {
125 let _p = profile("handle_matching_brace"); 124 let _p = profile("handle_matching_brace");
126 let file_id = from_proto::file_id(&world, &params.text_document.uri)?; 125 let file_id = from_proto::file_id(&snap, &params.text_document.uri)?;
127 let line_index = world.analysis().file_line_index(file_id)?; 126 let line_index = snap.analysis().file_line_index(file_id)?;
128 let res = params 127 let res = params
129 .positions 128 .positions
130 .into_iter() 129 .into_iter()
131 .map(|position| { 130 .map(|position| {
132 let offset = from_proto::offset(&line_index, position); 131 let offset = from_proto::offset(&line_index, position);
133 let offset = match world.analysis().matching_brace(FilePosition { file_id, offset }) { 132 let offset = match snap.analysis().matching_brace(FilePosition { file_id, offset }) {
134 Ok(Some(matching_brace_offset)) => matching_brace_offset, 133 Ok(Some(matching_brace_offset)) => matching_brace_offset,
135 Err(_) | Ok(None) => offset, 134 Err(_) | Ok(None) => offset,
136 }; 135 };
@@ -141,17 +140,17 @@ pub fn handle_matching_brace(
141} 140}
142 141
143pub fn handle_join_lines( 142pub fn handle_join_lines(
144 world: WorldSnapshot, 143 snap: GlobalStateSnapshot,
145 params: lsp_ext::JoinLinesParams, 144 params: lsp_ext::JoinLinesParams,
146) -> Result<Vec<lsp_types::TextEdit>> { 145) -> Result<Vec<lsp_types::TextEdit>> {
147 let _p = profile("handle_join_lines"); 146 let _p = profile("handle_join_lines");
148 let file_id = from_proto::file_id(&world, &params.text_document.uri)?; 147 let file_id = from_proto::file_id(&snap, &params.text_document.uri)?;
149 let line_index = world.analysis().file_line_index(file_id)?; 148 let line_index = snap.analysis().file_line_index(file_id)?;
150 let line_endings = world.file_line_endings(file_id); 149 let line_endings = snap.file_line_endings(file_id);
151 let mut res = TextEdit::default(); 150 let mut res = TextEdit::default();
152 for range in params.ranges { 151 for range in params.ranges {
153 let range = from_proto::text_range(&line_index, range); 152 let range = from_proto::text_range(&line_index, range);
154 let edit = world.analysis().join_lines(FileRange { file_id, range })?; 153 let edit = snap.analysis().join_lines(FileRange { file_id, range })?;
155 match res.union(edit) { 154 match res.union(edit) {
156 Ok(()) => (), 155 Ok(()) => (),
157 Err(_edit) => { 156 Err(_edit) => {
@@ -164,37 +163,37 @@ pub fn handle_join_lines(
164} 163}
165 164
166pub fn handle_on_enter( 165pub fn handle_on_enter(
167 world: WorldSnapshot, 166 snap: GlobalStateSnapshot,
168 params: lsp_types::TextDocumentPositionParams, 167 params: lsp_types::TextDocumentPositionParams,
169) -> Result<Option<Vec<lsp_ext::SnippetTextEdit>>> { 168) -> Result<Option<Vec<lsp_ext::SnippetTextEdit>>> {
170 let _p = profile("handle_on_enter"); 169 let _p = profile("handle_on_enter");
171 let position = from_proto::file_position(&world, params)?; 170 let position = from_proto::file_position(&snap, params)?;
172 let edit = match world.analysis().on_enter(position)? { 171 let edit = match snap.analysis().on_enter(position)? {
173 None => return Ok(None), 172 None => return Ok(None),
174 Some(it) => it, 173 Some(it) => it,
175 }; 174 };
176 let line_index = world.analysis().file_line_index(position.file_id)?; 175 let line_index = snap.analysis().file_line_index(position.file_id)?;
177 let line_endings = world.file_line_endings(position.file_id); 176 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); 177 let edit = to_proto::snippet_text_edit_vec(&line_index, line_endings, true, edit);
179 Ok(Some(edit)) 178 Ok(Some(edit))
180} 179}
181 180
182// Don't forget to add new trigger characters to `ServerCapabilities` in `caps.rs`. 181// Don't forget to add new trigger characters to `ServerCapabilities` in `caps.rs`.
183pub fn handle_on_type_formatting( 182pub fn handle_on_type_formatting(
184 world: WorldSnapshot, 183 snap: GlobalStateSnapshot,
185 params: lsp_types::DocumentOnTypeFormattingParams, 184 params: lsp_types::DocumentOnTypeFormattingParams,
186) -> Result<Option<Vec<lsp_types::TextEdit>>> { 185) -> Result<Option<Vec<lsp_types::TextEdit>>> {
187 let _p = profile("handle_on_type_formatting"); 186 let _p = profile("handle_on_type_formatting");
188 let mut position = from_proto::file_position(&world, params.text_document_position)?; 187 let mut position = from_proto::file_position(&snap, params.text_document_position)?;
189 let line_index = world.analysis().file_line_index(position.file_id)?; 188 let line_index = snap.analysis().file_line_index(position.file_id)?;
190 let line_endings = world.file_line_endings(position.file_id); 189 let line_endings = snap.file_line_endings(position.file_id);
191 190
192 // in `ra_ide`, the `on_type` invariant is that 191 // in `ra_ide`, the `on_type` invariant is that
193 // `text.char_at(position) == typed_char`. 192 // `text.char_at(position) == typed_char`.
194 position.offset -= TextSize::of('.'); 193 position.offset -= TextSize::of('.');
195 let char_typed = params.ch.chars().next().unwrap_or('\0'); 194 let char_typed = params.ch.chars().next().unwrap_or('\0');
196 assert!({ 195 assert!({
197 let text = world.analysis().file_text(position.file_id)?; 196 let text = snap.analysis().file_text(position.file_id)?;
198 text[usize::from(position.offset)..].starts_with(char_typed) 197 text[usize::from(position.offset)..].starts_with(char_typed)
199 }); 198 });
200 199
@@ -206,7 +205,7 @@ pub fn handle_on_type_formatting(
206 return Ok(None); 205 return Ok(None);
207 } 206 }
208 207
209 let edit = world.analysis().on_char_typed(position, char_typed)?; 208 let edit = snap.analysis().on_char_typed(position, char_typed)?;
210 let mut edit = match edit { 209 let mut edit = match edit {
211 Some(it) => it, 210 Some(it) => it,
212 None => return Ok(None), 211 None => return Ok(None),
@@ -220,16 +219,16 @@ pub fn handle_on_type_formatting(
220} 219}
221 220
222pub fn handle_document_symbol( 221pub fn handle_document_symbol(
223 world: WorldSnapshot, 222 snap: GlobalStateSnapshot,
224 params: lsp_types::DocumentSymbolParams, 223 params: lsp_types::DocumentSymbolParams,
225) -> Result<Option<lsp_types::DocumentSymbolResponse>> { 224) -> Result<Option<lsp_types::DocumentSymbolResponse>> {
226 let _p = profile("handle_document_symbol"); 225 let _p = profile("handle_document_symbol");
227 let file_id = from_proto::file_id(&world, &params.text_document.uri)?; 226 let file_id = from_proto::file_id(&snap, &params.text_document.uri)?;
228 let line_index = world.analysis().file_line_index(file_id)?; 227 let line_index = snap.analysis().file_line_index(file_id)?;
229 228
230 let mut parents: Vec<(DocumentSymbol, Option<usize>)> = Vec::new(); 229 let mut parents: Vec<(DocumentSymbol, Option<usize>)> = Vec::new();
231 230
232 for symbol in world.analysis().file_structure(file_id)? { 231 for symbol in snap.analysis().file_structure(file_id)? {
233 let doc_symbol = DocumentSymbol { 232 let doc_symbol = DocumentSymbol {
234 name: symbol.label, 233 name: symbol.label,
235 detail: symbol.detail, 234 detail: symbol.detail,
@@ -255,10 +254,10 @@ pub fn handle_document_symbol(
255 } 254 }
256 } 255 }
257 256
258 let res = if world.config.client_caps.hierarchical_symbols { 257 let res = if snap.config.client_caps.hierarchical_symbols {
259 document_symbols.into() 258 document_symbols.into()
260 } else { 259 } else {
261 let url = to_proto::url(&world, file_id)?; 260 let url = to_proto::url(&snap, file_id)?;
262 let mut symbol_information = Vec::<SymbolInformation>::new(); 261 let mut symbol_information = Vec::<SymbolInformation>::new();
263 for symbol in document_symbols { 262 for symbol in document_symbols {
264 flatten_document_symbol(&symbol, None, &url, &mut symbol_information); 263 flatten_document_symbol(&symbol, None, &url, &mut symbol_information);
@@ -288,7 +287,7 @@ pub fn handle_document_symbol(
288} 287}
289 288
290pub fn handle_workspace_symbol( 289pub fn handle_workspace_symbol(
291 world: WorldSnapshot, 290 snap: GlobalStateSnapshot,
292 params: lsp_types::WorkspaceSymbolParams, 291 params: lsp_types::WorkspaceSymbolParams,
293) -> Result<Option<Vec<SymbolInformation>>> { 292) -> Result<Option<Vec<SymbolInformation>>> {
294 let _p = profile("handle_workspace_symbol"); 293 let _p = profile("handle_workspace_symbol");
@@ -306,22 +305,22 @@ pub fn handle_workspace_symbol(
306 q.limit(128); 305 q.limit(128);
307 q 306 q
308 }; 307 };
309 let mut res = exec_query(&world, query)?; 308 let mut res = exec_query(&snap, query)?;
310 if res.is_empty() && !all_symbols { 309 if res.is_empty() && !all_symbols {
311 let mut query = Query::new(params.query); 310 let mut query = Query::new(params.query);
312 query.limit(128); 311 query.limit(128);
313 res = exec_query(&world, query)?; 312 res = exec_query(&snap, query)?;
314 } 313 }
315 314
316 return Ok(Some(res)); 315 return Ok(Some(res));
317 316
318 fn exec_query(world: &WorldSnapshot, query: Query) -> Result<Vec<SymbolInformation>> { 317 fn exec_query(snap: &GlobalStateSnapshot, query: Query) -> Result<Vec<SymbolInformation>> {
319 let mut res = Vec::new(); 318 let mut res = Vec::new();
320 for nav in world.analysis().symbol_search(query)? { 319 for nav in snap.analysis().symbol_search(query)? {
321 let info = SymbolInformation { 320 let info = SymbolInformation {
322 name: nav.name().to_string(), 321 name: nav.name().to_string(),
323 kind: to_proto::symbol_kind(nav.kind()), 322 kind: to_proto::symbol_kind(nav.kind()),
324 location: to_proto::location(world, nav.file_range())?, 323 location: to_proto::location(snap, nav.file_range())?,
325 container_name: nav.container_name().map(|v| v.to_string()), 324 container_name: nav.container_name().map(|v| v.to_string()),
326 deprecated: None, 325 deprecated: None,
327 }; 326 };
@@ -332,73 +331,73 @@ pub fn handle_workspace_symbol(
332} 331}
333 332
334pub fn handle_goto_definition( 333pub fn handle_goto_definition(
335 world: WorldSnapshot, 334 snap: GlobalStateSnapshot,
336 params: lsp_types::GotoDefinitionParams, 335 params: lsp_types::GotoDefinitionParams,
337) -> Result<Option<lsp_types::GotoDefinitionResponse>> { 336) -> Result<Option<lsp_types::GotoDefinitionResponse>> {
338 let _p = profile("handle_goto_definition"); 337 let _p = profile("handle_goto_definition");
339 let position = from_proto::file_position(&world, params.text_document_position_params)?; 338 let position = from_proto::file_position(&snap, params.text_document_position_params)?;
340 let nav_info = match world.analysis().goto_definition(position)? { 339 let nav_info = match snap.analysis().goto_definition(position)? {
341 None => return Ok(None), 340 None => return Ok(None),
342 Some(it) => it, 341 Some(it) => it,
343 }; 342 };
344 let src = FileRange { file_id: position.file_id, range: nav_info.range }; 343 let src = FileRange { file_id: position.file_id, range: nav_info.range };
345 let res = to_proto::goto_definition_response(&world, Some(src), nav_info.info)?; 344 let res = to_proto::goto_definition_response(&snap, Some(src), nav_info.info)?;
346 Ok(Some(res)) 345 Ok(Some(res))
347} 346}
348 347
349pub fn handle_goto_implementation( 348pub fn handle_goto_implementation(
350 world: WorldSnapshot, 349 snap: GlobalStateSnapshot,
351 params: lsp_types::request::GotoImplementationParams, 350 params: lsp_types::request::GotoImplementationParams,
352) -> Result<Option<lsp_types::request::GotoImplementationResponse>> { 351) -> Result<Option<lsp_types::request::GotoImplementationResponse>> {
353 let _p = profile("handle_goto_implementation"); 352 let _p = profile("handle_goto_implementation");
354 let position = from_proto::file_position(&world, params.text_document_position_params)?; 353 let position = from_proto::file_position(&snap, params.text_document_position_params)?;
355 let nav_info = match world.analysis().goto_implementation(position)? { 354 let nav_info = match snap.analysis().goto_implementation(position)? {
356 None => return Ok(None), 355 None => return Ok(None),
357 Some(it) => it, 356 Some(it) => it,
358 }; 357 };
359 let src = FileRange { file_id: position.file_id, range: nav_info.range }; 358 let src = FileRange { file_id: position.file_id, range: nav_info.range };
360 let res = to_proto::goto_definition_response(&world, Some(src), nav_info.info)?; 359 let res = to_proto::goto_definition_response(&snap, Some(src), nav_info.info)?;
361 Ok(Some(res)) 360 Ok(Some(res))
362} 361}
363 362
364pub fn handle_goto_type_definition( 363pub fn handle_goto_type_definition(
365 world: WorldSnapshot, 364 snap: GlobalStateSnapshot,
366 params: lsp_types::request::GotoTypeDefinitionParams, 365 params: lsp_types::request::GotoTypeDefinitionParams,
367) -> Result<Option<lsp_types::request::GotoTypeDefinitionResponse>> { 366) -> Result<Option<lsp_types::request::GotoTypeDefinitionResponse>> {
368 let _p = profile("handle_goto_type_definition"); 367 let _p = profile("handle_goto_type_definition");
369 let position = from_proto::file_position(&world, params.text_document_position_params)?; 368 let position = from_proto::file_position(&snap, params.text_document_position_params)?;
370 let nav_info = match world.analysis().goto_type_definition(position)? { 369 let nav_info = match snap.analysis().goto_type_definition(position)? {
371 None => return Ok(None), 370 None => return Ok(None),
372 Some(it) => it, 371 Some(it) => it,
373 }; 372 };
374 let src = FileRange { file_id: position.file_id, range: nav_info.range }; 373 let src = FileRange { file_id: position.file_id, range: nav_info.range };
375 let res = to_proto::goto_definition_response(&world, Some(src), nav_info.info)?; 374 let res = to_proto::goto_definition_response(&snap, Some(src), nav_info.info)?;
376 Ok(Some(res)) 375 Ok(Some(res))
377} 376}
378 377
379pub fn handle_parent_module( 378pub fn handle_parent_module(
380 world: WorldSnapshot, 379 snap: GlobalStateSnapshot,
381 params: lsp_types::TextDocumentPositionParams, 380 params: lsp_types::TextDocumentPositionParams,
382) -> Result<Option<lsp_types::GotoDefinitionResponse>> { 381) -> Result<Option<lsp_types::GotoDefinitionResponse>> {
383 let _p = profile("handle_parent_module"); 382 let _p = profile("handle_parent_module");
384 let position = from_proto::file_position(&world, params)?; 383 let position = from_proto::file_position(&snap, params)?;
385 let navs = world.analysis().parent_module(position)?; 384 let navs = snap.analysis().parent_module(position)?;
386 let res = to_proto::goto_definition_response(&world, None, navs)?; 385 let res = to_proto::goto_definition_response(&snap, None, navs)?;
387 Ok(Some(res)) 386 Ok(Some(res))
388} 387}
389 388
390pub fn handle_runnables( 389pub fn handle_runnables(
391 world: WorldSnapshot, 390 snap: GlobalStateSnapshot,
392 params: lsp_ext::RunnablesParams, 391 params: lsp_ext::RunnablesParams,
393) -> Result<Vec<lsp_ext::Runnable>> { 392) -> Result<Vec<lsp_ext::Runnable>> {
394 let _p = profile("handle_runnables"); 393 let _p = profile("handle_runnables");
395 let file_id = from_proto::file_id(&world, &params.text_document.uri)?; 394 let file_id = from_proto::file_id(&snap, &params.text_document.uri)?;
396 let line_index = world.analysis().file_line_index(file_id)?; 395 let line_index = snap.analysis().file_line_index(file_id)?;
397 let offset = params.position.map(|it| from_proto::offset(&line_index, it)); 396 let offset = params.position.map(|it| from_proto::offset(&line_index, it));
398 let mut res = Vec::new(); 397 let mut res = Vec::new();
399 let workspace_root = world.workspace_root_for(file_id); 398 let workspace_root = snap.workspace_root_for(file_id);
400 let cargo_spec = CargoTargetSpec::for_file(&world, file_id)?; 399 let cargo_spec = CargoTargetSpec::for_file(&snap, file_id)?;
401 for runnable in world.analysis().runnables(file_id)? { 400 for runnable in snap.analysis().runnables(file_id)? {
402 if let Some(offset) = offset { 401 if let Some(offset) = offset {
403 if !runnable.nav.full_range().contains_inclusive(offset) { 402 if !runnable.nav.full_range().contains_inclusive(offset) {
404 continue; 403 continue;
@@ -413,7 +412,7 @@ pub fn handle_runnables(
413 } 412 }
414 } 413 }
415 } 414 }
416 res.push(to_proto::runnable(&world, file_id, runnable)?); 415 res.push(to_proto::runnable(&snap, file_id, runnable)?);
417 } 416 }
418 417
419 // Add `cargo check` and `cargo test` for the whole package 418 // Add `cargo check` and `cargo test` for the whole package
@@ -453,16 +452,16 @@ pub fn handle_runnables(
453} 452}
454 453
455pub fn handle_completion( 454pub fn handle_completion(
456 world: WorldSnapshot, 455 snap: GlobalStateSnapshot,
457 params: lsp_types::CompletionParams, 456 params: lsp_types::CompletionParams,
458) -> Result<Option<lsp_types::CompletionResponse>> { 457) -> Result<Option<lsp_types::CompletionResponse>> {
459 let _p = profile("handle_completion"); 458 let _p = profile("handle_completion");
460 let position = from_proto::file_position(&world, params.text_document_position)?; 459 let position = from_proto::file_position(&snap, params.text_document_position)?;
461 let completion_triggered_after_single_colon = { 460 let completion_triggered_after_single_colon = {
462 let mut res = false; 461 let mut res = false;
463 if let Some(ctx) = params.context { 462 if let Some(ctx) = params.context {
464 if ctx.trigger_character.unwrap_or_default() == ":" { 463 if ctx.trigger_character.unwrap_or_default() == ":" {
465 let source_file = world.analysis().parse(position.file_id)?; 464 let source_file = snap.analysis().parse(position.file_id)?;
466 let syntax = source_file.syntax(); 465 let syntax = source_file.syntax();
467 let text = syntax.text(); 466 let text = syntax.text();
468 if let Some(next_char) = text.char_at(position.offset) { 467 if let Some(next_char) = text.char_at(position.offset) {
@@ -480,12 +479,12 @@ pub fn handle_completion(
480 return Ok(None); 479 return Ok(None);
481 } 480 }
482 481
483 let items = match world.analysis().completions(&world.config.completion, position)? { 482 let items = match snap.analysis().completions(&snap.config.completion, position)? {
484 None => return Ok(None), 483 None => return Ok(None),
485 Some(items) => items, 484 Some(items) => items,
486 }; 485 };
487 let line_index = world.analysis().file_line_index(position.file_id)?; 486 let line_index = snap.analysis().file_line_index(position.file_id)?;
488 let line_endings = world.file_line_endings(position.file_id); 487 let line_endings = snap.file_line_endings(position.file_id);
489 let items: Vec<CompletionItem> = items 488 let items: Vec<CompletionItem> = items
490 .into_iter() 489 .into_iter()
491 .map(|item| to_proto::completion_item(&line_index, line_endings, item)) 490 .map(|item| to_proto::completion_item(&line_index, line_endings, item))
@@ -495,15 +494,15 @@ pub fn handle_completion(
495} 494}
496 495
497pub fn handle_folding_range( 496pub fn handle_folding_range(
498 world: WorldSnapshot, 497 snap: GlobalStateSnapshot,
499 params: FoldingRangeParams, 498 params: FoldingRangeParams,
500) -> Result<Option<Vec<FoldingRange>>> { 499) -> Result<Option<Vec<FoldingRange>>> {
501 let _p = profile("handle_folding_range"); 500 let _p = profile("handle_folding_range");
502 let file_id = from_proto::file_id(&world, &params.text_document.uri)?; 501 let file_id = from_proto::file_id(&snap, &params.text_document.uri)?;
503 let folds = world.analysis().folding_ranges(file_id)?; 502 let folds = snap.analysis().folding_ranges(file_id)?;
504 let text = world.analysis().file_text(file_id)?; 503 let text = snap.analysis().file_text(file_id)?;
505 let line_index = world.analysis().file_line_index(file_id)?; 504 let line_index = snap.analysis().file_line_index(file_id)?;
506 let line_folding_only = world.config.client_caps.line_folding_only; 505 let line_folding_only = snap.config.client_caps.line_folding_only;
507 let res = folds 506 let res = folds
508 .into_iter() 507 .into_iter()
509 .map(|it| to_proto::folding_range(&*text, &line_index, line_folding_only, it)) 508 .map(|it| to_proto::folding_range(&*text, &line_index, line_folding_only, it))
@@ -512,16 +511,16 @@ pub fn handle_folding_range(
512} 511}
513 512
514pub fn handle_signature_help( 513pub fn handle_signature_help(
515 world: WorldSnapshot, 514 snap: GlobalStateSnapshot,
516 params: lsp_types::SignatureHelpParams, 515 params: lsp_types::SignatureHelpParams,
517) -> Result<Option<lsp_types::SignatureHelp>> { 516) -> Result<Option<lsp_types::SignatureHelp>> {
518 let _p = profile("handle_signature_help"); 517 let _p = profile("handle_signature_help");
519 let position = from_proto::file_position(&world, params.text_document_position_params)?; 518 let position = from_proto::file_position(&snap, params.text_document_position_params)?;
520 let call_info = match world.analysis().call_info(position)? { 519 let call_info = match snap.analysis().call_info(position)? {
521 None => return Ok(None), 520 None => return Ok(None),
522 Some(it) => it, 521 Some(it) => it,
523 }; 522 };
524 let concise = !world.config.call_info_full; 523 let concise = !snap.config.call_info_full;
525 let mut active_parameter = call_info.active_parameter.map(|it| it as i64); 524 let mut active_parameter = call_info.active_parameter.map(|it| it as i64);
526 if concise && call_info.signature.has_self_param { 525 if concise && call_info.signature.has_self_param {
527 active_parameter = active_parameter.map(|it| it.saturating_sub(1)); 526 active_parameter = active_parameter.map(|it| it.saturating_sub(1));
@@ -535,14 +534,17 @@ pub fn handle_signature_help(
535 })) 534 }))
536} 535}
537 536
538pub fn handle_hover(world: WorldSnapshot, params: lsp_types::HoverParams) -> Result<Option<Hover>> { 537pub fn handle_hover(
538 snap: GlobalStateSnapshot,
539 params: lsp_types::HoverParams,
540) -> Result<Option<Hover>> {
539 let _p = profile("handle_hover"); 541 let _p = profile("handle_hover");
540 let position = from_proto::file_position(&world, params.text_document_position_params)?; 542 let position = from_proto::file_position(&snap, params.text_document_position_params)?;
541 let info = match world.analysis().hover(position)? { 543 let info = match snap.analysis().hover(position)? {
542 None => return Ok(None), 544 None => return Ok(None),
543 Some(info) => info, 545 Some(info) => info,
544 }; 546 };
545 let line_index = world.analysis.file_line_index(position.file_id)?; 547 let line_index = snap.analysis.file_line_index(position.file_id)?;
546 let range = to_proto::range(&line_index, info.range); 548 let range = to_proto::range(&line_index, info.range);
547 let res = Hover { 549 let res = Hover {
548 contents: HoverContents::Markup(MarkupContent { 550 contents: HoverContents::Markup(MarkupContent {
@@ -555,26 +557,29 @@ pub fn handle_hover(world: WorldSnapshot, params: lsp_types::HoverParams) -> Res
555} 557}
556 558
557pub fn handle_prepare_rename( 559pub fn handle_prepare_rename(
558 world: WorldSnapshot, 560 snap: GlobalStateSnapshot,
559 params: lsp_types::TextDocumentPositionParams, 561 params: lsp_types::TextDocumentPositionParams,
560) -> Result<Option<PrepareRenameResponse>> { 562) -> Result<Option<PrepareRenameResponse>> {
561 let _p = profile("handle_prepare_rename"); 563 let _p = profile("handle_prepare_rename");
562 let position = from_proto::file_position(&world, params)?; 564 let position = from_proto::file_position(&snap, params)?;
563 565
564 let optional_change = world.analysis().rename(position, "dummy")?; 566 let optional_change = snap.analysis().rename(position, "dummy")?;
565 let range = match optional_change { 567 let range = match optional_change {
566 None => return Ok(None), 568 None => return Ok(None),
567 Some(it) => it.range, 569 Some(it) => it.range,
568 }; 570 };
569 571
570 let line_index = world.analysis().file_line_index(position.file_id)?; 572 let line_index = snap.analysis().file_line_index(position.file_id)?;
571 let range = to_proto::range(&line_index, range); 573 let range = to_proto::range(&line_index, range);
572 Ok(Some(PrepareRenameResponse::Range(range))) 574 Ok(Some(PrepareRenameResponse::Range(range)))
573} 575}
574 576
575pub fn handle_rename(world: WorldSnapshot, params: RenameParams) -> Result<Option<WorkspaceEdit>> { 577pub fn handle_rename(
578 snap: GlobalStateSnapshot,
579 params: RenameParams,
580) -> Result<Option<WorkspaceEdit>> {
576 let _p = profile("handle_rename"); 581 let _p = profile("handle_rename");
577 let position = from_proto::file_position(&world, params.text_document_position)?; 582 let position = from_proto::file_position(&snap, params.text_document_position)?;
578 583
579 if params.new_name.is_empty() { 584 if params.new_name.is_empty() {
580 return Err(LspError::new( 585 return Err(LspError::new(
@@ -584,36 +589,36 @@ pub fn handle_rename(world: WorldSnapshot, params: RenameParams) -> Result<Optio
584 .into()); 589 .into());
585 } 590 }
586 591
587 let optional_change = world.analysis().rename(position, &*params.new_name)?; 592 let optional_change = snap.analysis().rename(position, &*params.new_name)?;
588 let source_change = match optional_change { 593 let source_change = match optional_change {
589 None => return Ok(None), 594 None => return Ok(None),
590 Some(it) => it.info, 595 Some(it) => it.info,
591 }; 596 };
592 let workspace_edit = to_proto::workspace_edit(&world, source_change)?; 597 let workspace_edit = to_proto::workspace_edit(&snap, source_change)?;
593 Ok(Some(workspace_edit)) 598 Ok(Some(workspace_edit))
594} 599}
595 600
596pub fn handle_references( 601pub fn handle_references(
597 world: WorldSnapshot, 602 snap: GlobalStateSnapshot,
598 params: lsp_types::ReferenceParams, 603 params: lsp_types::ReferenceParams,
599) -> Result<Option<Vec<Location>>> { 604) -> Result<Option<Vec<Location>>> {
600 let _p = profile("handle_references"); 605 let _p = profile("handle_references");
601 let position = from_proto::file_position(&world, params.text_document_position)?; 606 let position = from_proto::file_position(&snap, params.text_document_position)?;
602 607
603 let refs = match world.analysis().find_all_refs(position, None)? { 608 let refs = match snap.analysis().find_all_refs(position, None)? {
604 None => return Ok(None), 609 None => return Ok(None),
605 Some(refs) => refs, 610 Some(refs) => refs,
606 }; 611 };
607 612
608 let locations = if params.context.include_declaration { 613 let locations = if params.context.include_declaration {
609 refs.into_iter() 614 refs.into_iter()
610 .filter_map(|reference| to_proto::location(&world, reference.file_range).ok()) 615 .filter_map(|reference| to_proto::location(&snap, reference.file_range).ok())
611 .collect() 616 .collect()
612 } else { 617 } else {
613 // Only iterate over the references if include_declaration was false 618 // Only iterate over the references if include_declaration was false
614 refs.references() 619 refs.references()
615 .iter() 620 .iter()
616 .filter_map(|reference| to_proto::location(&world, reference.file_range).ok()) 621 .filter_map(|reference| to_proto::location(&snap, reference.file_range).ok())
617 .collect() 622 .collect()
618 }; 623 };
619 624
@@ -621,24 +626,24 @@ pub fn handle_references(
621} 626}
622 627
623pub fn handle_formatting( 628pub fn handle_formatting(
624 world: WorldSnapshot, 629 snap: GlobalStateSnapshot,
625 params: DocumentFormattingParams, 630 params: DocumentFormattingParams,
626) -> Result<Option<Vec<lsp_types::TextEdit>>> { 631) -> Result<Option<Vec<lsp_types::TextEdit>>> {
627 let _p = profile("handle_formatting"); 632 let _p = profile("handle_formatting");
628 let file_id = from_proto::file_id(&world, &params.text_document.uri)?; 633 let file_id = from_proto::file_id(&snap, &params.text_document.uri)?;
629 let file = world.analysis().file_text(file_id)?; 634 let file = snap.analysis().file_text(file_id)?;
630 let crate_ids = world.analysis().crate_for(file_id)?; 635 let crate_ids = snap.analysis().crate_for(file_id)?;
631 636
632 let file_line_index = world.analysis().file_line_index(file_id)?; 637 let file_line_index = snap.analysis().file_line_index(file_id)?;
633 let end_position = to_proto::position(&file_line_index, TextSize::of(file.as_str())); 638 let end_position = to_proto::position(&file_line_index, TextSize::of(file.as_str()));
634 639
635 let mut rustfmt = match &world.config.rustfmt { 640 let mut rustfmt = match &snap.config.rustfmt {
636 RustfmtConfig::Rustfmt { extra_args } => { 641 RustfmtConfig::Rustfmt { extra_args } => {
637 let mut cmd = process::Command::new("rustfmt"); 642 let mut cmd = process::Command::new("rustfmt");
638 cmd.args(extra_args); 643 cmd.args(extra_args);
639 if let Some(&crate_id) = crate_ids.first() { 644 if let Some(&crate_id) = crate_ids.first() {
640 // Assume all crates are in the same edition 645 // Assume all crates are in the same edition
641 let edition = world.analysis().crate_edition(crate_id)?; 646 let edition = snap.analysis().crate_edition(crate_id)?;
642 cmd.arg("--edition"); 647 cmd.arg("--edition");
643 cmd.arg(edition.to_string()); 648 cmd.arg(edition.to_string());
644 } 649 }
@@ -697,23 +702,23 @@ pub fn handle_formatting(
697} 702}
698 703
699pub fn handle_code_action( 704pub fn handle_code_action(
700 world: WorldSnapshot, 705 snap: GlobalStateSnapshot,
701 params: lsp_types::CodeActionParams, 706 params: lsp_types::CodeActionParams,
702) -> Result<Option<Vec<lsp_ext::CodeAction>>> { 707) -> Result<Option<Vec<lsp_ext::CodeAction>>> {
703 let _p = profile("handle_code_action"); 708 let _p = profile("handle_code_action");
704 // We intentionally don't support command-based actions, as those either 709 // We intentionally don't support command-based actions, as those either
705 // requires custom client-code anyway, or requires server-initiated edits. 710 // requires custom client-code anyway, or requires server-initiated edits.
706 // Server initiated edits break causality, so we avoid those as well. 711 // Server initiated edits break causality, so we avoid those as well.
707 if !world.config.client_caps.code_action_literals { 712 if !snap.config.client_caps.code_action_literals {
708 return Ok(None); 713 return Ok(None);
709 } 714 }
710 715
711 let file_id = from_proto::file_id(&world, &params.text_document.uri)?; 716 let file_id = from_proto::file_id(&snap, &params.text_document.uri)?;
712 let line_index = world.analysis().file_line_index(file_id)?; 717 let line_index = snap.analysis().file_line_index(file_id)?;
713 let range = from_proto::text_range(&line_index, params.range); 718 let range = from_proto::text_range(&line_index, params.range);
714 let frange = FileRange { file_id, range }; 719 let frange = FileRange { file_id, range };
715 720
716 let diagnostics = world.analysis().diagnostics(file_id)?; 721 let diagnostics = snap.analysis().diagnostics(file_id)?;
717 let mut res: Vec<lsp_ext::CodeAction> = Vec::new(); 722 let mut res: Vec<lsp_ext::CodeAction> = Vec::new();
718 723
719 let fixes_from_diagnostics = diagnostics 724 let fixes_from_diagnostics = diagnostics
@@ -724,13 +729,13 @@ pub fn handle_code_action(
724 729
725 for fix in fixes_from_diagnostics { 730 for fix in fixes_from_diagnostics {
726 let title = fix.label; 731 let title = fix.label;
727 let edit = to_proto::snippet_workspace_edit(&world, fix.source_change)?; 732 let edit = to_proto::snippet_workspace_edit(&snap, fix.source_change)?;
728 let action = 733 let action =
729 lsp_ext::CodeAction { title, group: None, kind: None, edit: Some(edit), command: None }; 734 lsp_ext::CodeAction { title, group: None, kind: None, edit: Some(edit), command: None };
730 res.push(action); 735 res.push(action);
731 } 736 }
732 737
733 for fix in world.check_fixes.get(&file_id).into_iter().flatten() { 738 for fix in snap.check_fixes.get(&file_id).into_iter().flatten() {
734 let fix_range = from_proto::text_range(&line_index, fix.range); 739 let fix_range = from_proto::text_range(&line_index, fix.range);
735 if fix_range.intersect(range).is_none() { 740 if fix_range.intersect(range).is_none() {
736 continue; 741 continue;
@@ -738,31 +743,31 @@ pub fn handle_code_action(
738 res.push(fix.action.clone()); 743 res.push(fix.action.clone());
739 } 744 }
740 745
741 for assist in world.analysis().assists(&world.config.assist, frange)?.into_iter() { 746 for assist in snap.analysis().assists(&snap.config.assist, frange)?.into_iter() {
742 res.push(to_proto::code_action(&world, assist)?.into()); 747 res.push(to_proto::code_action(&snap, assist)?.into());
743 } 748 }
744 Ok(Some(res)) 749 Ok(Some(res))
745} 750}
746 751
747pub fn handle_code_lens( 752pub fn handle_code_lens(
748 world: WorldSnapshot, 753 snap: GlobalStateSnapshot,
749 params: lsp_types::CodeLensParams, 754 params: lsp_types::CodeLensParams,
750) -> Result<Option<Vec<CodeLens>>> { 755) -> Result<Option<Vec<CodeLens>>> {
751 let _p = profile("handle_code_lens"); 756 let _p = profile("handle_code_lens");
752 let mut lenses: Vec<CodeLens> = Default::default(); 757 let mut lenses: Vec<CodeLens> = Default::default();
753 758
754 if world.config.lens.none() { 759 if snap.config.lens.none() {
755 // early return before any db query! 760 // early return before any db query!
756 return Ok(Some(lenses)); 761 return Ok(Some(lenses));
757 } 762 }
758 763
759 let file_id = from_proto::file_id(&world, &params.text_document.uri)?; 764 let file_id = from_proto::file_id(&snap, &params.text_document.uri)?;
760 let line_index = world.analysis().file_line_index(file_id)?; 765 let line_index = snap.analysis().file_line_index(file_id)?;
761 let cargo_spec = CargoTargetSpec::for_file(&world, file_id)?; 766 let cargo_spec = CargoTargetSpec::for_file(&snap, file_id)?;
762 767
763 if world.config.lens.runnable() { 768 if snap.config.lens.runnable() {
764 // Gather runnables 769 // Gather runnables
765 for runnable in world.analysis().runnables(file_id)? { 770 for runnable in snap.analysis().runnables(file_id)? {
766 let (run_title, debugee) = match &runnable.kind { 771 let (run_title, debugee) = match &runnable.kind {
767 RunnableKind::Test { .. } | RunnableKind::TestMod { .. } => { 772 RunnableKind::Test { .. } | RunnableKind::TestMod { .. } => {
768 ("â–¶\u{fe0e} Run Test", true) 773 ("â–¶\u{fe0e} Run Test", true)
@@ -788,8 +793,8 @@ pub fn handle_code_lens(
788 }; 793 };
789 794
790 let range = to_proto::range(&line_index, runnable.nav.range()); 795 let range = to_proto::range(&line_index, runnable.nav.range());
791 let r = to_proto::runnable(&world, file_id, runnable)?; 796 let r = to_proto::runnable(&snap, file_id, runnable)?;
792 if world.config.lens.run { 797 if snap.config.lens.run {
793 let lens = CodeLens { 798 let lens = CodeLens {
794 range, 799 range,
795 command: Some(Command { 800 command: Some(Command {
@@ -802,7 +807,7 @@ pub fn handle_code_lens(
802 lenses.push(lens); 807 lenses.push(lens);
803 } 808 }
804 809
805 if debugee && world.config.lens.debug { 810 if debugee && snap.config.lens.debug {
806 let debug_lens = CodeLens { 811 let debug_lens = CodeLens {
807 range, 812 range,
808 command: Some(Command { 813 command: Some(Command {
@@ -817,11 +822,10 @@ pub fn handle_code_lens(
817 } 822 }
818 } 823 }
819 824
820 if world.config.lens.impementations { 825 if snap.config.lens.impementations {
821 // Handle impls 826 // Handle impls
822 lenses.extend( 827 lenses.extend(
823 world 828 snap.analysis()
824 .analysis()
825 .file_structure(file_id)? 829 .file_structure(file_id)?
826 .into_iter() 830 .into_iter()
827 .filter(|it| match it.kind { 831 .filter(|it| match it.kind {
@@ -856,14 +860,17 @@ enum CodeLensResolveData {
856 Impls(lsp_types::request::GotoImplementationParams), 860 Impls(lsp_types::request::GotoImplementationParams),
857} 861}
858 862
859pub fn handle_code_lens_resolve(world: WorldSnapshot, code_lens: CodeLens) -> Result<CodeLens> { 863pub fn handle_code_lens_resolve(
864 snap: GlobalStateSnapshot,
865 code_lens: CodeLens,
866) -> Result<CodeLens> {
860 let _p = profile("handle_code_lens_resolve"); 867 let _p = profile("handle_code_lens_resolve");
861 let data = code_lens.data.unwrap(); 868 let data = code_lens.data.unwrap();
862 let resolve = from_json::<Option<CodeLensResolveData>>("CodeLensResolveData", data)?; 869 let resolve = from_json::<Option<CodeLensResolveData>>("CodeLensResolveData", data)?;
863 match resolve { 870 match resolve {
864 Some(CodeLensResolveData::Impls(lens_params)) => { 871 Some(CodeLensResolveData::Impls(lens_params)) => {
865 let locations: Vec<Location> = 872 let locations: Vec<Location> =
866 match handle_goto_implementation(world, lens_params.clone())? { 873 match handle_goto_implementation(snap, lens_params.clone())? {
867 Some(lsp_types::GotoDefinitionResponse::Scalar(loc)) => vec![loc], 874 Some(lsp_types::GotoDefinitionResponse::Scalar(loc)) => vec![loc],
868 Some(lsp_types::GotoDefinitionResponse::Array(locs)) => locs, 875 Some(lsp_types::GotoDefinitionResponse::Array(locs)) => locs,
869 Some(lsp_types::GotoDefinitionResponse::Link(links)) => links 876 Some(lsp_types::GotoDefinitionResponse::Link(links)) => links
@@ -902,14 +909,14 @@ pub fn handle_code_lens_resolve(world: WorldSnapshot, code_lens: CodeLens) -> Re
902} 909}
903 910
904pub fn handle_document_highlight( 911pub fn handle_document_highlight(
905 world: WorldSnapshot, 912 snap: GlobalStateSnapshot,
906 params: lsp_types::DocumentHighlightParams, 913 params: lsp_types::DocumentHighlightParams,
907) -> Result<Option<Vec<DocumentHighlight>>> { 914) -> Result<Option<Vec<DocumentHighlight>>> {
908 let _p = profile("handle_document_highlight"); 915 let _p = profile("handle_document_highlight");
909 let position = from_proto::file_position(&world, params.text_document_position_params)?; 916 let position = from_proto::file_position(&snap, params.text_document_position_params)?;
910 let line_index = world.analysis().file_line_index(position.file_id)?; 917 let line_index = snap.analysis().file_line_index(position.file_id)?;
911 918
912 let refs = match world 919 let refs = match snap
913 .analysis() 920 .analysis()
914 .find_all_refs(position, Some(SearchScope::single_file(position.file_id)))? 921 .find_all_refs(position, Some(SearchScope::single_file(position.file_id)))?
915 { 922 {
@@ -929,19 +936,19 @@ pub fn handle_document_highlight(
929} 936}
930 937
931pub fn handle_ssr( 938pub fn handle_ssr(
932 world: WorldSnapshot, 939 snap: GlobalStateSnapshot,
933 params: lsp_ext::SsrParams, 940 params: lsp_ext::SsrParams,
934) -> Result<lsp_types::WorkspaceEdit> { 941) -> Result<lsp_types::WorkspaceEdit> {
935 let _p = profile("handle_ssr"); 942 let _p = profile("handle_ssr");
936 let source_change = 943 let source_change =
937 world.analysis().structural_search_replace(&params.query, params.parse_only)??; 944 snap.analysis().structural_search_replace(&params.query, params.parse_only)??;
938 to_proto::workspace_edit(&world, source_change) 945 to_proto::workspace_edit(&snap, source_change)
939} 946}
940 947
941pub fn publish_diagnostics(world: &WorldSnapshot, file_id: FileId) -> Result<DiagnosticTask> { 948pub fn publish_diagnostics(snap: &GlobalStateSnapshot, file_id: FileId) -> Result<DiagnosticTask> {
942 let _p = profile("publish_diagnostics"); 949 let _p = profile("publish_diagnostics");
943 let line_index = world.analysis().file_line_index(file_id)?; 950 let line_index = snap.analysis().file_line_index(file_id)?;
944 let diagnostics: Vec<Diagnostic> = world 951 let diagnostics: Vec<Diagnostic> = snap
945 .analysis() 952 .analysis()
946 .diagnostics(file_id)? 953 .diagnostics(file_id)?
947 .into_iter() 954 .into_iter()
@@ -959,28 +966,28 @@ pub fn publish_diagnostics(world: &WorldSnapshot, file_id: FileId) -> Result<Dia
959} 966}
960 967
961pub fn handle_inlay_hints( 968pub fn handle_inlay_hints(
962 world: WorldSnapshot, 969 snap: GlobalStateSnapshot,
963 params: InlayHintsParams, 970 params: InlayHintsParams,
964) -> Result<Vec<InlayHint>> { 971) -> Result<Vec<InlayHint>> {
965 let _p = profile("handle_inlay_hints"); 972 let _p = profile("handle_inlay_hints");
966 let file_id = from_proto::file_id(&world, &params.text_document.uri)?; 973 let file_id = from_proto::file_id(&snap, &params.text_document.uri)?;
967 let analysis = world.analysis(); 974 let analysis = snap.analysis();
968 let line_index = analysis.file_line_index(file_id)?; 975 let line_index = analysis.file_line_index(file_id)?;
969 Ok(analysis 976 Ok(analysis
970 .inlay_hints(file_id, &world.config.inlay_hints)? 977 .inlay_hints(file_id, &snap.config.inlay_hints)?
971 .into_iter() 978 .into_iter()
972 .map(|it| to_proto::inlay_int(&line_index, it)) 979 .map(|it| to_proto::inlay_int(&line_index, it))
973 .collect()) 980 .collect())
974} 981}
975 982
976pub fn handle_call_hierarchy_prepare( 983pub fn handle_call_hierarchy_prepare(
977 world: WorldSnapshot, 984 snap: GlobalStateSnapshot,
978 params: CallHierarchyPrepareParams, 985 params: CallHierarchyPrepareParams,
979) -> Result<Option<Vec<CallHierarchyItem>>> { 986) -> Result<Option<Vec<CallHierarchyItem>>> {
980 let _p = profile("handle_call_hierarchy_prepare"); 987 let _p = profile("handle_call_hierarchy_prepare");
981 let position = from_proto::file_position(&world, params.text_document_position_params)?; 988 let position = from_proto::file_position(&snap, params.text_document_position_params)?;
982 989
983 let nav_info = match world.analysis().call_hierarchy(position)? { 990 let nav_info = match snap.analysis().call_hierarchy(position)? {
984 None => return Ok(None), 991 None => return Ok(None),
985 Some(it) => it, 992 Some(it) => it,
986 }; 993 };
@@ -989,24 +996,24 @@ pub fn handle_call_hierarchy_prepare(
989 let res = navs 996 let res = navs
990 .into_iter() 997 .into_iter()
991 .filter(|it| it.kind() == SyntaxKind::FN_DEF) 998 .filter(|it| it.kind() == SyntaxKind::FN_DEF)
992 .map(|it| to_proto::call_hierarchy_item(&world, it)) 999 .map(|it| to_proto::call_hierarchy_item(&snap, it))
993 .collect::<Result<Vec<_>>>()?; 1000 .collect::<Result<Vec<_>>>()?;
994 1001
995 Ok(Some(res)) 1002 Ok(Some(res))
996} 1003}
997 1004
998pub fn handle_call_hierarchy_incoming( 1005pub fn handle_call_hierarchy_incoming(
999 world: WorldSnapshot, 1006 snap: GlobalStateSnapshot,
1000 params: CallHierarchyIncomingCallsParams, 1007 params: CallHierarchyIncomingCallsParams,
1001) -> Result<Option<Vec<CallHierarchyIncomingCall>>> { 1008) -> Result<Option<Vec<CallHierarchyIncomingCall>>> {
1002 let _p = profile("handle_call_hierarchy_incoming"); 1009 let _p = profile("handle_call_hierarchy_incoming");
1003 let item = params.item; 1010 let item = params.item;
1004 1011
1005 let doc = TextDocumentIdentifier::new(item.uri); 1012 let doc = TextDocumentIdentifier::new(item.uri);
1006 let frange = from_proto::file_range(&world, doc, item.range)?; 1013 let frange = from_proto::file_range(&snap, doc, item.range)?;
1007 let fpos = FilePosition { file_id: frange.file_id, offset: frange.range.start() }; 1014 let fpos = FilePosition { file_id: frange.file_id, offset: frange.range.start() };
1008 1015
1009 let call_items = match world.analysis().incoming_calls(fpos)? { 1016 let call_items = match snap.analysis().incoming_calls(fpos)? {
1010 None => return Ok(None), 1017 None => return Ok(None),
1011 Some(it) => it, 1018 Some(it) => it,
1012 }; 1019 };
@@ -1015,8 +1022,8 @@ pub fn handle_call_hierarchy_incoming(
1015 1022
1016 for call_item in call_items.into_iter() { 1023 for call_item in call_items.into_iter() {
1017 let file_id = call_item.target.file_id(); 1024 let file_id = call_item.target.file_id();
1018 let line_index = world.analysis().file_line_index(file_id)?; 1025 let line_index = snap.analysis().file_line_index(file_id)?;
1019 let item = to_proto::call_hierarchy_item(&world, call_item.target)?; 1026 let item = to_proto::call_hierarchy_item(&snap, call_item.target)?;
1020 res.push(CallHierarchyIncomingCall { 1027 res.push(CallHierarchyIncomingCall {
1021 from: item, 1028 from: item,
1022 from_ranges: call_item 1029 from_ranges: call_item
@@ -1031,17 +1038,17 @@ pub fn handle_call_hierarchy_incoming(
1031} 1038}
1032 1039
1033pub fn handle_call_hierarchy_outgoing( 1040pub fn handle_call_hierarchy_outgoing(
1034 world: WorldSnapshot, 1041 snap: GlobalStateSnapshot,
1035 params: CallHierarchyOutgoingCallsParams, 1042 params: CallHierarchyOutgoingCallsParams,
1036) -> Result<Option<Vec<CallHierarchyOutgoingCall>>> { 1043) -> Result<Option<Vec<CallHierarchyOutgoingCall>>> {
1037 let _p = profile("handle_call_hierarchy_outgoing"); 1044 let _p = profile("handle_call_hierarchy_outgoing");
1038 let item = params.item; 1045 let item = params.item;
1039 1046
1040 let doc = TextDocumentIdentifier::new(item.uri); 1047 let doc = TextDocumentIdentifier::new(item.uri);
1041 let frange = from_proto::file_range(&world, doc, item.range)?; 1048 let frange = from_proto::file_range(&snap, doc, item.range)?;
1042 let fpos = FilePosition { file_id: frange.file_id, offset: frange.range.start() }; 1049 let fpos = FilePosition { file_id: frange.file_id, offset: frange.range.start() };
1043 1050
1044 let call_items = match world.analysis().outgoing_calls(fpos)? { 1051 let call_items = match snap.analysis().outgoing_calls(fpos)? {
1045 None => return Ok(None), 1052 None => return Ok(None),
1046 Some(it) => it, 1053 Some(it) => it,
1047 }; 1054 };
@@ -1050,8 +1057,8 @@ pub fn handle_call_hierarchy_outgoing(
1050 1057
1051 for call_item in call_items.into_iter() { 1058 for call_item in call_items.into_iter() {
1052 let file_id = call_item.target.file_id(); 1059 let file_id = call_item.target.file_id();
1053 let line_index = world.analysis().file_line_index(file_id)?; 1060 let line_index = snap.analysis().file_line_index(file_id)?;
1054 let item = to_proto::call_hierarchy_item(&world, call_item.target)?; 1061 let item = to_proto::call_hierarchy_item(&snap, call_item.target)?;
1055 res.push(CallHierarchyOutgoingCall { 1062 res.push(CallHierarchyOutgoingCall {
1056 to: item, 1063 to: item,
1057 from_ranges: call_item 1064 from_ranges: call_item
@@ -1066,31 +1073,31 @@ pub fn handle_call_hierarchy_outgoing(
1066} 1073}
1067 1074
1068pub fn handle_semantic_tokens( 1075pub fn handle_semantic_tokens(
1069 world: WorldSnapshot, 1076 snap: GlobalStateSnapshot,
1070 params: SemanticTokensParams, 1077 params: SemanticTokensParams,
1071) -> Result<Option<SemanticTokensResult>> { 1078) -> Result<Option<SemanticTokensResult>> {
1072 let _p = profile("handle_semantic_tokens"); 1079 let _p = profile("handle_semantic_tokens");
1073 1080
1074 let file_id = from_proto::file_id(&world, &params.text_document.uri)?; 1081 let file_id = from_proto::file_id(&snap, &params.text_document.uri)?;
1075 let text = world.analysis().file_text(file_id)?; 1082 let text = snap.analysis().file_text(file_id)?;
1076 let line_index = world.analysis().file_line_index(file_id)?; 1083 let line_index = snap.analysis().file_line_index(file_id)?;
1077 1084
1078 let highlights = world.analysis().highlight(file_id)?; 1085 let highlights = snap.analysis().highlight(file_id)?;
1079 let semantic_tokens = to_proto::semantic_tokens(&text, &line_index, highlights); 1086 let semantic_tokens = to_proto::semantic_tokens(&text, &line_index, highlights);
1080 Ok(Some(semantic_tokens.into())) 1087 Ok(Some(semantic_tokens.into()))
1081} 1088}
1082 1089
1083pub fn handle_semantic_tokens_range( 1090pub fn handle_semantic_tokens_range(
1084 world: WorldSnapshot, 1091 snap: GlobalStateSnapshot,
1085 params: SemanticTokensRangeParams, 1092 params: SemanticTokensRangeParams,
1086) -> Result<Option<SemanticTokensRangeResult>> { 1093) -> Result<Option<SemanticTokensRangeResult>> {
1087 let _p = profile("handle_semantic_tokens_range"); 1094 let _p = profile("handle_semantic_tokens_range");
1088 1095
1089 let frange = from_proto::file_range(&world, params.text_document, params.range)?; 1096 let frange = from_proto::file_range(&snap, params.text_document, params.range)?;
1090 let text = world.analysis().file_text(frange.file_id)?; 1097 let text = snap.analysis().file_text(frange.file_id)?;
1091 let line_index = world.analysis().file_line_index(frange.file_id)?; 1098 let line_index = snap.analysis().file_line_index(frange.file_id)?;
1092 1099
1093 let highlights = world.analysis().highlight_range(frange)?; 1100 let highlights = snap.analysis().highlight_range(frange)?;
1094 let semantic_tokens = to_proto::semantic_tokens(&text, &line_index, highlights); 1101 let semantic_tokens = to_proto::semantic_tokens(&text, &line_index, highlights);
1095 Ok(Some(semantic_tokens.into())) 1102 Ok(Some(semantic_tokens.into()))
1096} 1103}
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs
index 85304aa87..0915a7fcb 100644
--- a/crates/rust-analyzer/src/to_proto.rs
+++ b/crates/rust-analyzer/src/to_proto.rs
@@ -10,7 +10,8 @@ use ra_syntax::{SyntaxKind, TextRange, TextSize};
10use ra_vfs::LineEndings; 10use ra_vfs::LineEndings;
11 11
12use crate::{ 12use crate::{
13 cargo_target_spec::CargoTargetSpec, lsp_ext, semantic_tokens, world::WorldSnapshot, Result, 13 cargo_target_spec::CargoTargetSpec, global_state::GlobalStateSnapshot, lsp_ext,
14 semantic_tokens, Result,
14}; 15};
15 16
16pub(crate) fn position(line_index: &LineIndex, offset: TextSize) -> lsp_types::Position { 17pub(crate) fn position(line_index: &LineIndex, offset: TextSize) -> lsp_types::Position {
@@ -384,41 +385,44 @@ pub(crate) fn folding_range(
384 } 385 }
385} 386}
386 387
387pub(crate) fn url(world: &WorldSnapshot, file_id: FileId) -> Result<lsp_types::Url> { 388pub(crate) fn url(snap: &GlobalStateSnapshot, file_id: FileId) -> Result<lsp_types::Url> {
388 world.file_id_to_uri(file_id) 389 snap.file_id_to_uri(file_id)
389} 390}
390 391
391pub(crate) fn versioned_text_document_identifier( 392pub(crate) fn versioned_text_document_identifier(
392 world: &WorldSnapshot, 393 snap: &GlobalStateSnapshot,
393 file_id: FileId, 394 file_id: FileId,
394 version: Option<i64>, 395 version: Option<i64>,
395) -> Result<lsp_types::VersionedTextDocumentIdentifier> { 396) -> Result<lsp_types::VersionedTextDocumentIdentifier> {
396 let res = lsp_types::VersionedTextDocumentIdentifier { uri: url(world, file_id)?, version }; 397 let res = lsp_types::VersionedTextDocumentIdentifier { uri: url(snap, file_id)?, version };
397 Ok(res) 398 Ok(res)
398} 399}
399 400
400pub(crate) fn location(world: &WorldSnapshot, frange: FileRange) -> Result<lsp_types::Location> { 401pub(crate) fn location(
401 let url = url(world, frange.file_id)?; 402 snap: &GlobalStateSnapshot,
402 let line_index = world.analysis().file_line_index(frange.file_id)?; 403 frange: FileRange,
404) -> Result<lsp_types::Location> {
405 let url = url(snap, frange.file_id)?;
406 let line_index = snap.analysis().file_line_index(frange.file_id)?;
403 let range = range(&line_index, frange.range); 407 let range = range(&line_index, frange.range);
404 let loc = lsp_types::Location::new(url, range); 408 let loc = lsp_types::Location::new(url, range);
405 Ok(loc) 409 Ok(loc)
406} 410}
407 411
408pub(crate) fn location_link( 412pub(crate) fn location_link(
409 world: &WorldSnapshot, 413 snap: &GlobalStateSnapshot,
410 src: Option<FileRange>, 414 src: Option<FileRange>,
411 target: NavigationTarget, 415 target: NavigationTarget,
412) -> Result<lsp_types::LocationLink> { 416) -> Result<lsp_types::LocationLink> {
413 let origin_selection_range = match src { 417 let origin_selection_range = match src {
414 Some(src) => { 418 Some(src) => {
415 let line_index = world.analysis().file_line_index(src.file_id)?; 419 let line_index = snap.analysis().file_line_index(src.file_id)?;
416 let range = range(&line_index, src.range); 420 let range = range(&line_index, src.range);
417 Some(range) 421 Some(range)
418 } 422 }
419 None => None, 423 None => None,
420 }; 424 };
421 let (target_uri, target_range, target_selection_range) = location_info(world, target)?; 425 let (target_uri, target_range, target_selection_range) = location_info(snap, target)?;
422 let res = lsp_types::LocationLink { 426 let res = lsp_types::LocationLink {
423 origin_selection_range, 427 origin_selection_range,
424 target_uri, 428 target_uri,
@@ -429,12 +433,12 @@ pub(crate) fn location_link(
429} 433}
430 434
431fn location_info( 435fn location_info(
432 world: &WorldSnapshot, 436 snap: &GlobalStateSnapshot,
433 target: NavigationTarget, 437 target: NavigationTarget,
434) -> Result<(lsp_types::Url, lsp_types::Range, lsp_types::Range)> { 438) -> Result<(lsp_types::Url, lsp_types::Range, lsp_types::Range)> {
435 let line_index = world.analysis().file_line_index(target.file_id())?; 439 let line_index = snap.analysis().file_line_index(target.file_id())?;
436 440
437 let target_uri = url(world, target.file_id())?; 441 let target_uri = url(snap, target.file_id())?;
438 let target_range = range(&line_index, target.full_range()); 442 let target_range = range(&line_index, target.full_range());
439 let target_selection_range = 443 let target_selection_range =
440 target.focus_range().map(|it| range(&line_index, it)).unwrap_or(target_range); 444 target.focus_range().map(|it| range(&line_index, it)).unwrap_or(target_range);
@@ -442,14 +446,14 @@ fn location_info(
442} 446}
443 447
444pub(crate) fn goto_definition_response( 448pub(crate) fn goto_definition_response(
445 world: &WorldSnapshot, 449 snap: &GlobalStateSnapshot,
446 src: Option<FileRange>, 450 src: Option<FileRange>,
447 targets: Vec<NavigationTarget>, 451 targets: Vec<NavigationTarget>,
448) -> Result<lsp_types::GotoDefinitionResponse> { 452) -> Result<lsp_types::GotoDefinitionResponse> {
449 if world.config.client_caps.location_link { 453 if snap.config.client_caps.location_link {
450 let links = targets 454 let links = targets
451 .into_iter() 455 .into_iter()
452 .map(|nav| location_link(world, src, nav)) 456 .map(|nav| location_link(snap, src, nav))
453 .collect::<Result<Vec<_>>>()?; 457 .collect::<Result<Vec<_>>>()?;
454 Ok(links.into()) 458 Ok(links.into())
455 } else { 459 } else {
@@ -457,7 +461,7 @@ pub(crate) fn goto_definition_response(
457 .into_iter() 461 .into_iter()
458 .map(|nav| { 462 .map(|nav| {
459 location( 463 location(
460 world, 464 snap,
461 FileRange { 465 FileRange {
462 file_id: nav.file_id(), 466 file_id: nav.file_id(),
463 range: nav.focus_range().unwrap_or(nav.range()), 467 range: nav.focus_range().unwrap_or(nav.range()),
@@ -470,13 +474,13 @@ pub(crate) fn goto_definition_response(
470} 474}
471 475
472pub(crate) fn snippet_text_document_edit( 476pub(crate) fn snippet_text_document_edit(
473 world: &WorldSnapshot, 477 snap: &GlobalStateSnapshot,
474 is_snippet: bool, 478 is_snippet: bool,
475 source_file_edit: SourceFileEdit, 479 source_file_edit: SourceFileEdit,
476) -> Result<lsp_ext::SnippetTextDocumentEdit> { 480) -> Result<lsp_ext::SnippetTextDocumentEdit> {
477 let text_document = versioned_text_document_identifier(world, source_file_edit.file_id, None)?; 481 let text_document = versioned_text_document_identifier(snap, source_file_edit.file_id, None)?;
478 let line_index = world.analysis().file_line_index(source_file_edit.file_id)?; 482 let line_index = snap.analysis().file_line_index(source_file_edit.file_id)?;
479 let line_endings = world.file_line_endings(source_file_edit.file_id); 483 let line_endings = snap.file_line_endings(source_file_edit.file_id);
480 let edits = source_file_edit 484 let edits = source_file_edit
481 .edit 485 .edit
482 .into_iter() 486 .into_iter()
@@ -486,17 +490,17 @@ pub(crate) fn snippet_text_document_edit(
486} 490}
487 491
488pub(crate) fn resource_op( 492pub(crate) fn resource_op(
489 world: &WorldSnapshot, 493 snap: &GlobalStateSnapshot,
490 file_system_edit: FileSystemEdit, 494 file_system_edit: FileSystemEdit,
491) -> Result<lsp_types::ResourceOp> { 495) -> Result<lsp_types::ResourceOp> {
492 let res = match file_system_edit { 496 let res = match file_system_edit {
493 FileSystemEdit::CreateFile { source_root, path } => { 497 FileSystemEdit::CreateFile { source_root, path } => {
494 let uri = world.path_to_uri(source_root, &path)?; 498 let uri = snap.path_to_uri(source_root, &path)?;
495 lsp_types::ResourceOp::Create(lsp_types::CreateFile { uri, options: None }) 499 lsp_types::ResourceOp::Create(lsp_types::CreateFile { uri, options: None })
496 } 500 }
497 FileSystemEdit::MoveFile { src, dst_source_root, dst_path } => { 501 FileSystemEdit::MoveFile { src, dst_source_root, dst_path } => {
498 let old_uri = world.file_id_to_uri(src)?; 502 let old_uri = snap.file_id_to_uri(src)?;
499 let new_uri = world.path_to_uri(dst_source_root, &dst_path)?; 503 let new_uri = snap.path_to_uri(dst_source_root, &dst_path)?;
500 lsp_types::ResourceOp::Rename(lsp_types::RenameFile { old_uri, new_uri, options: None }) 504 lsp_types::ResourceOp::Rename(lsp_types::RenameFile { old_uri, new_uri, options: None })
501 } 505 }
502 }; 506 };
@@ -504,16 +508,16 @@ pub(crate) fn resource_op(
504} 508}
505 509
506pub(crate) fn snippet_workspace_edit( 510pub(crate) fn snippet_workspace_edit(
507 world: &WorldSnapshot, 511 snap: &GlobalStateSnapshot,
508 source_change: SourceChange, 512 source_change: SourceChange,
509) -> Result<lsp_ext::SnippetWorkspaceEdit> { 513) -> Result<lsp_ext::SnippetWorkspaceEdit> {
510 let mut document_changes: Vec<lsp_ext::SnippetDocumentChangeOperation> = Vec::new(); 514 let mut document_changes: Vec<lsp_ext::SnippetDocumentChangeOperation> = Vec::new();
511 for op in source_change.file_system_edits { 515 for op in source_change.file_system_edits {
512 let op = resource_op(&world, op)?; 516 let op = resource_op(&snap, op)?;
513 document_changes.push(lsp_ext::SnippetDocumentChangeOperation::Op(op)); 517 document_changes.push(lsp_ext::SnippetDocumentChangeOperation::Op(op));
514 } 518 }
515 for edit in source_change.source_file_edits { 519 for edit in source_change.source_file_edits {
516 let edit = snippet_text_document_edit(&world, source_change.is_snippet, edit)?; 520 let edit = snippet_text_document_edit(&snap, source_change.is_snippet, edit)?;
517 document_changes.push(lsp_ext::SnippetDocumentChangeOperation::Edit(edit)); 521 document_changes.push(lsp_ext::SnippetDocumentChangeOperation::Edit(edit));
518 } 522 }
519 let workspace_edit = 523 let workspace_edit =
@@ -522,11 +526,11 @@ pub(crate) fn snippet_workspace_edit(
522} 526}
523 527
524pub(crate) fn workspace_edit( 528pub(crate) fn workspace_edit(
525 world: &WorldSnapshot, 529 snap: &GlobalStateSnapshot,
526 source_change: SourceChange, 530 source_change: SourceChange,
527) -> Result<lsp_types::WorkspaceEdit> { 531) -> Result<lsp_types::WorkspaceEdit> {
528 assert!(!source_change.is_snippet); 532 assert!(!source_change.is_snippet);
529 snippet_workspace_edit(world, source_change).map(|it| it.into()) 533 snippet_workspace_edit(snap, source_change).map(|it| it.into())
530} 534}
531 535
532impl From<lsp_ext::SnippetWorkspaceEdit> for lsp_types::WorkspaceEdit { 536impl From<lsp_ext::SnippetWorkspaceEdit> for lsp_types::WorkspaceEdit {
@@ -565,13 +569,13 @@ impl From<lsp_ext::SnippetWorkspaceEdit> for lsp_types::WorkspaceEdit {
565} 569}
566 570
567pub fn call_hierarchy_item( 571pub fn call_hierarchy_item(
568 world: &WorldSnapshot, 572 snap: &GlobalStateSnapshot,
569 target: NavigationTarget, 573 target: NavigationTarget,
570) -> Result<lsp_types::CallHierarchyItem> { 574) -> Result<lsp_types::CallHierarchyItem> {
571 let name = target.name().to_string(); 575 let name = target.name().to_string();
572 let detail = target.description().map(|it| it.to_string()); 576 let detail = target.description().map(|it| it.to_string());
573 let kind = symbol_kind(target.kind()); 577 let kind = symbol_kind(target.kind());
574 let (uri, range, selection_range) = location_info(world, target)?; 578 let (uri, range, selection_range) = location_info(snap, target)?;
575 Ok(lsp_types::CallHierarchyItem { name, kind, tags: None, detail, uri, range, selection_range }) 579 Ok(lsp_types::CallHierarchyItem { name, kind, tags: None, detail, uri, range, selection_range })
576} 580}
577 581
@@ -619,23 +623,26 @@ fn main() <fold>{
619 } 623 }
620} 624}
621 625
622pub(crate) fn code_action(world: &WorldSnapshot, assist: Assist) -> Result<lsp_ext::CodeAction> { 626pub(crate) fn code_action(
627 snap: &GlobalStateSnapshot,
628 assist: Assist,
629) -> Result<lsp_ext::CodeAction> {
623 let res = lsp_ext::CodeAction { 630 let res = lsp_ext::CodeAction {
624 title: assist.label, 631 title: assist.label,
625 group: if world.config.client_caps.code_action_group { assist.group_label } else { None }, 632 group: if snap.config.client_caps.code_action_group { assist.group_label } else { None },
626 kind: Some(String::new()), 633 kind: Some(String::new()),
627 edit: Some(snippet_workspace_edit(world, assist.source_change)?), 634 edit: Some(snippet_workspace_edit(snap, assist.source_change)?),
628 command: None, 635 command: None,
629 }; 636 };
630 Ok(res) 637 Ok(res)
631} 638}
632 639
633pub(crate) fn runnable( 640pub(crate) fn runnable(
634 world: &WorldSnapshot, 641 snap: &GlobalStateSnapshot,
635 file_id: FileId, 642 file_id: FileId,
636 runnable: Runnable, 643 runnable: Runnable,
637) -> Result<lsp_ext::Runnable> { 644) -> Result<lsp_ext::Runnable> {
638 let spec = CargoTargetSpec::for_file(world, file_id)?; 645 let spec = CargoTargetSpec::for_file(snap, file_id)?;
639 let target = spec.as_ref().map(|s| s.target.clone()); 646 let target = spec.as_ref().map(|s| s.target.clone());
640 let (cargo_args, executable_args) = 647 let (cargo_args, executable_args) =
641 CargoTargetSpec::runnable_args(spec, &runnable.kind, &runnable.cfg_exprs)?; 648 CargoTargetSpec::runnable_args(spec, &runnable.kind, &runnable.cfg_exprs)?;
@@ -648,14 +655,14 @@ pub(crate) fn runnable(
648 target.map_or_else(|| "run binary".to_string(), |t| format!("run {}", t)) 655 target.map_or_else(|| "run binary".to_string(), |t| format!("run {}", t))
649 } 656 }
650 }; 657 };
651 let location = location_link(world, None, runnable.nav)?; 658 let location = location_link(snap, None, runnable.nav)?;
652 659
653 Ok(lsp_ext::Runnable { 660 Ok(lsp_ext::Runnable {
654 label, 661 label,
655 location: Some(location), 662 location: Some(location),
656 kind: lsp_ext::RunnableKind::Cargo, 663 kind: lsp_ext::RunnableKind::Cargo,
657 args: lsp_ext::CargoRunnable { 664 args: lsp_ext::CargoRunnable {
658 workspace_root: world.workspace_root_for(file_id).map(|root| root.to_owned()), 665 workspace_root: snap.workspace_root_for(file_id).map(|root| root.to_owned()),
659 cargo_args, 666 cargo_args,
660 executable_args, 667 executable_args,
661 }, 668 },