aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_project_model/src/cargo_workspace.rs8
-rw-r--r--crates/ra_project_model/src/lib.rs2
-rw-r--r--crates/ra_project_model/src/sysroot.rs6
-rw-r--r--crates/rust-analyzer/src/config.rs4
-rw-r--r--crates/rust-analyzer/src/main_loop.rs20
-rw-r--r--crates/rust-analyzer/src/reload.rs40
-rw-r--r--editors/code/package.json5
7 files changed, 57 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)]
28pub struct CargoWorkspace { 28pub 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
69pub type Target = Idx<TargetData>; 69pub type Target = Idx<TargetData>;
70 70
71#[derive(Debug, Clone)] 71#[derive(Debug, Clone, Eq, PartialEq)]
72pub struct PackageData { 72pub 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)]
87pub struct PackageDependency { 87pub 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)]
93pub struct TargetData { 93pub 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};
25pub use ra_proc_macro::ProcMacroClient; 25pub use ra_proc_macro::ProcMacroClient;
26 26
27#[derive(Debug, Clone)] 27#[derive(Debug, Clone, Eq, PartialEq)]
28pub enum ProjectWorkspace { 28pub 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 @@
3use std::{convert::TryFrom, env, ops, path::Path, process::Command}; 3use std::{convert::TryFrom, env, ops, path::Path, process::Command};
4 4
5use anyhow::{bail, format_err, Result}; 5use anyhow::{bail, format_err, Result};
6use paths::{AbsPath, AbsPathBuf};
6use ra_arena::{Arena, Idx}; 7use ra_arena::{Arena, Idx};
7 8
8use crate::output; 9use crate::output;
9use paths::{AbsPath, AbsPathBuf};
10 10
11#[derive(Default, Debug, Clone)] 11#[derive(Default, Debug, Clone, Eq, PartialEq)]
12pub struct Sysroot { 12pub struct Sysroot {
13 crates: Arena<SysrootCrateData>, 13 crates: Arena<SysrootCrateData>,
14} 14}
15 15
16pub type SysrootCrate = Idx<SysrootCrateData>; 16pub type SysrootCrate = Idx<SysrootCrateData>;
17 17
18#[derive(Debug, Clone)] 18#[derive(Debug, Clone, Eq, PartialEq)]
19pub struct SysrootCrateData { 19pub 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
11use crate::{ 11use 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
diff --git a/editors/code/package.json b/editors/code/package.json
index 743a2290c..aac4ba94f 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -237,6 +237,11 @@
237 "default": true, 237 "default": true,
238 "markdownDescription": "Whether to show `can't find Cargo.toml` error message" 238 "markdownDescription": "Whether to show `can't find Cargo.toml` error message"
239 }, 239 },
240 "rust-analyzer.cargo.autoreload": {
241 "type": "boolean",
242 "default": true,
243 "markdownDescription": "Automatically refresh project info via `cargo metadata` on Cargo.toml changes"
244 },
240 "rust-analyzer.cargo.noDefaultFeatures": { 245 "rust-analyzer.cargo.noDefaultFeatures": {
241 "type": "boolean", 246 "type": "boolean",
242 "default": false, 247 "default": false,