mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-12 21:28:51 +00:00
propagate deps to CrateGraph
This commit is contained in:
parent
32c067f8c9
commit
9b1356464a
3 changed files with 43 additions and 14 deletions
|
@ -48,6 +48,9 @@ impl CrateGraph {
|
||||||
assert!(prev.is_none());
|
assert!(prev.is_none());
|
||||||
crate_id
|
crate_id
|
||||||
}
|
}
|
||||||
|
//FIXME: check that we don't have cycles here.
|
||||||
|
// Just a simple depth first search from `to` should work,
|
||||||
|
// the graph is small.
|
||||||
pub fn add_dep(&mut self, from: CrateId, to: CrateId) {
|
pub fn add_dep(&mut self, from: CrateId, to: CrateId) {
|
||||||
self.arena.get_mut(&from).unwrap().add_dep(to)
|
self.arena.get_mut(&from).unwrap().add_dep(to)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use serde_derive::Serialize;
|
|
||||||
use cargo_metadata::{metadata_run, CargoOpt};
|
use cargo_metadata::{metadata_run, CargoOpt};
|
||||||
use ra_syntax::SmolStr;
|
use ra_syntax::SmolStr;
|
||||||
use rustc_hash::{FxHashMap, FxHashSet};
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
|
@ -11,15 +10,22 @@ use crate::{
|
||||||
thread_watcher::{ThreadWatcher, Worker},
|
thread_watcher::{ThreadWatcher, Worker},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// `CargoWorksapce` represents the logical structure of, well, a Cargo
|
||||||
|
/// workspace. It pretty closely mirrors `cargo metadata` output.
|
||||||
|
///
|
||||||
|
/// Note that internally, rust analyzer uses a differnet structure:
|
||||||
|
/// `CrateGraph`. `CrateGraph` is lower-level: it knows only about the crates,
|
||||||
|
/// while this knows about `Pacakges` & `Targets`: purely cargo-related
|
||||||
|
/// concepts.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct CargoWorkspace {
|
pub struct CargoWorkspace {
|
||||||
packages: Vec<PackageData>,
|
packages: Vec<PackageData>,
|
||||||
targets: Vec<TargetData>,
|
targets: Vec<TargetData>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Serialize)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||||
pub struct Package(usize);
|
pub struct Package(usize);
|
||||||
#[derive(Clone, Copy, Debug, Serialize)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||||
pub struct Target(usize);
|
pub struct Target(usize);
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
@ -62,6 +68,9 @@ impl Package {
|
||||||
pub fn is_member(self, ws: &CargoWorkspace) -> bool {
|
pub fn is_member(self, ws: &CargoWorkspace) -> bool {
|
||||||
ws.pkg(self).is_member
|
ws.pkg(self).is_member
|
||||||
}
|
}
|
||||||
|
pub fn dependencies<'a>(self, ws: &'a CargoWorkspace) -> impl Iterator<Item = Package> + 'a {
|
||||||
|
ws.pkg(self).dependencies.iter().cloned()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Target {
|
impl Target {
|
||||||
|
|
|
@ -13,7 +13,7 @@ use failure::{bail, format_err};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
path_map::{PathMap, Root},
|
path_map::{PathMap, Root},
|
||||||
project_model::CargoWorkspace,
|
project_model::{CargoWorkspace, TargetKind},
|
||||||
vfs::{FileEvent, FileEventKind},
|
vfs::{FileEvent, FileEventKind},
|
||||||
Result,
|
Result,
|
||||||
};
|
};
|
||||||
|
@ -142,17 +142,34 @@ impl ServerWorldState {
|
||||||
}
|
}
|
||||||
pub fn set_workspaces(&mut self, ws: Vec<CargoWorkspace>) {
|
pub fn set_workspaces(&mut self, ws: Vec<CargoWorkspace>) {
|
||||||
let mut crate_graph = CrateGraph::default();
|
let mut crate_graph = CrateGraph::default();
|
||||||
ws.iter()
|
let mut pkg_to_lib_crate = FxHashMap::default();
|
||||||
.flat_map(|ws| {
|
let mut pkg_crates = FxHashMap::default();
|
||||||
ws.packages()
|
for ws in ws.iter() {
|
||||||
.flat_map(move |pkg| pkg.targets(ws))
|
for pkg in ws.packages() {
|
||||||
.map(move |tgt| tgt.root(ws))
|
for tgt in pkg.targets(ws) {
|
||||||
})
|
let root = tgt.root(ws);
|
||||||
.for_each(|root| {
|
if let Some(file_id) = self.path_map.get_id(root) {
|
||||||
if let Some(file_id) = self.path_map.get_id(root) {
|
let crate_id = crate_graph.add_crate_root(file_id);
|
||||||
crate_graph.add_crate_root(file_id);
|
if tgt.kind(ws) == TargetKind::Lib {
|
||||||
|
pkg_to_lib_crate.insert(pkg, crate_id);
|
||||||
|
}
|
||||||
|
pkg_crates
|
||||||
|
.entry(pkg)
|
||||||
|
.or_insert_with(Vec::new)
|
||||||
|
.push(crate_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
for pkg in ws.packages() {
|
||||||
|
for dep in pkg.dependencies(ws) {
|
||||||
|
if let Some(&to) = pkg_to_lib_crate.get(&dep) {
|
||||||
|
for &from in pkg_crates.get(&pkg).into_iter().flatten() {
|
||||||
|
crate_graph.add_dep(from, to);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
self.workspaces = Arc::new(ws);
|
self.workspaces = Arc::new(ws);
|
||||||
let mut change = AnalysisChange::new();
|
let mut change = AnalysisChange::new();
|
||||||
change.set_crate_graph(crate_graph);
|
change.set_crate_graph(crate_graph);
|
||||||
|
|
Loading…
Reference in a new issue