mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-29 02:52:11 +00:00
Salsify the crate graph
I.e. make it not one giant input but multiple, for incrementality and decreased memory usage for Salsa 3 reasons.
This commit is contained in:
parent
44f18c3d05
commit
c94e9efbef
108 changed files with 3630 additions and 2512 deletions
|
|
@ -504,9 +504,7 @@ fn get_doc_base_urls(
|
|||
|
||||
let Some(krate) = krate else { return Default::default() };
|
||||
let Some(display_name) = krate.display_name(db) else { return Default::default() };
|
||||
let crate_data = &db.crate_graph()[krate.into()];
|
||||
|
||||
let (web_base, local_base) = match &crate_data.origin {
|
||||
let (web_base, local_base) = match krate.origin(db) {
|
||||
// std and co do not specify `html_root_url` any longer so we gotta handwrite this ourself.
|
||||
// FIXME: Use the toolchains channel instead of nightly
|
||||
CrateOrigin::Lang(
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
use hir::db::ExpandDatabase;
|
||||
use hir::{ExpandResult, InFile, MacroFileIdExt, Semantics};
|
||||
use ide_db::base_db::CrateId;
|
||||
use ide_db::{
|
||||
helpers::pick_best_token, syntax_helpers::prettify_macro_expansion, FileId, RootDatabase,
|
||||
base_db::Crate, helpers::pick_best_token, syntax_helpers::prettify_macro_expansion, FileId,
|
||||
RootDatabase,
|
||||
};
|
||||
use span::{Edition, SpanMap, SyntaxContextId, TextRange, TextSize};
|
||||
use stdx::format_to;
|
||||
|
|
@ -208,7 +208,7 @@ fn format(
|
|||
file_id: FileId,
|
||||
expanded: SyntaxNode,
|
||||
span_map: &SpanMap<SyntaxContextId>,
|
||||
krate: CrateId,
|
||||
krate: Crate,
|
||||
) -> String {
|
||||
let expansion = prettify_macro_expansion(db, expanded, span_map, krate).to_string();
|
||||
|
||||
|
|
@ -249,7 +249,7 @@ fn _format(
|
|||
|
||||
let upcast_db = ide_db::base_db::Upcast::<dyn ide_db::base_db::RootQueryDb>::upcast(db);
|
||||
let &crate_id = upcast_db.relevant_crates(file_id).iter().next()?;
|
||||
let edition = upcast_db.crate_graph()[crate_id].edition;
|
||||
let edition = crate_id.data(upcast_db).edition;
|
||||
|
||||
#[allow(clippy::disallowed_methods)]
|
||||
let mut cmd = std::process::Command::new(toolchain::Tool::Rustfmt.path());
|
||||
|
|
|
|||
|
|
@ -20,21 +20,24 @@ pub struct CrateInfo {
|
|||
//
|
||||
// 
|
||||
pub(crate) fn fetch_crates(db: &RootDatabase) -> FxIndexSet<CrateInfo> {
|
||||
let crate_graph = db.crate_graph();
|
||||
crate_graph
|
||||
db.all_crates()
|
||||
.iter()
|
||||
.map(|crate_id| &crate_graph[crate_id])
|
||||
.filter(|&data| !matches!(data.origin, CrateOrigin::Local { .. }))
|
||||
.map(crate_info)
|
||||
.copied()
|
||||
.map(|crate_id| (crate_id.data(db), crate_id.extra_data(db)))
|
||||
.filter(|(data, _)| !matches!(data.origin, CrateOrigin::Local { .. }))
|
||||
.map(|(data, extra_data)| crate_info(data, extra_data))
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn crate_info(data: &ide_db::base_db::CrateData) -> CrateInfo {
|
||||
let crate_name = crate_name(data);
|
||||
let version = data.version.clone();
|
||||
fn crate_info(
|
||||
data: &ide_db::base_db::BuiltCrateData,
|
||||
extra_data: &ide_db::base_db::ExtraCrateData,
|
||||
) -> CrateInfo {
|
||||
let crate_name = crate_name(extra_data);
|
||||
let version = extra_data.version.clone();
|
||||
CrateInfo { name: crate_name, version, root_file_id: data.root_file_id }
|
||||
}
|
||||
|
||||
fn crate_name(data: &ide_db::base_db::CrateData) -> Option<String> {
|
||||
fn crate_name(data: &ide_db::base_db::ExtraCrateData) -> Option<String> {
|
||||
data.display_name.as_ref().map(|it| it.canonical_name().as_str().to_owned())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ use hir::{
|
|||
MethodViolationCode, Name, Semantics, Symbol, Trait, Type, TypeInfo, VariantDef,
|
||||
};
|
||||
use ide_db::{
|
||||
base_db::RootQueryDb,
|
||||
defs::Definition,
|
||||
documentation::HasDocs,
|
||||
famous_defs::FamousDefs,
|
||||
|
|
@ -466,8 +465,7 @@ pub(super) fn path(
|
|||
item_name: Option<String>,
|
||||
edition: Edition,
|
||||
) -> String {
|
||||
let crate_name =
|
||||
db.crate_graph()[module.krate().into()].display_name.as_ref().map(|it| it.to_string());
|
||||
let crate_name = module.krate().display_name(db).as_ref().map(|it| it.to_string());
|
||||
let module_path = module
|
||||
.path_to_root(db)
|
||||
.into_iter()
|
||||
|
|
|
|||
|
|
@ -9252,7 +9252,7 @@ fn main() {
|
|||
S
|
||||
```
|
||||
___
|
||||
Implements notable traits: Notable, Future<Output = u32>, Iterator<Item = S>"#]],
|
||||
Implements notable traits: Future<Output = u32>, Iterator<Item = S>, Notable"#]],
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -868,15 +868,15 @@ fn main() {
|
|||
//- minicore: fn
|
||||
fn main() {
|
||||
let x = || 2;
|
||||
//^ {closure#26624}
|
||||
//^ {closure#25600}
|
||||
let y = |t: i32| x() + t;
|
||||
//^ {closure#26625}
|
||||
//^ {closure#25601}
|
||||
let mut t = 5;
|
||||
//^ i32
|
||||
let z = |k: i32| { t += k; };
|
||||
//^ {closure#26626}
|
||||
//^ {closure#25602}
|
||||
let p = (y, z);
|
||||
//^ ({closure#26625}, {closure#26626})
|
||||
//^ ({closure#25601}, {closure#25602})
|
||||
}
|
||||
"#,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ mod view_memory_layout;
|
|||
mod view_mir;
|
||||
mod view_syntax_tree;
|
||||
|
||||
use std::{iter, panic::UnwindSafe};
|
||||
use std::panic::UnwindSafe;
|
||||
|
||||
use cfg::CfgOptions;
|
||||
use fetch_crates::CrateInfo;
|
||||
|
|
@ -125,7 +125,7 @@ pub use ide_completion::{
|
|||
};
|
||||
pub use ide_db::text_edit::{Indel, TextEdit};
|
||||
pub use ide_db::{
|
||||
base_db::{CrateGraph, CrateId, FileChange, SourceRoot, SourceRootId},
|
||||
base_db::{Crate, CrateGraphBuilder, FileChange, SourceRoot, SourceRootId},
|
||||
documentation::Documentation,
|
||||
label::Label,
|
||||
line_index::{LineCol, LineIndex},
|
||||
|
|
@ -239,7 +239,7 @@ impl Analysis {
|
|||
|
||||
let mut change = ChangeWithProcMacros::new();
|
||||
change.set_roots(vec![source_root]);
|
||||
let mut crate_graph = CrateGraph::default();
|
||||
let mut crate_graph = CrateGraphBuilder::default();
|
||||
// FIXME: cfg options
|
||||
// Default to enable test for single file.
|
||||
let mut cfg_options = CfgOptions::default();
|
||||
|
|
@ -255,16 +255,13 @@ impl Analysis {
|
|||
CrateOrigin::Local { repo: None, name: None },
|
||||
false,
|
||||
None,
|
||||
);
|
||||
change.change_file(file_id, Some(text));
|
||||
let ws_data = crate_graph
|
||||
.iter()
|
||||
.zip(iter::repeat(Arc::new(CrateWorkspaceData {
|
||||
Arc::new(CrateWorkspaceData {
|
||||
data_layout: Err("fixture has no layout".into()),
|
||||
toolchain: None,
|
||||
})))
|
||||
.collect();
|
||||
change.set_crate_graph(crate_graph, ws_data);
|
||||
}),
|
||||
);
|
||||
change.change_file(file_id, Some(text));
|
||||
change.set_crate_graph(crate_graph);
|
||||
|
||||
host.apply_change(change);
|
||||
(host.analysis(), file_id)
|
||||
|
|
@ -372,7 +369,7 @@ impl Analysis {
|
|||
self.with_db(|db| test_explorer::discover_tests_in_crate_by_test_id(db, crate_id))
|
||||
}
|
||||
|
||||
pub fn discover_tests_in_crate(&self, crate_id: CrateId) -> Cancellable<Vec<TestItem>> {
|
||||
pub fn discover_tests_in_crate(&self, crate_id: Crate) -> Cancellable<Vec<TestItem>> {
|
||||
self.with_db(|db| test_explorer::discover_tests_in_crate(db, crate_id))
|
||||
}
|
||||
|
||||
|
|
@ -602,17 +599,17 @@ impl Analysis {
|
|||
}
|
||||
|
||||
/// Returns crates that this file belongs to.
|
||||
pub fn crates_for(&self, file_id: FileId) -> Cancellable<Vec<CrateId>> {
|
||||
pub fn crates_for(&self, file_id: FileId) -> Cancellable<Vec<Crate>> {
|
||||
self.with_db(|db| parent_module::crates_for(db, file_id))
|
||||
}
|
||||
|
||||
/// Returns crates that this file belongs to.
|
||||
pub fn transitive_rev_deps(&self, crate_id: CrateId) -> Cancellable<Vec<CrateId>> {
|
||||
self.with_db(|db| db.crate_graph().transitive_rev_deps(crate_id).collect())
|
||||
pub fn transitive_rev_deps(&self, crate_id: Crate) -> Cancellable<Vec<Crate>> {
|
||||
self.with_db(|db| Vec::from_iter(db.transitive_rev_deps(crate_id)))
|
||||
}
|
||||
|
||||
/// Returns crates that this file *might* belong to.
|
||||
pub fn relevant_crates_for(&self, file_id: FileId) -> Cancellable<Vec<CrateId>> {
|
||||
pub fn relevant_crates_for(&self, file_id: FileId) -> Cancellable<Vec<Crate>> {
|
||||
self.with_db(|db| {
|
||||
let db = Upcast::<dyn RootQueryDb>::upcast(db);
|
||||
db.relevant_crates(file_id).iter().copied().collect()
|
||||
|
|
@ -620,18 +617,23 @@ impl Analysis {
|
|||
}
|
||||
|
||||
/// Returns the edition of the given crate.
|
||||
pub fn crate_edition(&self, crate_id: CrateId) -> Cancellable<Edition> {
|
||||
self.with_db(|db| db.crate_graph()[crate_id].edition)
|
||||
pub fn crate_edition(&self, crate_id: Crate) -> Cancellable<Edition> {
|
||||
self.with_db(|db| crate_id.data(db).edition)
|
||||
}
|
||||
|
||||
/// Returns whether the given crate is a proc macro.
|
||||
pub fn is_proc_macro_crate(&self, crate_id: Crate) -> Cancellable<bool> {
|
||||
self.with_db(|db| crate_id.data(db).is_proc_macro)
|
||||
}
|
||||
|
||||
/// Returns true if this crate has `no_std` or `no_core` specified.
|
||||
pub fn is_crate_no_std(&self, crate_id: CrateId) -> Cancellable<bool> {
|
||||
pub fn is_crate_no_std(&self, crate_id: Crate) -> Cancellable<bool> {
|
||||
self.with_db(|db| hir::db::DefDatabase::crate_def_map(db, crate_id).is_no_std())
|
||||
}
|
||||
|
||||
/// Returns the root file of the given crate.
|
||||
pub fn crate_root(&self, crate_id: CrateId) -> Cancellable<FileId> {
|
||||
self.with_db(|db| db.crate_graph()[crate_id].root_file_id)
|
||||
pub fn crate_root(&self, crate_id: Crate) -> Cancellable<FileId> {
|
||||
self.with_db(|db| crate_id.data(db).root_file_id)
|
||||
}
|
||||
|
||||
/// Returns the set of possible targets to run for the current file.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use hir::{db::DefDatabase, Semantics};
|
||||
use ide_db::{
|
||||
base_db::{CrateId, RootQueryDb, Upcast},
|
||||
base_db::{Crate, RootQueryDb, Upcast},
|
||||
FileId, FilePosition, RootDatabase,
|
||||
};
|
||||
use itertools::Itertools;
|
||||
|
|
@ -53,7 +53,7 @@ pub(crate) fn parent_module(db: &RootDatabase, position: FilePosition) -> Vec<Na
|
|||
}
|
||||
|
||||
/// This returns `Vec` because a module may be included from several places.
|
||||
pub(crate) fn crates_for(db: &RootDatabase, file_id: FileId) -> Vec<CrateId> {
|
||||
pub(crate) fn crates_for(db: &RootDatabase, file_id: FileId) -> Vec<Crate> {
|
||||
let root_db = Upcast::<dyn RootQueryDb>::upcast(db);
|
||||
root_db
|
||||
.relevant_crates(file_id)
|
||||
|
|
|
|||
|
|
@ -498,9 +498,8 @@ fn module_def_doctest(db: &RootDatabase, def: Definition) -> Option<Runnable> {
|
|||
};
|
||||
let krate = def.krate(db);
|
||||
let edition = krate.map(|it| it.edition(db)).unwrap_or(Edition::CURRENT);
|
||||
let display_target = krate
|
||||
.unwrap_or_else(|| (*db.crate_graph().crates_in_topological_order().last().unwrap()).into())
|
||||
.to_display_target(db);
|
||||
let display_target =
|
||||
krate.unwrap_or_else(|| (*db.all_crates().last().unwrap()).into()).to_display_target(db);
|
||||
if !has_runnable_doc_test(&attrs) {
|
||||
return None;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -119,9 +119,7 @@ fn documentation_for_definition(
|
|||
sema.db,
|
||||
famous_defs.as_ref(),
|
||||
def.krate(sema.db)
|
||||
.unwrap_or_else(|| {
|
||||
(*sema.db.crate_graph().crates_in_topological_order().last().unwrap()).into()
|
||||
})
|
||||
.unwrap_or_else(|| (*sema.db.all_crates().last().unwrap()).into())
|
||||
.to_display_target(sema.db),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use ide_db::base_db::{CrateData, RootQueryDb, Upcast};
|
||||
use ide_db::base_db::{BuiltCrateData, ExtraCrateData};
|
||||
use ide_db::RootDatabase;
|
||||
use itertools::Itertools;
|
||||
use span::FileId;
|
||||
|
|
@ -34,28 +34,25 @@ pub(crate) fn status(db: &RootDatabase, file_id: Option<FileId>) -> String {
|
|||
if crates.is_empty() {
|
||||
format_to!(buf, "Does not belong to any crate");
|
||||
}
|
||||
|
||||
let crate_graph = Upcast::<dyn RootQueryDb>::upcast(db).crate_graph();
|
||||
for crate_id in crates {
|
||||
let CrateData {
|
||||
let BuiltCrateData {
|
||||
root_file_id,
|
||||
edition,
|
||||
version,
|
||||
display_name,
|
||||
cfg_options,
|
||||
potential_cfg_options,
|
||||
env,
|
||||
dependencies,
|
||||
origin,
|
||||
is_proc_macro,
|
||||
proc_macro_cwd,
|
||||
} = &crate_graph[crate_id];
|
||||
} = crate_id.data(db);
|
||||
let ExtraCrateData { version, display_name, potential_cfg_options } =
|
||||
crate_id.extra_data(db);
|
||||
let cfg_options = crate_id.cfg_options(db);
|
||||
let env = crate_id.env(db);
|
||||
format_to!(
|
||||
buf,
|
||||
"Crate: {}\n",
|
||||
match display_name {
|
||||
Some(it) => format!("{it}({})", crate_id.into_raw()),
|
||||
None => format!("{}", crate_id.into_raw()),
|
||||
Some(it) => format!("{it}({:?})", crate_id),
|
||||
None => format!("{:?}", crate_id),
|
||||
}
|
||||
);
|
||||
format_to!(buf, " Root module file id: {}\n", root_file_id.index());
|
||||
|
|
@ -69,7 +66,7 @@ pub(crate) fn status(db: &RootDatabase, file_id: Option<FileId>) -> String {
|
|||
format_to!(buf, " Proc macro cwd: {:?}\n", proc_macro_cwd);
|
||||
let deps = dependencies
|
||||
.iter()
|
||||
.map(|dep| format!("{}={}", dep.name, dep.crate_id.into_raw()))
|
||||
.map(|dep| format!("{}={:?}", dep.name, dep.crate_id))
|
||||
.format(", ");
|
||||
format_to!(buf, " Dependencies: {}\n", deps);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,15 @@
|
|||
//! Discovers tests
|
||||
|
||||
use hir::{Crate, Module, ModuleDef, Semantics};
|
||||
use ide_db::{
|
||||
base_db::{CrateGraph, CrateId, RootQueryDb},
|
||||
FileId, RootDatabase,
|
||||
};
|
||||
use ide_db::base_db;
|
||||
use ide_db::{base_db::RootQueryDb, FileId, RootDatabase};
|
||||
use syntax::TextRange;
|
||||
|
||||
use crate::{runnables::runnable_fn, NavigationTarget, Runnable, TryToNav};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum TestItemKind {
|
||||
Crate(CrateId),
|
||||
Crate(base_db::Crate),
|
||||
Module,
|
||||
Function,
|
||||
}
|
||||
|
|
@ -28,12 +26,12 @@ pub struct TestItem {
|
|||
}
|
||||
|
||||
pub(crate) fn discover_test_roots(db: &RootDatabase) -> Vec<TestItem> {
|
||||
let crate_graph = db.crate_graph();
|
||||
crate_graph
|
||||
db.all_crates()
|
||||
.iter()
|
||||
.filter(|&id| crate_graph[id].origin.is_local())
|
||||
.copied()
|
||||
.filter(|&id| id.data(db).origin.is_local())
|
||||
.filter_map(|id| {
|
||||
let test_id = crate_graph[id].display_name.as_ref()?.to_string();
|
||||
let test_id = id.extra_data(db).display_name.as_ref()?.to_string();
|
||||
Some(TestItem {
|
||||
kind: TestItemKind::Crate(id),
|
||||
label: test_id.clone(),
|
||||
|
|
@ -47,12 +45,12 @@ pub(crate) fn discover_test_roots(db: &RootDatabase) -> Vec<TestItem> {
|
|||
.collect()
|
||||
}
|
||||
|
||||
fn find_crate_by_id(crate_graph: &CrateGraph, crate_id: &str) -> Option<CrateId> {
|
||||
fn find_crate_by_id(db: &RootDatabase, crate_id: &str) -> Option<base_db::Crate> {
|
||||
// here, we use display_name as the crate id. This is not super ideal, but it works since we
|
||||
// only show tests for the local crates.
|
||||
crate_graph.iter().find(|&id| {
|
||||
crate_graph[id].origin.is_local()
|
||||
&& crate_graph[id].display_name.as_ref().is_some_and(|x| x.to_string() == crate_id)
|
||||
db.all_crates().iter().copied().find(|&id| {
|
||||
id.data(db).origin.is_local()
|
||||
&& id.extra_data(db).display_name.as_ref().is_some_and(|x| x.to_string() == crate_id)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -115,8 +113,7 @@ pub(crate) fn discover_tests_in_crate_by_test_id(
|
|||
db: &RootDatabase,
|
||||
crate_test_id: &str,
|
||||
) -> Vec<TestItem> {
|
||||
let crate_graph = db.crate_graph();
|
||||
let Some(crate_id) = find_crate_by_id(&crate_graph, crate_test_id) else {
|
||||
let Some(crate_id) = find_crate_by_id(db, crate_test_id) else {
|
||||
return vec![];
|
||||
};
|
||||
discover_tests_in_crate(db, crate_id)
|
||||
|
|
@ -171,12 +168,14 @@ fn find_module_id_and_test_parents(
|
|||
Some((r, id))
|
||||
}
|
||||
|
||||
pub(crate) fn discover_tests_in_crate(db: &RootDatabase, crate_id: CrateId) -> Vec<TestItem> {
|
||||
let crate_graph = db.crate_graph();
|
||||
if !crate_graph[crate_id].origin.is_local() {
|
||||
pub(crate) fn discover_tests_in_crate(
|
||||
db: &RootDatabase,
|
||||
crate_id: base_db::Crate,
|
||||
) -> Vec<TestItem> {
|
||||
if !crate_id.data(db).origin.is_local() {
|
||||
return vec![];
|
||||
}
|
||||
let Some(crate_test_id) = &crate_graph[crate_id].display_name else {
|
||||
let Some(crate_test_id) = &crate_id.extra_data(db).display_name else {
|
||||
return vec![];
|
||||
};
|
||||
let kind = TestItemKind::Crate(crate_id);
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
use dot::{Id, LabelText};
|
||||
use ide_db::{
|
||||
base_db::{CrateGraph, CrateId, Dependency, RootQueryDb, SourceDatabase, Upcast},
|
||||
FxHashSet, RootDatabase,
|
||||
base_db::{
|
||||
BuiltCrateData, BuiltDependency, Crate, ExtraCrateData, RootQueryDb, SourceDatabase,
|
||||
},
|
||||
FxHashMap, RootDatabase,
|
||||
};
|
||||
use triomphe::Arc;
|
||||
|
||||
// Feature: View Crate Graph
|
||||
//
|
||||
|
|
@ -16,77 +17,80 @@ use triomphe::Arc;
|
|||
// |---------|-------------|
|
||||
// | VS Code | **rust-analyzer: View Crate Graph** |
|
||||
pub(crate) fn view_crate_graph(db: &RootDatabase, full: bool) -> Result<String, String> {
|
||||
let crate_graph = Upcast::<dyn RootQueryDb>::upcast(db).crate_graph();
|
||||
let crates_to_render = crate_graph
|
||||
let all_crates = db.all_crates();
|
||||
let crates_to_render = all_crates
|
||||
.iter()
|
||||
.filter(|krate| {
|
||||
.copied()
|
||||
.map(|krate| (krate, (krate.data(db), krate.extra_data(db))))
|
||||
.filter(|(_, (crate_data, _))| {
|
||||
if full {
|
||||
true
|
||||
} else {
|
||||
// Only render workspace crates
|
||||
let root_id =
|
||||
db.file_source_root(crate_graph[*krate].root_file_id).source_root_id(db);
|
||||
let root_id = db.file_source_root(crate_data.root_file_id).source_root_id(db);
|
||||
!db.source_root(root_id).source_root(db).is_library
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
let graph = DotCrateGraph { graph: crate_graph, crates_to_render };
|
||||
let graph = DotCrateGraph { crates_to_render };
|
||||
|
||||
let mut dot = Vec::new();
|
||||
dot::render(&graph, &mut dot).unwrap();
|
||||
Ok(String::from_utf8(dot).unwrap())
|
||||
}
|
||||
|
||||
struct DotCrateGraph {
|
||||
graph: Arc<CrateGraph>,
|
||||
crates_to_render: FxHashSet<CrateId>,
|
||||
struct DotCrateGraph<'db> {
|
||||
crates_to_render: FxHashMap<Crate, (&'db BuiltCrateData, &'db ExtraCrateData)>,
|
||||
}
|
||||
|
||||
type Edge<'a> = (CrateId, &'a Dependency);
|
||||
type Edge<'a> = (Crate, &'a BuiltDependency);
|
||||
|
||||
impl<'a> dot::GraphWalk<'a, CrateId, Edge<'a>> for DotCrateGraph {
|
||||
fn nodes(&'a self) -> dot::Nodes<'a, CrateId> {
|
||||
self.crates_to_render.iter().copied().collect()
|
||||
impl<'a> dot::GraphWalk<'a, Crate, Edge<'a>> for DotCrateGraph<'_> {
|
||||
fn nodes(&'a self) -> dot::Nodes<'a, Crate> {
|
||||
self.crates_to_render.keys().copied().collect()
|
||||
}
|
||||
|
||||
fn edges(&'a self) -> dot::Edges<'a, Edge<'a>> {
|
||||
self.crates_to_render
|
||||
.iter()
|
||||
.flat_map(|krate| {
|
||||
self.graph[*krate]
|
||||
.flat_map(|(krate, (crate_data, _))| {
|
||||
crate_data
|
||||
.dependencies
|
||||
.iter()
|
||||
.filter(|dep| self.crates_to_render.contains(&dep.crate_id))
|
||||
.filter(|dep| self.crates_to_render.contains_key(&dep.crate_id))
|
||||
.map(move |dep| (*krate, dep))
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn source(&'a self, edge: &Edge<'a>) -> CrateId {
|
||||
fn source(&'a self, edge: &Edge<'a>) -> Crate {
|
||||
edge.0
|
||||
}
|
||||
|
||||
fn target(&'a self, edge: &Edge<'a>) -> CrateId {
|
||||
fn target(&'a self, edge: &Edge<'a>) -> Crate {
|
||||
edge.1.crate_id
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> dot::Labeller<'a, CrateId, Edge<'a>> for DotCrateGraph {
|
||||
impl<'a> dot::Labeller<'a, Crate, Edge<'a>> for DotCrateGraph<'_> {
|
||||
fn graph_id(&'a self) -> Id<'a> {
|
||||
Id::new("rust_analyzer_crate_graph").unwrap()
|
||||
}
|
||||
|
||||
fn node_id(&'a self, n: &CrateId) -> Id<'a> {
|
||||
Id::new(format!("_{}", u32::from(n.into_raw()))).unwrap()
|
||||
fn node_id(&'a self, n: &Crate) -> Id<'a> {
|
||||
Id::new(format!("_{:?}", n)).unwrap()
|
||||
}
|
||||
|
||||
fn node_shape(&'a self, _node: &CrateId) -> Option<LabelText<'a>> {
|
||||
fn node_shape(&'a self, _node: &Crate) -> Option<LabelText<'a>> {
|
||||
Some(LabelText::LabelStr("box".into()))
|
||||
}
|
||||
|
||||
fn node_label(&'a self, n: &CrateId) -> LabelText<'a> {
|
||||
let name =
|
||||
self.graph[*n].display_name.as_ref().map_or("(unnamed crate)", |name| name.as_str());
|
||||
fn node_label(&'a self, n: &Crate) -> LabelText<'a> {
|
||||
let name = self.crates_to_render[n]
|
||||
.1
|
||||
.display_name
|
||||
.as_ref()
|
||||
.map_or("(unnamed crate)", |name| name.as_str());
|
||||
LabelText::LabelStr(name.into())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue