Skip to content
This repository was archived by the owner on Dec 29, 2022. It is now read-only.

Commit 56bee0e

Browse files
authored
Merge pull request #534 from alexheretic/master
Ignore irrelevant `DidChangeWatchedFiles` notifications
2 parents b55a82e + e80c7b8 commit 56bee0e

File tree

2 files changed

+62
-10
lines changed

2 files changed

+62
-10
lines changed

src/actions/mod.rs

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
use analysis::AnalysisHost;
1212
use vfs::Vfs;
1313
use config::{Config, FmtConfig};
14+
use serde_json;
15+
use url::Url;
1416
use span;
1517
use Span;
1618

@@ -211,6 +213,51 @@ fn find_word_at_pos(line: &str, pos: &Column) -> (Column, Column) {
211213
(span::Column::new_zero_indexed(start), span::Column::new_zero_indexed(end))
212214
}
213215

216+
// TODO include workspace Cargo.tomls in watchers / relevant
217+
/// Client file-watching request / filtering logic
218+
/// We want to watch workspace 'Cargo.toml', root 'Cargo.lock' & the root 'target' dir
219+
pub struct FileWatch<'ctx> {
220+
project_str: &'ctx str,
221+
project_uri: String,
222+
}
223+
224+
impl<'ctx> FileWatch<'ctx> {
225+
pub fn new(ctx: &'ctx InitActionContext) -> Self {
226+
Self {
227+
project_str: ctx.current_project.to_str().unwrap(),
228+
project_uri: Url::from_file_path(&ctx.current_project).unwrap().into_string(),
229+
}
230+
}
231+
232+
/// Returns json config for desired file watches
233+
pub fn watchers_config(&self) -> serde_json::Value {
234+
let pattern = format!("{}/Cargo{{.toml,.lock}}", self.project_str);
235+
let target_pattern = format!("{}/target", self.project_str);
236+
// For target, we only watch if it gets deleted.
237+
json!({
238+
"watchers": [{ "globPattern": pattern }, { "globPattern": target_pattern, "kind": 4 }]
239+
})
240+
}
241+
242+
/// Returns if a file change is relevant to the files we actually wanted to watch
243+
// Implementation note: This is expected to be called a large number of times in a loop
244+
// so should be fast / avoid allocation.
245+
#[inline]
246+
pub fn is_relevant(&self, change: &FileEvent) -> bool {
247+
let path = change.uri.as_str();
248+
249+
if !path.starts_with(&self.project_uri) {
250+
return false;
251+
}
252+
253+
let local = &path[self.project_uri.len()..];
254+
255+
local == "/Cargo.lock" || local == "/Cargo.toml"
256+
|| local == "/target" && change.typ == FileChangeType::Deleted
257+
}
258+
}
259+
260+
214261
#[cfg(test)]
215262
mod test {
216263
use super::*;
@@ -244,4 +291,4 @@ mod test {
244291
assert_range("span::Position<|T>", (15, 16));
245292
assert_range("span::Position<T|>", (15, 16));
246293
}
247-
}
294+
}

src/actions/notifications.rs

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
// except according to those terms.
1010

1111
use actions::ActionContext;
12+
use actions::FileWatch;
1213
use vfs::Change;
1314
use config::Config;
1415
use serde::Deserialize;
@@ -42,13 +43,7 @@ impl<'a> NotificationAction<'a> for Initialized {
4243

4344
let ctx = ctx.inited();
4445

45-
// TODO we should watch for workspace Cargo.tomls too
46-
let pattern = format!("{}/Cargo{{.toml,.lock}}", ctx.current_project.to_str().unwrap());
47-
let target_pattern = format!("{}/target", ctx.current_project.to_str().unwrap());
48-
// For target, we only watch if it gets deleted.
49-
let options = json!({
50-
"watchers": [{ "globPattern": pattern }, { "globPattern": target_pattern, "kind": 4 }]
51-
});
46+
let options = FileWatch::new(&ctx).watchers_config();
5247
let output = serde_json::to_string(
5348
&RequestMessage::new(out.provide_id(),
5449
NOTIFICATION__RegisterCapability.to_owned(),
@@ -271,10 +266,20 @@ impl<'a> Action<'a> for DidChangeWatchedFiles {
271266
}
272267

273268
impl<'a> NotificationAction<'a> for DidChangeWatchedFiles {
274-
fn handle<O: Output>(&mut self, _params: DidChangeWatchedFilesParams, ctx: &mut ActionContext, out: O) -> Result<(), ()> {
269+
fn handle<O: Output>(
270+
&mut self,
271+
params: DidChangeWatchedFilesParams,
272+
ctx: &mut ActionContext,
273+
out: O,
274+
) -> Result<(), ()> {
275275
trace!("on_cargo_change: thread: {:?}", thread::current().id());
276+
276277
let ctx = ctx.inited();
277-
ctx.build_current_project(BuildPriority::Cargo, out);
278+
let file_watch = FileWatch::new(&ctx);
279+
280+
if params.changes.iter().any(|c| file_watch.is_relevant(c)) {
281+
ctx.build_current_project(BuildPriority::Cargo, out);
282+
}
278283

279284
Ok(())
280285
}

0 commit comments

Comments
 (0)