diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2020-07-10 14:35:46 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2020-07-10 14:35:46 +0100 |
commit | 9ab59e2162bf7dcb120378e0c2e9fd6dac39c107 (patch) | |
tree | 2dfd1838493bf62b3f790f3c7c5943993b15af0d /crates | |
parent | 0f7770ae43dd0d97686eb85fccb38801ff30117b (diff) | |
parent | d0a8f6a3eb5094af36a72ca01b290a494dfd7b16 (diff) |
Merge #5293
5293: Automatically reload project info on Cargo.toml changes r=matklad a=matklad
bors r+
🤖
Co-authored-by: Aleksey Kladov <[email protected]>
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_project_model/src/cargo_workspace.rs | 8 | ||||
-rw-r--r-- | crates/ra_project_model/src/lib.rs | 2 | ||||
-rw-r--r-- | crates/ra_project_model/src/sysroot.rs | 6 | ||||
-rw-r--r-- | crates/rust-analyzer/src/config.rs | 4 | ||||
-rw-r--r-- | crates/rust-analyzer/src/main_loop.rs | 20 | ||||
-rw-r--r-- | crates/rust-analyzer/src/reload.rs | 40 |
6 files changed, 52 insertions, 28 deletions
diff --git a/crates/ra_project_model/src/cargo_workspace.rs b/crates/ra_project_model/src/cargo_workspace.rs index 04f7eb741..6d1154056 100644 --- a/crates/ra_project_model/src/cargo_workspace.rs +++ b/crates/ra_project_model/src/cargo_workspace.rs | |||
@@ -24,7 +24,7 @@ use rustc_hash::FxHashMap; | |||
24 | /// | 24 | /// |
25 | /// We use absolute paths here, `cargo metadata` guarantees to always produce | 25 | /// We use absolute paths here, `cargo metadata` guarantees to always produce |
26 | /// abs paths. | 26 | /// abs paths. |
27 | #[derive(Debug, Clone)] | 27 | #[derive(Debug, Clone, Eq, PartialEq)] |
28 | pub struct CargoWorkspace { | 28 | pub struct CargoWorkspace { |
29 | packages: Arena<PackageData>, | 29 | packages: Arena<PackageData>, |
30 | targets: Arena<TargetData>, | 30 | targets: Arena<TargetData>, |
@@ -68,7 +68,7 @@ pub type Package = Idx<PackageData>; | |||
68 | 68 | ||
69 | pub type Target = Idx<TargetData>; | 69 | pub type Target = Idx<TargetData>; |
70 | 70 | ||
71 | #[derive(Debug, Clone)] | 71 | #[derive(Debug, Clone, Eq, PartialEq)] |
72 | pub struct PackageData { | 72 | pub struct PackageData { |
73 | pub version: String, | 73 | pub version: String, |
74 | pub name: String, | 74 | pub name: String, |
@@ -83,13 +83,13 @@ pub struct PackageData { | |||
83 | pub proc_macro_dylib_path: Option<AbsPathBuf>, | 83 | pub proc_macro_dylib_path: Option<AbsPathBuf>, |
84 | } | 84 | } |
85 | 85 | ||
86 | #[derive(Debug, Clone)] | 86 | #[derive(Debug, Clone, Eq, PartialEq)] |
87 | pub struct PackageDependency { | 87 | pub struct PackageDependency { |
88 | pub pkg: Package, | 88 | pub pkg: Package, |
89 | pub name: String, | 89 | pub name: String, |
90 | } | 90 | } |
91 | 91 | ||
92 | #[derive(Debug, Clone)] | 92 | #[derive(Debug, Clone, Eq, PartialEq)] |
93 | pub struct TargetData { | 93 | pub struct TargetData { |
94 | pub package: Package, | 94 | pub package: Package, |
95 | pub name: String, | 95 | pub name: String, |
diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs index 5d1f871c4..b9c5424bf 100644 --- a/crates/ra_project_model/src/lib.rs +++ b/crates/ra_project_model/src/lib.rs | |||
@@ -24,7 +24,7 @@ pub use crate::{ | |||
24 | }; | 24 | }; |
25 | pub use ra_proc_macro::ProcMacroClient; | 25 | pub use ra_proc_macro::ProcMacroClient; |
26 | 26 | ||
27 | #[derive(Debug, Clone)] | 27 | #[derive(Debug, Clone, Eq, PartialEq)] |
28 | pub enum ProjectWorkspace { | 28 | pub enum ProjectWorkspace { |
29 | /// Project workspace was discovered by running `cargo metadata` and `rustc --print sysroot`. | 29 | /// Project workspace was discovered by running `cargo metadata` and `rustc --print sysroot`. |
30 | Cargo { cargo: CargoWorkspace, sysroot: Sysroot }, | 30 | Cargo { cargo: CargoWorkspace, sysroot: Sysroot }, |
diff --git a/crates/ra_project_model/src/sysroot.rs b/crates/ra_project_model/src/sysroot.rs index fc1673ede..68d134da4 100644 --- a/crates/ra_project_model/src/sysroot.rs +++ b/crates/ra_project_model/src/sysroot.rs | |||
@@ -3,19 +3,19 @@ | |||
3 | use std::{convert::TryFrom, env, ops, path::Path, process::Command}; | 3 | use std::{convert::TryFrom, env, ops, path::Path, process::Command}; |
4 | 4 | ||
5 | use anyhow::{bail, format_err, Result}; | 5 | use anyhow::{bail, format_err, Result}; |
6 | use paths::{AbsPath, AbsPathBuf}; | ||
6 | use ra_arena::{Arena, Idx}; | 7 | use ra_arena::{Arena, Idx}; |
7 | 8 | ||
8 | use crate::output; | 9 | use crate::output; |
9 | use paths::{AbsPath, AbsPathBuf}; | ||
10 | 10 | ||
11 | #[derive(Default, Debug, Clone)] | 11 | #[derive(Default, Debug, Clone, Eq, PartialEq)] |
12 | pub struct Sysroot { | 12 | pub struct Sysroot { |
13 | crates: Arena<SysrootCrateData>, | 13 | crates: Arena<SysrootCrateData>, |
14 | } | 14 | } |
15 | 15 | ||
16 | pub type SysrootCrate = Idx<SysrootCrateData>; | 16 | pub type SysrootCrate = Idx<SysrootCrateData>; |
17 | 17 | ||
18 | #[derive(Debug, Clone)] | 18 | #[derive(Debug, Clone, Eq, PartialEq)] |
19 | pub struct SysrootCrateData { | 19 | pub struct SysrootCrateData { |
20 | pub name: String, | 20 | pub name: String, |
21 | pub root: AbsPathBuf, | 21 | pub root: AbsPathBuf, |
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 9dd81b4fc..ed5e52871 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs | |||
@@ -29,6 +29,7 @@ pub struct Config { | |||
29 | pub files: FilesConfig, | 29 | pub files: FilesConfig, |
30 | pub notifications: NotificationsConfig, | 30 | pub notifications: NotificationsConfig, |
31 | 31 | ||
32 | pub cargo_autoreload: bool, | ||
32 | pub cargo: CargoConfig, | 33 | pub cargo: CargoConfig, |
33 | pub rustfmt: RustfmtConfig, | 34 | pub rustfmt: RustfmtConfig, |
34 | pub flycheck: Option<FlycheckConfig>, | 35 | pub flycheck: Option<FlycheckConfig>, |
@@ -141,6 +142,7 @@ impl Config { | |||
141 | files: FilesConfig { watcher: FilesWatcher::Notify, exclude: Vec::new() }, | 142 | files: FilesConfig { watcher: FilesWatcher::Notify, exclude: Vec::new() }, |
142 | notifications: NotificationsConfig { cargo_toml_not_found: true }, | 143 | notifications: NotificationsConfig { cargo_toml_not_found: true }, |
143 | 144 | ||
145 | cargo_autoreload: true, | ||
144 | cargo: CargoConfig::default(), | 146 | cargo: CargoConfig::default(), |
145 | rustfmt: RustfmtConfig::Rustfmt { extra_args: Vec::new() }, | 147 | rustfmt: RustfmtConfig::Rustfmt { extra_args: Vec::new() }, |
146 | flycheck: Some(FlycheckConfig::CargoCommand { | 148 | flycheck: Some(FlycheckConfig::CargoCommand { |
@@ -189,6 +191,7 @@ impl Config { | |||
189 | }; | 191 | }; |
190 | self.notifications = | 192 | self.notifications = |
191 | NotificationsConfig { cargo_toml_not_found: data.notifications_cargoTomlNotFound }; | 193 | NotificationsConfig { cargo_toml_not_found: data.notifications_cargoTomlNotFound }; |
194 | self.cargo_autoreload = data.cargo_autoreload; | ||
192 | self.cargo = CargoConfig { | 195 | self.cargo = CargoConfig { |
193 | no_default_features: data.cargo_noDefaultFeatures, | 196 | no_default_features: data.cargo_noDefaultFeatures, |
194 | all_features: data.cargo_allFeatures, | 197 | all_features: data.cargo_allFeatures, |
@@ -364,6 +367,7 @@ config_data! { | |||
364 | struct ConfigData { | 367 | struct ConfigData { |
365 | callInfo_full: bool = true, | 368 | callInfo_full: bool = true, |
366 | 369 | ||
370 | cargo_autoreload: bool = true, | ||
367 | cargo_allFeatures: bool = false, | 371 | cargo_allFeatures: bool = false, |
368 | cargo_features: Vec<String> = Vec::new(), | 372 | cargo_features: Vec<String> = Vec::new(), |
369 | cargo_loadOutDirsFromCheck: bool = false, | 373 | cargo_loadOutDirsFromCheck: bool = false, |
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index b48239058..96e2399ce 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs | |||
@@ -314,19 +314,6 @@ impl GlobalState { | |||
314 | Ok(()) | 314 | Ok(()) |
315 | } | 315 | } |
316 | 316 | ||
317 | fn transition(&mut self, new_status: Status) { | ||
318 | self.status = Status::Ready; | ||
319 | if self.config.client_caps.status_notification { | ||
320 | let lsp_status = match new_status { | ||
321 | Status::Loading => lsp_ext::Status::Loading, | ||
322 | Status::Ready => lsp_ext::Status::Ready, | ||
323 | Status::Invalid => lsp_ext::Status::Invalid, | ||
324 | Status::NeedsReload => lsp_ext::Status::NeedsReload, | ||
325 | }; | ||
326 | self.send_notification::<lsp_ext::StatusNotification>(lsp_status); | ||
327 | } | ||
328 | } | ||
329 | |||
330 | fn on_request(&mut self, request_received: Instant, req: Request) -> Result<()> { | 317 | fn on_request(&mut self, request_received: Instant, req: Request) -> Result<()> { |
331 | self.register_request(&req, request_received); | 318 | self.register_request(&req, request_received); |
332 | 319 | ||
@@ -441,12 +428,7 @@ impl GlobalState { | |||
441 | if let Some(flycheck) = &this.flycheck { | 428 | if let Some(flycheck) = &this.flycheck { |
442 | flycheck.handle.update(); | 429 | flycheck.handle.update(); |
443 | } | 430 | } |
444 | let uri = params.text_document.uri.as_str(); | 431 | this.maybe_refresh(params.text_document.uri.as_str()); |
445 | if uri.ends_with("Cargo.toml") || uri.ends_with("Cargo.lock") { | ||
446 | if matches!(this.status, Status::Ready | Status::Invalid) { | ||
447 | this.transition(Status::NeedsReload); | ||
448 | } | ||
449 | } | ||
450 | Ok(()) | 432 | Ok(()) |
451 | })? | 433 | })? |
452 | .on::<lsp_types::notification::DidChangeConfiguration>(|this, _params| { | 434 | .on::<lsp_types::notification::DidChangeConfiguration>(|this, _params| { |
diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs index 74c3344df..0a201fceb 100644 --- a/crates/rust-analyzer/src/reload.rs +++ b/crates/rust-analyzer/src/reload.rs | |||
@@ -10,7 +10,8 @@ use vfs::{file_set::FileSetConfig, AbsPath}; | |||
10 | 10 | ||
11 | use crate::{ | 11 | use crate::{ |
12 | config::{Config, FilesWatcher, LinkedProject}, | 12 | config::{Config, FilesWatcher, LinkedProject}, |
13 | global_state::{GlobalState, Handle}, | 13 | global_state::{GlobalState, Handle, Status}, |
14 | lsp_ext, | ||
14 | main_loop::Task, | 15 | main_loop::Task, |
15 | }; | 16 | }; |
16 | 17 | ||
@@ -26,6 +27,32 @@ impl GlobalState { | |||
26 | self.reload_flycheck(); | 27 | self.reload_flycheck(); |
27 | } | 28 | } |
28 | } | 29 | } |
30 | pub(crate) fn maybe_refresh(&mut self, saved_doc_url: &str) { | ||
31 | if !(saved_doc_url.ends_with("Cargo.toml") || saved_doc_url.ends_with("Cargo.lock")) { | ||
32 | return; | ||
33 | } | ||
34 | match self.status { | ||
35 | Status::Loading | Status::NeedsReload => return, | ||
36 | Status::Ready | Status::Invalid => (), | ||
37 | } | ||
38 | if self.config.cargo_autoreload { | ||
39 | self.fetch_workspaces(); | ||
40 | } else { | ||
41 | self.transition(Status::NeedsReload); | ||
42 | } | ||
43 | } | ||
44 | pub(crate) fn transition(&mut self, new_status: Status) { | ||
45 | self.status = new_status; | ||
46 | if self.config.client_caps.status_notification { | ||
47 | let lsp_status = match new_status { | ||
48 | Status::Loading => lsp_ext::Status::Loading, | ||
49 | Status::Ready => lsp_ext::Status::Ready, | ||
50 | Status::Invalid => lsp_ext::Status::Invalid, | ||
51 | Status::NeedsReload => lsp_ext::Status::NeedsReload, | ||
52 | }; | ||
53 | self.send_notification::<lsp_ext::StatusNotification>(lsp_status); | ||
54 | } | ||
55 | } | ||
29 | pub(crate) fn fetch_workspaces(&mut self) { | 56 | pub(crate) fn fetch_workspaces(&mut self) { |
30 | self.task_pool.handle.spawn({ | 57 | self.task_pool.handle.spawn({ |
31 | let linked_projects = self.config.linked_projects.clone(); | 58 | let linked_projects = self.config.linked_projects.clone(); |
@@ -53,10 +80,13 @@ impl GlobalState { | |||
53 | } | 80 | } |
54 | pub(crate) fn switch_workspaces(&mut self, workspaces: Vec<anyhow::Result<ProjectWorkspace>>) { | 81 | pub(crate) fn switch_workspaces(&mut self, workspaces: Vec<anyhow::Result<ProjectWorkspace>>) { |
55 | log::info!("reloading projects: {:?}", self.config.linked_projects); | 82 | log::info!("reloading projects: {:?}", self.config.linked_projects); |
83 | |||
84 | let mut has_errors = false; | ||
56 | let workspaces = workspaces | 85 | let workspaces = workspaces |
57 | .into_iter() | 86 | .into_iter() |
58 | .filter_map(|res| { | 87 | .filter_map(|res| { |
59 | res.map_err(|err| { | 88 | res.map_err(|err| { |
89 | has_errors = true; | ||
60 | log::error!("failed to load workspace: {:#}", err); | 90 | log::error!("failed to load workspace: {:#}", err); |
61 | self.show_message( | 91 | self.show_message( |
62 | lsp_types::MessageType::Error, | 92 | lsp_types::MessageType::Error, |
@@ -67,6 +97,14 @@ impl GlobalState { | |||
67 | }) | 97 | }) |
68 | .collect::<Vec<_>>(); | 98 | .collect::<Vec<_>>(); |
69 | 99 | ||
100 | if &*self.workspaces == &workspaces { | ||
101 | return; | ||
102 | } | ||
103 | |||
104 | if !self.workspaces.is_empty() && has_errors { | ||
105 | return; | ||
106 | } | ||
107 | |||
70 | if let FilesWatcher::Client = self.config.files.watcher { | 108 | if let FilesWatcher::Client = self.config.files.watcher { |
71 | let registration_options = lsp_types::DidChangeWatchedFilesRegistrationOptions { | 109 | let registration_options = lsp_types::DidChangeWatchedFilesRegistrationOptions { |
72 | watchers: workspaces | 110 | watchers: workspaces |