diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_cargo_watch/Cargo.toml | 1 | ||||
-rw-r--r-- | crates/ra_cargo_watch/src/lib.rs | 61 | ||||
-rw-r--r-- | crates/ra_prof/src/lib.rs | 8 | ||||
-rw-r--r-- | crates/rust-analyzer/src/main_loop.rs | 55 | ||||
-rw-r--r-- | crates/rust-analyzer/src/world.rs | 15 | ||||
-rw-r--r-- | crates/rust-analyzer/tests/heavy_tests/support.rs | 3 |
6 files changed, 59 insertions, 84 deletions
diff --git a/crates/ra_cargo_watch/Cargo.toml b/crates/ra_cargo_watch/Cargo.toml index 741345a21..300033a18 100644 --- a/crates/ra_cargo_watch/Cargo.toml +++ b/crates/ra_cargo_watch/Cargo.toml | |||
@@ -10,6 +10,7 @@ lsp-types = { version = "0.73.0", features = ["proposed"] } | |||
10 | log = "0.4.8" | 10 | log = "0.4.8" |
11 | cargo_metadata = "0.9.1" | 11 | cargo_metadata = "0.9.1" |
12 | serde_json = "1.0.48" | 12 | serde_json = "1.0.48" |
13 | jod-thread = "0.1.1" | ||
13 | 14 | ||
14 | [dev-dependencies] | 15 | [dev-dependencies] |
15 | insta = "0.15.0" | 16 | insta = "0.15.0" |
diff --git a/crates/ra_cargo_watch/src/lib.rs b/crates/ra_cargo_watch/src/lib.rs index 7c525c430..c67ec39d4 100644 --- a/crates/ra_cargo_watch/src/lib.rs +++ b/crates/ra_cargo_watch/src/lib.rs | |||
@@ -12,7 +12,6 @@ use std::{ | |||
12 | io::{BufRead, BufReader}, | 12 | io::{BufRead, BufReader}, |
13 | path::{Path, PathBuf}, | 13 | path::{Path, PathBuf}, |
14 | process::{Command, Stdio}, | 14 | process::{Command, Stdio}, |
15 | thread::JoinHandle, | ||
16 | time::Instant, | 15 | time::Instant, |
17 | }; | 16 | }; |
18 | 17 | ||
@@ -36,9 +35,10 @@ pub struct CheckOptions { | |||
36 | /// The spawned thread is shut down when this struct is dropped. | 35 | /// The spawned thread is shut down when this struct is dropped. |
37 | #[derive(Debug)] | 36 | #[derive(Debug)] |
38 | pub struct CheckWatcher { | 37 | pub struct CheckWatcher { |
38 | // XXX: drop order is significant | ||
39 | cmd_send: Sender<CheckCommand>, | ||
40 | handle: Option<jod_thread::JoinHandle<()>>, | ||
39 | pub task_recv: Receiver<CheckTask>, | 41 | pub task_recv: Receiver<CheckTask>, |
40 | cmd_send: Option<Sender<CheckCommand>>, | ||
41 | handle: Option<JoinHandle<()>>, | ||
42 | } | 42 | } |
43 | 43 | ||
44 | impl CheckWatcher { | 44 | impl CheckWatcher { |
@@ -47,39 +47,16 @@ impl CheckWatcher { | |||
47 | 47 | ||
48 | let (task_send, task_recv) = unbounded::<CheckTask>(); | 48 | let (task_send, task_recv) = unbounded::<CheckTask>(); |
49 | let (cmd_send, cmd_recv) = unbounded::<CheckCommand>(); | 49 | let (cmd_send, cmd_recv) = unbounded::<CheckCommand>(); |
50 | let handle = std::thread::spawn(move || { | 50 | let handle = jod_thread::spawn(move || { |
51 | let mut check = CheckWatcherThread::new(options, workspace_root); | 51 | let mut check = CheckWatcherThread::new(options, workspace_root); |
52 | check.run(&task_send, &cmd_recv); | 52 | check.run(&task_send, &cmd_recv); |
53 | }); | 53 | }); |
54 | CheckWatcher { task_recv, cmd_send: Some(cmd_send), handle: Some(handle) } | 54 | CheckWatcher { task_recv, cmd_send, handle: Some(handle) } |
55 | } | ||
56 | |||
57 | /// Returns a CheckWatcher that doesn't actually do anything | ||
58 | pub fn dummy() -> CheckWatcher { | ||
59 | CheckWatcher { task_recv: never(), cmd_send: None, handle: None } | ||
60 | } | 55 | } |
61 | 56 | ||
62 | /// Schedule a re-start of the cargo check worker. | 57 | /// Schedule a re-start of the cargo check worker. |
63 | pub fn update(&self) { | 58 | pub fn update(&self) { |
64 | if let Some(cmd_send) = &self.cmd_send { | 59 | self.cmd_send.send(CheckCommand::Update).unwrap(); |
65 | cmd_send.send(CheckCommand::Update).unwrap(); | ||
66 | } | ||
67 | } | ||
68 | } | ||
69 | |||
70 | impl std::ops::Drop for CheckWatcher { | ||
71 | fn drop(&mut self) { | ||
72 | if let Some(handle) = self.handle.take() { | ||
73 | // Take the sender out of the option | ||
74 | let cmd_send = self.cmd_send.take(); | ||
75 | |||
76 | // Dropping the sender finishes the thread loop | ||
77 | drop(cmd_send); | ||
78 | |||
79 | // Join the thread, it should finish shortly. We don't really care | ||
80 | // whether it panicked, so it is safe to ignore the result | ||
81 | let _ = handle.join(); | ||
82 | } | ||
83 | } | 60 | } |
84 | } | 61 | } |
85 | 62 | ||
@@ -237,8 +214,9 @@ pub struct DiagnosticWithFixes { | |||
237 | /// The correct way to dispose of the thread is to drop it, on which the | 214 | /// The correct way to dispose of the thread is to drop it, on which the |
238 | /// sub-process will be killed, and the thread will be joined. | 215 | /// sub-process will be killed, and the thread will be joined. |
239 | struct WatchThread { | 216 | struct WatchThread { |
240 | handle: Option<JoinHandle<()>>, | 217 | // XXX: drop order is significant |
241 | message_recv: Receiver<CheckEvent>, | 218 | message_recv: Receiver<CheckEvent>, |
219 | _handle: Option<jod_thread::JoinHandle<()>>, | ||
242 | } | 220 | } |
243 | 221 | ||
244 | enum CheckEvent { | 222 | enum CheckEvent { |
@@ -333,7 +311,7 @@ pub fn run_cargo( | |||
333 | 311 | ||
334 | impl WatchThread { | 312 | impl WatchThread { |
335 | fn dummy() -> WatchThread { | 313 | fn dummy() -> WatchThread { |
336 | WatchThread { handle: None, message_recv: never() } | 314 | WatchThread { message_recv: never(), _handle: None } |
337 | } | 315 | } |
338 | 316 | ||
339 | fn new(options: &CheckOptions, workspace_root: &Path) -> WatchThread { | 317 | fn new(options: &CheckOptions, workspace_root: &Path) -> WatchThread { |
@@ -352,7 +330,7 @@ impl WatchThread { | |||
352 | let (message_send, message_recv) = unbounded(); | 330 | let (message_send, message_recv) = unbounded(); |
353 | let workspace_root = workspace_root.to_owned(); | 331 | let workspace_root = workspace_root.to_owned(); |
354 | let handle = if options.enable { | 332 | let handle = if options.enable { |
355 | Some(std::thread::spawn(move || { | 333 | Some(jod_thread::spawn(move || { |
356 | // If we trigger an error here, we will do so in the loop instead, | 334 | // If we trigger an error here, we will do so in the loop instead, |
357 | // which will break out of the loop, and continue the shutdown | 335 | // which will break out of the loop, and continue the shutdown |
358 | let _ = message_send.send(CheckEvent::Begin); | 336 | let _ = message_send.send(CheckEvent::Begin); |
@@ -383,23 +361,6 @@ impl WatchThread { | |||
383 | } else { | 361 | } else { |
384 | None | 362 | None |
385 | }; | 363 | }; |
386 | WatchThread { handle, message_recv } | 364 | WatchThread { message_recv, _handle: handle } |
387 | } | ||
388 | } | ||
389 | |||
390 | impl std::ops::Drop for WatchThread { | ||
391 | fn drop(&mut self) { | ||
392 | if let Some(handle) = self.handle.take() { | ||
393 | // Replace our reciever with dummy one, so we can drop and close the | ||
394 | // one actually communicating with the thread | ||
395 | let recv = std::mem::replace(&mut self.message_recv, never()); | ||
396 | |||
397 | // Dropping the original reciever initiates thread sub-process shutdown | ||
398 | drop(recv); | ||
399 | |||
400 | // Join the thread, it should finish shortly. We don't really care | ||
401 | // whether it panicked, so it is safe to ignore the result | ||
402 | let _ = handle.join(); | ||
403 | } | ||
404 | } | 365 | } |
405 | } | 366 | } |
diff --git a/crates/ra_prof/src/lib.rs b/crates/ra_prof/src/lib.rs index 9e167db96..00ea3a9b0 100644 --- a/crates/ra_prof/src/lib.rs +++ b/crates/ra_prof/src/lib.rs | |||
@@ -339,6 +339,14 @@ pub fn print_backtrace() { | |||
339 | let bt = backtrace::Backtrace::new(); | 339 | let bt = backtrace::Backtrace::new(); |
340 | eprintln!("{:?}", bt); | 340 | eprintln!("{:?}", bt); |
341 | } | 341 | } |
342 | #[cfg(not(feature = "backtrace"))] | ||
343 | pub fn print_backtrace() { | ||
344 | eprintln!( | ||
345 | r#"enable the backtrace feature: | ||
346 | ra_prof = {{ path = "../ra_prof", features = [ "backtrace"] }} | ||
347 | "# | ||
348 | ); | ||
349 | } | ||
342 | 350 | ||
343 | thread_local!(static IN_SCOPE: RefCell<bool> = RefCell::new(false)); | 351 | thread_local!(static IN_SCOPE: RefCell<bool> = RefCell::new(false)); |
344 | 352 | ||
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index 7825b0077..c899ff677 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs | |||
@@ -14,7 +14,7 @@ use std::{ | |||
14 | time::{Duration, Instant}, | 14 | time::{Duration, Instant}, |
15 | }; | 15 | }; |
16 | 16 | ||
17 | use crossbeam_channel::{select, unbounded, RecvError, Sender}; | 17 | use crossbeam_channel::{never, select, unbounded, RecvError, Sender}; |
18 | use lsp_server::{Connection, ErrorCode, Message, Notification, Request, RequestId, Response}; | 18 | use lsp_server::{Connection, ErrorCode, Message, Notification, Request, RequestId, Response}; |
19 | use lsp_types::{ | 19 | use lsp_types::{ |
20 | ClientCapabilities, NumberOrString, WorkDoneProgress, WorkDoneProgressBegin, | 20 | ClientCapabilities, NumberOrString, WorkDoneProgress, WorkDoneProgressBegin, |
@@ -208,6 +208,9 @@ pub fn main_loop( | |||
208 | ) | 208 | ) |
209 | }; | 209 | }; |
210 | 210 | ||
211 | loop_state.roots_total = world_state.vfs.read().n_roots(); | ||
212 | loop_state.roots_scanned = 0; | ||
213 | |||
211 | let pool = ThreadPool::default(); | 214 | let pool = ThreadPool::default(); |
212 | let (task_sender, task_receiver) = unbounded::<Task>(); | 215 | let (task_sender, task_receiver) = unbounded::<Task>(); |
213 | let (libdata_sender, libdata_receiver) = unbounded::<LibraryData>(); | 216 | let (libdata_sender, libdata_receiver) = unbounded::<LibraryData>(); |
@@ -229,7 +232,7 @@ pub fn main_loop( | |||
229 | Err(RecvError) => return Err("vfs died".into()), | 232 | Err(RecvError) => return Err("vfs died".into()), |
230 | }, | 233 | }, |
231 | recv(libdata_receiver) -> data => Event::Lib(data.unwrap()), | 234 | recv(libdata_receiver) -> data => Event::Lib(data.unwrap()), |
232 | recv(world_state.check_watcher.task_recv) -> task => match task { | 235 | recv(world_state.check_watcher.as_ref().map_or(&never(), |it| &it.task_recv)) -> task => match task { |
233 | Ok(task) => Event::CheckWatcher(task), | 236 | Ok(task) => Event::CheckWatcher(task), |
234 | Err(RecvError) => return Err("check watcher died".into()), | 237 | Err(RecvError) => return Err("check watcher died".into()), |
235 | } | 238 | } |
@@ -333,7 +336,10 @@ struct LoopState { | |||
333 | in_flight_libraries: usize, | 336 | in_flight_libraries: usize, |
334 | pending_libraries: Vec<(SourceRootId, Vec<(FileId, RelativePathBuf, Arc<String>)>)>, | 337 | pending_libraries: Vec<(SourceRootId, Vec<(FileId, RelativePathBuf, Arc<String>)>)>, |
335 | workspace_loaded: bool, | 338 | workspace_loaded: bool, |
336 | roots_scanned_progress: Option<usize>, | 339 | |
340 | roots_progress_reported: Option<usize>, | ||
341 | roots_scanned: usize, | ||
342 | roots_total: usize, | ||
337 | } | 343 | } |
338 | 344 | ||
339 | impl LoopState { | 345 | impl LoopState { |
@@ -377,6 +383,7 @@ fn loop_turn( | |||
377 | world_state.add_lib(lib); | 383 | world_state.add_lib(lib); |
378 | world_state.maybe_collect_garbage(); | 384 | world_state.maybe_collect_garbage(); |
379 | loop_state.in_flight_libraries -= 1; | 385 | loop_state.in_flight_libraries -= 1; |
386 | loop_state.roots_scanned += 1; | ||
380 | } | 387 | } |
381 | Event::CheckWatcher(task) => on_check_task(task, world_state, task_sender)?, | 388 | Event::CheckWatcher(task) => on_check_task(task, world_state, task_sender)?, |
382 | Event::Msg(msg) => match msg { | 389 | Event::Msg(msg) => match msg { |
@@ -408,7 +415,7 @@ fn loop_turn( | |||
408 | }; | 415 | }; |
409 | 416 | ||
410 | let mut state_changed = false; | 417 | let mut state_changed = false; |
411 | if let Some(changes) = world_state.process_changes() { | 418 | if let Some(changes) = world_state.process_changes(&mut loop_state.roots_scanned) { |
412 | state_changed = true; | 419 | state_changed = true; |
413 | loop_state.pending_libraries.extend(changes); | 420 | loop_state.pending_libraries.extend(changes); |
414 | } | 421 | } |
@@ -427,21 +434,27 @@ fn loop_turn( | |||
427 | }); | 434 | }); |
428 | } | 435 | } |
429 | 436 | ||
437 | let show_progress = !loop_state.workspace_loaded | ||
438 | && world_state.feature_flags.get("notifications.workspace-loaded"); | ||
439 | |||
430 | if !loop_state.workspace_loaded | 440 | if !loop_state.workspace_loaded |
431 | && world_state.roots_to_scan == 0 | 441 | && loop_state.roots_scanned == loop_state.roots_total |
432 | && loop_state.pending_libraries.is_empty() | 442 | && loop_state.pending_libraries.is_empty() |
433 | && loop_state.in_flight_libraries == 0 | 443 | && loop_state.in_flight_libraries == 0 |
434 | { | 444 | { |
435 | loop_state.workspace_loaded = true; | 445 | loop_state.workspace_loaded = true; |
436 | world_state.check_watcher.update(); | 446 | if let Some(check_watcher) = &world_state.check_watcher { |
447 | check_watcher.update(); | ||
448 | } | ||
437 | pool.execute({ | 449 | pool.execute({ |
438 | let subs = loop_state.subscriptions.subscriptions(); | 450 | let subs = loop_state.subscriptions.subscriptions(); |
439 | let snap = world_state.snapshot(); | 451 | let snap = world_state.snapshot(); |
440 | move || snap.analysis().prime_caches(subs).unwrap_or_else(|_: Canceled| ()) | 452 | move || snap.analysis().prime_caches(subs).unwrap_or_else(|_: Canceled| ()) |
441 | }); | 453 | }); |
442 | send_startup_progress(&connection.sender, loop_state, world_state); | 454 | } |
443 | } else if !loop_state.workspace_loaded { | 455 | |
444 | send_startup_progress(&connection.sender, loop_state, world_state); | 456 | if show_progress { |
457 | send_startup_progress(&connection.sender, loop_state); | ||
445 | } | 458 | } |
446 | 459 | ||
447 | if state_changed { | 460 | if state_changed { |
@@ -604,7 +617,9 @@ fn on_notification( | |||
604 | }; | 617 | }; |
605 | let not = match notification_cast::<req::DidSaveTextDocument>(not) { | 618 | let not = match notification_cast::<req::DidSaveTextDocument>(not) { |
606 | Ok(_params) => { | 619 | Ok(_params) => { |
607 | state.check_watcher.update(); | 620 | if let Some(check_watcher) = &state.check_watcher { |
621 | check_watcher.update(); | ||
622 | } | ||
608 | return Ok(()); | 623 | return Ok(()); |
609 | } | 624 | } |
610 | Err(not) => not, | 625 | Err(not) => not, |
@@ -706,21 +721,13 @@ fn on_diagnostic_task(task: DiagnosticTask, msg_sender: &Sender<Message>, state: | |||
706 | } | 721 | } |
707 | } | 722 | } |
708 | 723 | ||
709 | fn send_startup_progress( | 724 | fn send_startup_progress(sender: &Sender<Message>, loop_state: &mut LoopState) { |
710 | sender: &Sender<Message>, | 725 | let total: usize = loop_state.roots_total; |
711 | loop_state: &mut LoopState, | 726 | let prev = loop_state.roots_progress_reported; |
712 | world_state: &WorldState, | 727 | let progress = loop_state.roots_scanned; |
713 | ) { | 728 | loop_state.roots_progress_reported = Some(progress); |
714 | if !world_state.feature_flags.get("notifications.workspace-loaded") { | ||
715 | return; | ||
716 | } | ||
717 | |||
718 | let total: usize = world_state.workspaces.iter().map(|it| it.n_packages()).sum(); | ||
719 | let prev_progress = loop_state.roots_scanned_progress; | ||
720 | let progress = total - world_state.roots_to_scan; | ||
721 | loop_state.roots_scanned_progress = Some(progress); | ||
722 | 729 | ||
723 | match (prev_progress, loop_state.workspace_loaded) { | 730 | match (prev, loop_state.workspace_loaded) { |
724 | (None, false) => { | 731 | (None, false) => { |
725 | let work_done_progress_create = request_new::<req::WorkDoneProgressCreate>( | 732 | let work_done_progress_create = request_new::<req::WorkDoneProgressCreate>( |
726 | loop_state.next_request_id(), | 733 | loop_state.next_request_id(), |
diff --git a/crates/rust-analyzer/src/world.rs b/crates/rust-analyzer/src/world.rs index 64a7b907e..ca045f93c 100644 --- a/crates/rust-analyzer/src/world.rs +++ b/crates/rust-analyzer/src/world.rs | |||
@@ -51,15 +51,13 @@ pub struct Options { | |||
51 | pub struct WorldState { | 51 | pub struct WorldState { |
52 | pub options: Options, | 52 | pub options: Options, |
53 | pub feature_flags: Arc<FeatureFlags>, | 53 | pub feature_flags: Arc<FeatureFlags>, |
54 | //FIXME: this belongs to `LoopState` rather than to `WorldState` | ||
55 | pub roots_to_scan: usize, | ||
56 | pub roots: Vec<PathBuf>, | 54 | pub roots: Vec<PathBuf>, |
57 | pub workspaces: Arc<Vec<ProjectWorkspace>>, | 55 | pub workspaces: Arc<Vec<ProjectWorkspace>>, |
58 | pub analysis_host: AnalysisHost, | 56 | pub analysis_host: AnalysisHost, |
59 | pub vfs: Arc<RwLock<Vfs>>, | 57 | pub vfs: Arc<RwLock<Vfs>>, |
60 | pub task_receiver: Receiver<VfsTask>, | 58 | pub task_receiver: Receiver<VfsTask>, |
61 | pub latest_requests: Arc<RwLock<LatestRequests>>, | 59 | pub latest_requests: Arc<RwLock<LatestRequests>>, |
62 | pub check_watcher: CheckWatcher, | 60 | pub check_watcher: Option<CheckWatcher>, |
63 | pub diagnostics: DiagnosticCollection, | 61 | pub diagnostics: DiagnosticCollection, |
64 | } | 62 | } |
65 | 63 | ||
@@ -123,7 +121,7 @@ impl WorldState { | |||
123 | let (task_sender, task_receiver) = unbounded(); | 121 | let (task_sender, task_receiver) = unbounded(); |
124 | let task_sender = Box::new(move |t| task_sender.send(t).unwrap()); | 122 | let task_sender = Box::new(move |t| task_sender.send(t).unwrap()); |
125 | let (mut vfs, vfs_roots) = Vfs::new(roots, task_sender, watch); | 123 | let (mut vfs, vfs_roots) = Vfs::new(roots, task_sender, watch); |
126 | let roots_to_scan = vfs_roots.len(); | 124 | |
127 | for r in vfs_roots { | 125 | for r in vfs_roots { |
128 | let vfs_root_path = vfs.root2path(r); | 126 | let vfs_root_path = vfs.root2path(r); |
129 | let is_local = folder_roots.iter().any(|it| vfs_root_path.starts_with(it)); | 127 | let is_local = folder_roots.iter().any(|it| vfs_root_path.starts_with(it)); |
@@ -178,11 +176,11 @@ impl WorldState { | |||
178 | }) | 176 | }) |
179 | .map(|cargo| { | 177 | .map(|cargo| { |
180 | let cargo_project_root = cargo.workspace_root().to_path_buf(); | 178 | let cargo_project_root = cargo.workspace_root().to_path_buf(); |
181 | CheckWatcher::new(&options.cargo_watch, cargo_project_root) | 179 | Some(CheckWatcher::new(&options.cargo_watch, cargo_project_root)) |
182 | }) | 180 | }) |
183 | .unwrap_or_else(|| { | 181 | .unwrap_or_else(|| { |
184 | log::warn!("Cargo check watching only supported for cargo workspaces, disabling"); | 182 | log::warn!("Cargo check watching only supported for cargo workspaces, disabling"); |
185 | CheckWatcher::dummy() | 183 | None |
186 | }); | 184 | }); |
187 | 185 | ||
188 | let mut analysis_host = AnalysisHost::new(lru_capacity); | 186 | let mut analysis_host = AnalysisHost::new(lru_capacity); |
@@ -190,7 +188,6 @@ impl WorldState { | |||
190 | WorldState { | 188 | WorldState { |
191 | options, | 189 | options, |
192 | feature_flags: Arc::new(feature_flags), | 190 | feature_flags: Arc::new(feature_flags), |
193 | roots_to_scan, | ||
194 | roots: folder_roots, | 191 | roots: folder_roots, |
195 | workspaces: Arc::new(workspaces), | 192 | workspaces: Arc::new(workspaces), |
196 | analysis_host, | 193 | analysis_host, |
@@ -206,6 +203,7 @@ impl WorldState { | |||
206 | /// FIXME: better API here | 203 | /// FIXME: better API here |
207 | pub fn process_changes( | 204 | pub fn process_changes( |
208 | &mut self, | 205 | &mut self, |
206 | roots_scanned: &mut usize, | ||
209 | ) -> Option<Vec<(SourceRootId, Vec<(FileId, RelativePathBuf, Arc<String>)>)>> { | 207 | ) -> Option<Vec<(SourceRootId, Vec<(FileId, RelativePathBuf, Arc<String>)>)>> { |
210 | let changes = self.vfs.write().commit_changes(); | 208 | let changes = self.vfs.write().commit_changes(); |
211 | if changes.is_empty() { | 209 | if changes.is_empty() { |
@@ -219,7 +217,7 @@ impl WorldState { | |||
219 | let root_path = self.vfs.read().root2path(root); | 217 | let root_path = self.vfs.read().root2path(root); |
220 | let is_local = self.roots.iter().any(|r| root_path.starts_with(r)); | 218 | let is_local = self.roots.iter().any(|r| root_path.starts_with(r)); |
221 | if is_local { | 219 | if is_local { |
222 | self.roots_to_scan -= 1; | 220 | *roots_scanned += 1; |
223 | for (file, path, text) in files { | 221 | for (file, path, text) in files { |
224 | change.add_file(SourceRootId(root.0), FileId(file.0), path, text); | 222 | change.add_file(SourceRootId(root.0), FileId(file.0), path, text); |
225 | } | 223 | } |
@@ -247,7 +245,6 @@ impl WorldState { | |||
247 | } | 245 | } |
248 | 246 | ||
249 | pub fn add_lib(&mut self, data: LibraryData) { | 247 | pub fn add_lib(&mut self, data: LibraryData) { |
250 | self.roots_to_scan -= 1; | ||
251 | let mut change = AnalysisChange::new(); | 248 | let mut change = AnalysisChange::new(); |
252 | change.add_library(data); | 249 | change.add_library(data); |
253 | self.analysis_host.apply_change(change); | 250 | self.analysis_host.apply_change(change); |
diff --git a/crates/rust-analyzer/tests/heavy_tests/support.rs b/crates/rust-analyzer/tests/heavy_tests/support.rs index 1d7062bdf..67f3c9332 100644 --- a/crates/rust-analyzer/tests/heavy_tests/support.rs +++ b/crates/rust-analyzer/tests/heavy_tests/support.rs | |||
@@ -83,9 +83,10 @@ pub fn project(fixture: &str) -> Server { | |||
83 | pub struct Server { | 83 | pub struct Server { |
84 | req_id: Cell<u64>, | 84 | req_id: Cell<u64>, |
85 | messages: RefCell<Vec<Message>>, | 85 | messages: RefCell<Vec<Message>>, |
86 | dir: TempDir, | ||
87 | _thread: jod_thread::JoinHandle<()>, | 86 | _thread: jod_thread::JoinHandle<()>, |
88 | client: Connection, | 87 | client: Connection, |
88 | /// XXX: remove the tempdir last | ||
89 | dir: TempDir, | ||
89 | } | 90 | } |
90 | 91 | ||
91 | impl Server { | 92 | impl Server { |