Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/flycheck/src/lib.rs7
-rw-r--r--crates/paths/src/lib.rs8
-rw-r--r--crates/rust-analyzer/src/main_loop.rs62
3 files changed, 70 insertions, 7 deletions
diff --git a/crates/flycheck/src/lib.rs b/crates/flycheck/src/lib.rs
index f683fe61fe..973f2a53c1 100644
--- a/crates/flycheck/src/lib.rs
+++ b/crates/flycheck/src/lib.rs
@@ -55,6 +55,7 @@ pub struct FlycheckHandle {
// XXX: drop order is significant
sender: Sender<Restart>,
_thread: jod_thread::JoinHandle,
+ id: usize,
}
impl FlycheckHandle {
@@ -70,13 +71,17 @@ impl FlycheckHandle {
.name("Flycheck".to_owned())
.spawn(move || actor.run(receiver))
.expect("failed to spawn thread");
- FlycheckHandle { sender, _thread: thread }
+ FlycheckHandle { id, sender, _thread: thread }
}
/// Schedule a re-start of the cargo check worker.
pub fn update(&self) {
self.sender.send(Restart).unwrap();
}
+
+ pub fn id(&self) -> usize {
+ self.id
+ }
}
pub enum Message {
diff --git a/crates/paths/src/lib.rs b/crates/paths/src/lib.rs
index b4beb40e74..cf06bf0c27 100644
--- a/crates/paths/src/lib.rs
+++ b/crates/paths/src/lib.rs
@@ -103,6 +103,14 @@ impl AsRef<Path> for AbsPath {
}
}
+impl ToOwned for AbsPath {
+ type Owned = AbsPathBuf;
+
+ fn to_owned(&self) -> Self::Owned {
+ AbsPathBuf(self.0.to_owned())
+ }
+}
+
impl<'a> TryFrom<&'a Path> for &'a AbsPath {
type Error = &'a Path;
fn try_from(path: &'a Path) -> Result<&'a AbsPath, &'a Path> {
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs
index 49b8394111..262c30f132 100644
--- a/crates/rust-analyzer/src/main_loop.rs
+++ b/crates/rust-analyzer/src/main_loop.rs
@@ -2,6 +2,7 @@
//! requests/replies and notifications back to the client.
use std::{
fmt,
+ ops::Deref,
sync::Arc,
time::{Duration, Instant},
};
@@ -720,13 +721,62 @@ impl GlobalState {
Ok(())
})?
.on::<lsp_types::notification::DidSaveTextDocument>(|this, params| {
- for flycheck in &this.flycheck {
- flycheck.update();
+ let mut updated = false;
+ if let Ok(vfs_path) = from_proto::vfs_path(&params.text_document.uri) {
+ let (vfs, _) = &*this.vfs.read();
+ if let Some(file_id) = vfs.file_id(&vfs_path) {
+ let analysis = this.analysis_host.analysis();
+ let crate_ids = analysis.crate_for(file_id)?;
+
+ let paths: Vec<_> = crate_ids
+ .iter()
+ .filter_map(|&crate_id| {
+ analysis
+ .crate_root(crate_id)
+ .map(|file_id| {
+ vfs.file_path(file_id).as_path().map(ToOwned::to_owned)
+ })
+ .transpose()
+ })
+ .collect::<ide::Cancellable<_>>()?;
+ let paths: Vec<_> = paths.iter().map(Deref::deref).collect();
+
+ let workspace_ids =
+ this.workspaces.iter().enumerate().filter(|(_, ws)| match ws {
+ project_model::ProjectWorkspace::Cargo { cargo, .. } => {
+ cargo.packages().filter(|&pkg| cargo[pkg].is_member).any(
+ |pkg| {
+ cargo[pkg].targets.iter().any(|&it| {
+ paths.contains(&cargo[it].root.as_path())
+ })
+ },
+ )
+ }
+ project_model::ProjectWorkspace::Json { project, .. } => project
+ .crates()
+ .any(|(c, _)| crate_ids.iter().any(|&crate_id| crate_id == c)),
+ project_model::ProjectWorkspace::DetachedFiles { .. } => false,
+ });
+ 'workspace: for (id, _) in workspace_ids {
+ for flycheck in &this.flycheck {
+ if id == flycheck.id() {
+ updated = true;
+ flycheck.update();
+ continue 'workspace;
+ }
+ }
+ }
+ }
+ if let Some(abs_path) = vfs_path.as_path() {
+ if reload::should_refresh_for_change(&abs_path, ChangeKind::Modify) {
+ this.fetch_workspaces_queue
+ .request_op(format!("DidSaveTextDocument {}", abs_path.display()));
+ }
+ }
}
- if let Ok(abs_path) = from_proto::abs_path(&params.text_document.uri) {
- if reload::should_refresh_for_change(&abs_path, ChangeKind::Modify) {
- this.fetch_workspaces_queue
- .request_op(format!("DidSaveTextDocument {}", abs_path.display()));
+ if !updated {
+ for flycheck in &this.flycheck {
+ flycheck.update();
}
}
Ok(())