Skip to content

Commit fd6fb78

Browse files
bors[bot]matklad
andauthored
Merge #5299
5299: Reload when new example/test/etc is added r=matklad a=matklad bors r+ 🤖 Co-authored-by: Aleksey Kladov <[email protected]>
2 parents c1eed62 + a1ef6cc commit fd6fb78

File tree

5 files changed

+107
-42
lines changed

5 files changed

+107
-42
lines changed

crates/ra_project_model/src/cargo_workspace.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ impl CargoWorkspace {
155155
if let Some(target) = cargo_features.target.as_ref() {
156156
meta.other_options(vec![String::from("--filter-platform"), target.clone()]);
157157
}
158-
let meta = meta.exec().with_context(|| {
158+
let mut meta = meta.exec().with_context(|| {
159159
format!("Failed to run `cargo metadata --manifest-path {}`", cargo_toml.display())
160160
})?;
161161

@@ -175,6 +175,7 @@ impl CargoWorkspace {
175175

176176
let ws_members = &meta.workspace_members;
177177

178+
meta.packages.sort_by(|a, b| a.id.cmp(&b.id));
178179
for meta_pkg in meta.packages {
179180
let cargo_metadata::Package { id, edition, name, manifest_path, version, .. } =
180181
meta_pkg;
@@ -210,7 +211,7 @@ impl CargoWorkspace {
210211
}
211212
}
212213
let resolve = meta.resolve.expect("metadata executed with deps");
213-
for node in resolve.nodes {
214+
for mut node in resolve.nodes {
214215
let source = match pkg_by_id.get(&node.id) {
215216
Some(&src) => src,
216217
// FIXME: replace this and a similar branch below with `.unwrap`, once
@@ -221,6 +222,7 @@ impl CargoWorkspace {
221222
continue;
222223
}
223224
};
225+
node.deps.sort_by(|a, b| a.pkg.cmp(&b.pkg));
224226
for dep_node in node.deps {
225227
let pkg = match pkg_by_id.get(&dep_node.pkg) {
226228
Some(&pkg) => pkg,

crates/rust-analyzer/src/global_state.rs

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ use crate::{
2626
to_proto::url_from_abs_path,
2727
Result,
2828
};
29+
use ra_prof::profile;
2930

3031
#[derive(Eq, PartialEq, Copy, Clone)]
3132
pub(crate) enum Status {
@@ -122,6 +123,10 @@ impl GlobalState {
122123
}
123124

124125
pub(crate) fn process_changes(&mut self) -> bool {
126+
let _p = profile("GlobalState::process_changes");
127+
let mut fs_changes = Vec::new();
128+
let mut has_fs_changes = false;
129+
125130
let change = {
126131
let mut change = AnalysisChange::new();
127132
let (vfs, line_endings_map) = &mut *self.vfs.write();
@@ -130,13 +135,14 @@ impl GlobalState {
130135
return false;
131136
}
132137

133-
let fs_op = changed_files.iter().any(|it| it.is_created_or_deleted());
134-
if fs_op {
135-
let roots = self.source_root_config.partition(&vfs);
136-
change.set_roots(roots)
137-
}
138-
139138
for file in changed_files {
139+
if file.is_created_or_deleted() {
140+
if let Some(path) = vfs.file_path(file.file_id).as_path() {
141+
fs_changes.push((path.to_path_buf(), file.change_kind));
142+
has_fs_changes = true;
143+
}
144+
}
145+
140146
let text = if file.exists() {
141147
let bytes = vfs.file_contents(file.file_id).to_vec();
142148
match String::from_utf8(bytes).ok() {
@@ -152,10 +158,15 @@ impl GlobalState {
152158
};
153159
change.change_file(file.file_id, text);
154160
}
161+
if has_fs_changes {
162+
let roots = self.source_root_config.partition(&vfs);
163+
change.set_roots(roots);
164+
}
155165
change
156166
};
157167

158168
self.analysis_host.apply_change(change);
169+
self.maybe_refresh(&fs_changes);
159170
true
160171
}
161172

crates/rust-analyzer/src/main_loop.rs

Lines changed: 43 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use crate::{
2222
Result,
2323
};
2424
use ra_project_model::ProjectWorkspace;
25+
use vfs::ChangeKind;
2526

2627
pub fn main_loop(config: Config, connection: Connection) -> Result<()> {
2728
log::info!("initial config: {:#?}", config);
@@ -197,39 +198,49 @@ impl GlobalState {
197198
}
198199
self.analysis_host.maybe_collect_garbage();
199200
}
200-
Event::Vfs(task) => match task {
201-
vfs::loader::Message::Loaded { files } => {
202-
let vfs = &mut self.vfs.write().0;
203-
for (path, contents) in files {
204-
let path = VfsPath::from(path);
205-
if !self.mem_docs.contains(&path) {
206-
vfs.set_file_contents(path, contents)
201+
Event::Vfs(mut task) => {
202+
let _p = profile("GlobalState::handle_event/vfs");
203+
loop {
204+
match task {
205+
vfs::loader::Message::Loaded { files } => {
206+
let vfs = &mut self.vfs.write().0;
207+
for (path, contents) in files {
208+
let path = VfsPath::from(path);
209+
if !self.mem_docs.contains(&path) {
210+
vfs.set_file_contents(path, contents)
211+
}
212+
}
213+
}
214+
vfs::loader::Message::Progress { n_total, n_done } => {
215+
if n_total == 0 {
216+
self.transition(Status::Invalid);
217+
} else {
218+
let state = if n_done == 0 {
219+
self.transition(Status::Loading);
220+
Progress::Begin
221+
} else if n_done < n_total {
222+
Progress::Report
223+
} else {
224+
assert_eq!(n_done, n_total);
225+
self.transition(Status::Ready);
226+
Progress::End
227+
};
228+
self.report_progress(
229+
"roots scanned",
230+
state,
231+
Some(format!("{}/{}", n_done, n_total)),
232+
Some(Progress::percentage(n_done, n_total)),
233+
)
234+
}
207235
}
208236
}
209-
}
210-
vfs::loader::Message::Progress { n_total, n_done } => {
211-
if n_total == 0 {
212-
self.transition(Status::Invalid);
213-
} else {
214-
let state = if n_done == 0 {
215-
self.transition(Status::Loading);
216-
Progress::Begin
217-
} else if n_done < n_total {
218-
Progress::Report
219-
} else {
220-
assert_eq!(n_done, n_total);
221-
self.transition(Status::Ready);
222-
Progress::End
223-
};
224-
self.report_progress(
225-
"roots scanned",
226-
state,
227-
Some(format!("{}/{}", n_done, n_total)),
228-
Some(Progress::percentage(n_done, n_total)),
229-
)
237+
// Coalesce many VFS event into a single loop turn
238+
task = match self.loader.receiver.try_recv() {
239+
Ok(task) => task,
240+
Err(_) => break,
230241
}
231242
}
232-
},
243+
}
233244
Event::Flycheck(task) => match task {
234245
flycheck::Message::AddDiagnostic { workspace_root, diagnostic } => {
235246
let diagnostics = crate::diagnostics::to_proto::map_rust_diagnostic_to_lsp(
@@ -428,7 +439,9 @@ impl GlobalState {
428439
if let Some(flycheck) = &this.flycheck {
429440
flycheck.handle.update();
430441
}
431-
this.maybe_refresh(params.text_document.uri.as_str());
442+
if let Ok(abs_path) = from_proto::abs_path(&params.text_document.uri) {
443+
this.maybe_refresh(&[(abs_path, ChangeKind::Modify)]);
444+
}
432445
Ok(())
433446
})?
434447
.on::<lsp_types::notification::DidChangeConfiguration>(|this, _params| {

crates/rust-analyzer/src/reload.rs

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,19 @@ use flycheck::FlycheckHandle;
66
use ra_db::{CrateGraph, SourceRoot, VfsPath};
77
use ra_ide::AnalysisChange;
88
use ra_project_model::{PackageRoot, ProcMacroClient, ProjectWorkspace};
9-
use vfs::{file_set::FileSetConfig, AbsPath};
9+
use vfs::{file_set::FileSetConfig, AbsPath, AbsPathBuf, ChangeKind};
1010

1111
use crate::{
1212
config::{Config, FilesWatcher, LinkedProject},
1313
global_state::{GlobalState, Handle, Status},
1414
lsp_ext,
1515
main_loop::Task,
1616
};
17+
use ra_prof::profile;
1718

1819
impl GlobalState {
1920
pub(crate) fn update_configuration(&mut self, config: Config) {
21+
let _p = profile("GlobalState::update_configuration");
2022
let old_config = mem::replace(&mut self.config, config);
2123
if self.config.lru_capacity != old_config.lru_capacity {
2224
self.analysis_host.update_lru_capacity(old_config.lru_capacity);
@@ -27,8 +29,8 @@ impl GlobalState {
2729
self.reload_flycheck();
2830
}
2931
}
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+
pub(crate) fn maybe_refresh(&mut self, changes: &[(AbsPathBuf, ChangeKind)]) {
33+
if !changes.iter().any(|(path, kind)| is_interesting(path, *kind)) {
3234
return;
3335
}
3436
match self.status {
@@ -40,6 +42,41 @@ impl GlobalState {
4042
} else {
4143
self.transition(Status::NeedsReload);
4244
}
45+
46+
fn is_interesting(path: &AbsPath, change_kind: ChangeKind) -> bool {
47+
const IMPLICIT_TARGET_FILES: &[&str] = &["build.rs", "src/main.rs", "src/lib.rs"];
48+
const IMPLICIT_TARGET_DIRS: &[&str] = &["src/bin", "examples", "tests", "benches"];
49+
50+
if path.ends_with("Cargo.toml") || path.ends_with("Cargo.lock") {
51+
return true;
52+
}
53+
if change_kind == ChangeKind::Modify {
54+
return false;
55+
}
56+
if path.extension().map(|it| it.to_str()) != Some("rs".into()) {
57+
return false;
58+
}
59+
if IMPLICIT_TARGET_FILES.iter().any(|it| path.ends_with(it)) {
60+
return true;
61+
}
62+
let parent = match path.parent() {
63+
Some(it) => it,
64+
None => return false,
65+
};
66+
if IMPLICIT_TARGET_DIRS.iter().any(|it| parent.ends_with(it)) {
67+
return true;
68+
}
69+
if path.ends_with("main.rs") {
70+
let grand_parent = match parent.parent() {
71+
Some(it) => it,
72+
None => return false,
73+
};
74+
if IMPLICIT_TARGET_DIRS.iter().any(|it| grand_parent.ends_with(it)) {
75+
return true;
76+
}
77+
}
78+
false
79+
}
4380
}
4481
pub(crate) fn transition(&mut self, new_status: Status) {
4582
self.status = new_status;
@@ -79,6 +116,7 @@ impl GlobalState {
79116
});
80117
}
81118
pub(crate) fn switch_workspaces(&mut self, workspaces: Vec<anyhow::Result<ProjectWorkspace>>) {
119+
let _p = profile("GlobalState::switch_workspaces");
82120
log::info!("reloading projects: {:?}", self.config.linked_projects);
83121

84122
let mut has_errors = false;
@@ -267,6 +305,7 @@ pub(crate) struct SourceRootConfig {
267305

268306
impl SourceRootConfig {
269307
pub(crate) fn partition(&self, vfs: &vfs::Vfs) -> Vec<SourceRoot> {
308+
let _p = profile("SourceRootConfig::partition");
270309
self.fsc
271310
.partition(vfs)
272311
.into_iter()

crates/vfs/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ impl ChangedFile {
7070
}
7171
}
7272

73-
#[derive(Eq, PartialEq)]
73+
#[derive(Eq, PartialEq, Copy, Clone, Debug)]
7474
pub enum ChangeKind {
7575
Create,
7676
Modify,

0 commit comments

Comments
 (0)