mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-25 12:33:33 +00:00
Improve prime_caches and display its progress
This commit is contained in:
parent
518f6d7724
commit
cde7392ec8
5 changed files with 120 additions and 14 deletions
|
@ -221,6 +221,34 @@ impl CrateGraph {
|
||||||
deps.into_iter()
|
deps.into_iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns all crates in the graph, sorted in topological order (ie. dependencies of a crate
|
||||||
|
/// come before the crate itself).
|
||||||
|
pub fn crates_in_topological_order(&self) -> Vec<CrateId> {
|
||||||
|
let mut res = Vec::new();
|
||||||
|
let mut visited = FxHashSet::default();
|
||||||
|
|
||||||
|
for krate in self.arena.keys().copied() {
|
||||||
|
go(self, &mut visited, &mut res, krate);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
|
||||||
|
fn go(
|
||||||
|
graph: &CrateGraph,
|
||||||
|
visited: &mut FxHashSet<CrateId>,
|
||||||
|
res: &mut Vec<CrateId>,
|
||||||
|
source: CrateId,
|
||||||
|
) {
|
||||||
|
if !visited.insert(source) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for dep in graph[source].dependencies.iter() {
|
||||||
|
go(graph, visited, res, dep.crate_id)
|
||||||
|
}
|
||||||
|
res.push(source)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: this only finds one crate with the given root; we could have multiple
|
// FIXME: this only finds one crate with the given root; we could have multiple
|
||||||
pub fn crate_id_for_crate_root(&self, file_id: FileId) -> Option<CrateId> {
|
pub fn crate_id_for_crate_root(&self, file_id: FileId) -> Option<CrateId> {
|
||||||
let (&crate_id, _) =
|
let (&crate_id, _) =
|
||||||
|
|
|
@ -77,6 +77,7 @@ pub use crate::{
|
||||||
hover::{HoverAction, HoverConfig, HoverGotoTypeData, HoverResult},
|
hover::{HoverAction, HoverConfig, HoverGotoTypeData, HoverResult},
|
||||||
inlay_hints::{InlayHint, InlayHintsConfig, InlayKind},
|
inlay_hints::{InlayHint, InlayHintsConfig, InlayKind},
|
||||||
markup::Markup,
|
markup::Markup,
|
||||||
|
prime_caches::PrimeCachesProgress,
|
||||||
references::{
|
references::{
|
||||||
Declaration, Reference, ReferenceAccess, ReferenceKind, ReferenceSearchResult, RenameError,
|
Declaration, Reference, ReferenceAccess, ReferenceKind, ReferenceSearchResult, RenameError,
|
||||||
},
|
},
|
||||||
|
@ -223,8 +224,11 @@ impl Analysis {
|
||||||
self.with_db(|db| status::status(&*db, file_id))
|
self.with_db(|db| status::status(&*db, file_id))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn prime_caches(&self, files: Vec<FileId>) -> Cancelable<()> {
|
pub fn prime_caches<F>(&self, cb: F) -> Cancelable<()>
|
||||||
self.with_db(|db| prime_caches::prime_caches(db, files))
|
where
|
||||||
|
F: Fn(PrimeCachesProgress) + Sync + std::panic::UnwindSafe,
|
||||||
|
{
|
||||||
|
self.with_db(move |db| prime_caches::prime_caches(db, &cb))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the text of the source file.
|
/// Gets the text of the source file.
|
||||||
|
|
|
@ -3,10 +3,45 @@
|
||||||
//! request takes longer to compute. This modules implemented prepopulating of
|
//! request takes longer to compute. This modules implemented prepopulating of
|
||||||
//! various caches, it's not really advanced at the moment.
|
//! various caches, it's not really advanced at the moment.
|
||||||
|
|
||||||
use crate::{FileId, RootDatabase};
|
use base_db::SourceDatabase;
|
||||||
|
use hir::db::DefDatabase;
|
||||||
|
|
||||||
pub(crate) fn prime_caches(db: &RootDatabase, files: Vec<FileId>) {
|
use crate::RootDatabase;
|
||||||
for file in files {
|
|
||||||
let _ = crate::syntax_highlighting::highlight(db, file, None, false);
|
#[derive(Debug)]
|
||||||
}
|
pub enum PrimeCachesProgress {
|
||||||
|
Started,
|
||||||
|
/// We started indexing a crate.
|
||||||
|
StartedOnCrate {
|
||||||
|
on_crate: String,
|
||||||
|
n_done: usize,
|
||||||
|
n_total: usize,
|
||||||
|
},
|
||||||
|
/// We finished indexing all crates.
|
||||||
|
Finished,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn prime_caches(db: &RootDatabase, cb: &(dyn Fn(PrimeCachesProgress) + Sync)) {
|
||||||
|
let _p = profile::span("prime_caches");
|
||||||
|
let graph = db.crate_graph();
|
||||||
|
let topo = &graph.crates_in_topological_order();
|
||||||
|
|
||||||
|
cb(PrimeCachesProgress::Started);
|
||||||
|
|
||||||
|
// FIXME: This would be easy to parallelize, since it's in the ideal ordering for that.
|
||||||
|
// Unfortunately rayon prevents panics from propagation out of a `scope`, which breaks
|
||||||
|
// cancellation, so we cannot use rayon.
|
||||||
|
for (i, krate) in topo.iter().enumerate() {
|
||||||
|
let crate_name =
|
||||||
|
graph[*krate].declaration_name.as_ref().map(ToString::to_string).unwrap_or_default();
|
||||||
|
|
||||||
|
cb(PrimeCachesProgress::StartedOnCrate {
|
||||||
|
on_crate: crate_name,
|
||||||
|
n_done: i,
|
||||||
|
n_total: topo.len(),
|
||||||
|
});
|
||||||
|
db.crate_def_map(*krate);
|
||||||
|
}
|
||||||
|
|
||||||
|
cb(PrimeCachesProgress::Finished);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ use std::{
|
||||||
|
|
||||||
use base_db::VfsPath;
|
use base_db::VfsPath;
|
||||||
use crossbeam_channel::{select, Receiver};
|
use crossbeam_channel::{select, Receiver};
|
||||||
|
use ide::PrimeCachesProgress;
|
||||||
use ide::{Canceled, FileId};
|
use ide::{Canceled, FileId};
|
||||||
use lsp_server::{Connection, Notification, Request, Response};
|
use lsp_server::{Connection, Notification, Request, Response};
|
||||||
use lsp_types::notification::Notification as _;
|
use lsp_types::notification::Notification as _;
|
||||||
|
@ -61,7 +62,7 @@ pub(crate) enum Task {
|
||||||
Response(Response),
|
Response(Response),
|
||||||
Diagnostics(Vec<(FileId, Vec<lsp_types::Diagnostic>)>),
|
Diagnostics(Vec<(FileId, Vec<lsp_types::Diagnostic>)>),
|
||||||
Workspaces(Vec<anyhow::Result<ProjectWorkspace>>),
|
Workspaces(Vec<anyhow::Result<ProjectWorkspace>>),
|
||||||
Unit,
|
PrimeCaches(PrimeCachesProgress),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for Event {
|
impl fmt::Debug for Event {
|
||||||
|
@ -197,7 +198,28 @@ impl GlobalState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Task::Workspaces(workspaces) => self.switch_workspaces(workspaces),
|
Task::Workspaces(workspaces) => self.switch_workspaces(workspaces),
|
||||||
Task::Unit => (),
|
Task::PrimeCaches(progress) => {
|
||||||
|
let (state, message, fraction);
|
||||||
|
match progress {
|
||||||
|
PrimeCachesProgress::Started => {
|
||||||
|
state = Progress::Begin;
|
||||||
|
message = None;
|
||||||
|
fraction = 0.0;
|
||||||
|
}
|
||||||
|
PrimeCachesProgress::StartedOnCrate { on_crate, n_done, n_total } => {
|
||||||
|
state = Progress::Report;
|
||||||
|
message = Some(format!("{}/{} ({})", n_done, n_total, on_crate));
|
||||||
|
fraction = Progress::fraction(n_done, n_total);
|
||||||
|
}
|
||||||
|
PrimeCachesProgress::Finished => {
|
||||||
|
state = Progress::End;
|
||||||
|
message = None;
|
||||||
|
fraction = 1.0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
self.report_progress("indexing", state, message, Some(fraction));
|
||||||
|
}
|
||||||
},
|
},
|
||||||
Event::Vfs(mut task) => {
|
Event::Vfs(mut task) => {
|
||||||
let _p = profile::span("GlobalState::handle_event/vfs");
|
let _p = profile::span("GlobalState::handle_event/vfs");
|
||||||
|
@ -573,12 +595,18 @@ impl GlobalState {
|
||||||
Task::Diagnostics(diagnostics)
|
Task::Diagnostics(diagnostics)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
self.task_pool.handle.spawn({
|
self.task_pool.handle.spawn_with_sender({
|
||||||
let subs = subscriptions;
|
|
||||||
let snap = self.snapshot();
|
let snap = self.snapshot();
|
||||||
move || {
|
move |sender| {
|
||||||
snap.analysis.prime_caches(subs).unwrap_or_else(|_: Canceled| ());
|
snap.analysis
|
||||||
Task::Unit
|
.prime_caches(|progress| {
|
||||||
|
sender.send(Task::PrimeCaches(progress)).unwrap();
|
||||||
|
})
|
||||||
|
.unwrap_or_else(|_: Canceled| {
|
||||||
|
// Pretend that we're done, so that the progress bar is removed. Otherwise
|
||||||
|
// the editor may complain about it already existing.
|
||||||
|
sender.send(Task::PrimeCaches(PrimeCachesProgress::Finished)).unwrap()
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,17 @@ impl<T> TaskPool<T> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn spawn_with_sender<F>(&mut self, task: F)
|
||||||
|
where
|
||||||
|
F: FnOnce(Sender<T>) + Send + 'static,
|
||||||
|
T: Send + 'static,
|
||||||
|
{
|
||||||
|
self.inner.execute({
|
||||||
|
let sender = self.sender.clone();
|
||||||
|
move || task(sender)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn len(&self) -> usize {
|
pub(crate) fn len(&self) -> usize {
|
||||||
self.inner.queued_count()
|
self.inner.queued_count()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue