sync::Arc,
};
-use languageserver_types::Url;
+use lsp_types::Url;
use ra_ide_api::{
Analysis, AnalysisChange, AnalysisHost, CrateGraph, FileId, LibraryData,
SourceRootId
use failure::format_err;
use crate::{
- project_model::{CargoWorkspace, TargetKind},
+ project_model::{ProjectWorkspace, TargetKind},
Result,
};
pub struct ServerWorldState {
pub roots_to_scan: usize,
pub root: PathBuf,
- pub workspaces: Arc<Vec<CargoWorkspace>>,
+ pub workspaces: Arc<Vec<ProjectWorkspace>>,
pub analysis_host: AnalysisHost,
pub vfs: Arc<RwLock<Vfs>>,
}
pub struct ServerWorld {
- pub workspaces: Arc<Vec<CargoWorkspace>>,
+ pub workspaces: Arc<Vec<ProjectWorkspace>>,
pub analysis: Analysis,
pub vfs: Arc<RwLock<Vfs>>,
}
impl ServerWorldState {
- pub fn new(root: PathBuf, workspaces: Vec<CargoWorkspace>) -> ServerWorldState {
+ pub fn new(root: PathBuf, workspaces: Vec<ProjectWorkspace>) -> ServerWorldState {
let mut change = AnalysisChange::new();
let mut roots = Vec::new();
roots.push(root.clone());
for ws in workspaces.iter() {
- for pkg in ws.packages() {
- roots.push(pkg.root(&ws).to_path_buf());
+ for pkg in ws.cargo.packages() {
+ roots.push(pkg.root(&ws.cargo).to_path_buf());
+ }
+ for krate in ws.sysroot.crates() {
+ roots.push(krate.root_dir(&ws.sysroot).to_path_buf())
}
}
+ roots.sort();
+ roots.dedup();
let roots_to_scan = roots.len();
let (mut vfs, roots) = Vfs::new(roots);
for r in roots {
}
let mut crate_graph = CrateGraph::default();
- let mut pkg_to_lib_crate = FxHashMap::default();
- let mut pkg_crates = FxHashMap::default();
for ws in workspaces.iter() {
- for pkg in ws.packages() {
- for tgt in pkg.targets(ws) {
- let root = tgt.root(ws);
+ // First, load std
+ let mut sysroot_crates = FxHashMap::default();
+ for krate in ws.sysroot.crates() {
+ if let Some(file_id) = vfs.load(krate.root(&ws.sysroot)) {
+ let file_id = FileId(file_id.0.into());
+ sysroot_crates.insert(krate, crate_graph.add_crate_root(file_id));
+ }
+ }
+ for from in ws.sysroot.crates() {
+ for to in from.deps(&ws.sysroot) {
+ let name = to.name(&ws.sysroot);
+ if let (Some(&from), Some(&to)) =
+ (sysroot_crates.get(&from), sysroot_crates.get(&to))
+ {
+ if let Err(_) = crate_graph.add_dep(from, name.clone(), to) {
+ log::error!("cyclic dependency between sysroot crates")
+ }
+ }
+ }
+ }
+
+ let libstd = ws
+ .sysroot
+ .std()
+ .and_then(|it| sysroot_crates.get(&it).map(|&it| it));
+
+ let mut pkg_to_lib_crate = FxHashMap::default();
+ let mut pkg_crates = FxHashMap::default();
+ // Next, create crates for each package, target pair
+ for pkg in ws.cargo.packages() {
+ let mut lib_tgt = None;
+ for tgt in pkg.targets(&ws.cargo) {
+ let root = tgt.root(&ws.cargo);
if let Some(file_id) = vfs.load(root) {
let file_id = FileId(file_id.0.into());
let crate_id = crate_graph.add_crate_root(file_id);
- if tgt.kind(ws) == TargetKind::Lib {
+ if tgt.kind(&ws.cargo) == TargetKind::Lib {
+ lib_tgt = Some(crate_id);
pkg_to_lib_crate.insert(pkg, crate_id);
}
pkg_crates
.push(crate_id);
}
}
+
+ // Set deps to the std and to the lib target of the current package
+ for &from in pkg_crates.get(&pkg).into_iter().flatten() {
+ if let Some(to) = lib_tgt {
+ if to != from {
+ if let Err(_) =
+ crate_graph.add_dep(from, pkg.name(&ws.cargo).into(), to)
+ {
+ log::error!(
+ "cyclic dependency between targets of {}",
+ pkg.name(&ws.cargo)
+ )
+ }
+ }
+ }
+ if let Some(std) = libstd {
+ if let Err(_) = crate_graph.add_dep(from, "std".into(), std) {
+ log::error!("cyclic dependency on std for {}", pkg.name(&ws.cargo))
+ }
+ }
+ }
}
- for pkg in ws.packages() {
- for dep in pkg.dependencies(ws) {
+
+ // Now add a dep ednge from all targets of upstream to the lib
+ // target of downstream.
+ for pkg in ws.cargo.packages() {
+ for dep in pkg.dependencies(&ws.cargo) {
if let Some(&to) = pkg_to_lib_crate.get(&dep.pkg) {
for &from in pkg_crates.get(&pkg).into_iter().flatten() {
- crate_graph.add_dep(from, dep.name.clone(), to);
+ if let Err(_) = crate_graph.add_dep(from, dep.name.clone(), to) {
+ log::error!(
+ "cyclic dependency {} -> {}",
+ pkg.name(&ws.cargo),
+ dep.pkg.name(&ws.cargo)
+ )
+ }
}
}
}
vfs: Arc::clone(&self.vfs),
}
}
+
+ pub fn maybe_collect_garbage(&mut self) {
+ self.analysis_host.maybe_collect_garbage()
+ }
+
+ pub fn collect_garbage(&mut self) {
+ self.analysis_host.collect_garbage()
+ }
}
impl ServerWorld {
.map_err(|_| format_err!("can't convert path to url: {}", path.display()))?;
Ok(url)
}
+
+ pub fn status(&self) -> String {
+ let mut res = String::new();
+ if self.workspaces.is_empty() {
+ res.push_str("no workspaces\n")
+ } else {
+ res.push_str("workspaces:\n");
+ for w in self.workspaces.iter() {
+ res += &format!("{} packages loaded\n", w.cargo.packages().count());
+ }
+ }
+ res.push_str("\nanalysis:\n");
+ res.push_str(&self.analysis.status());
+ res
+ }
}