5884: Add sysroot shortcut to rust-project.json
 r=matklad a=matklad

bors r+
🤖

Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
bors[bot] 2020-08-25 17:42:27 +00:00 committed by GitHub
commit f647edcb08
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 70 additions and 22 deletions

View file

@ -39,11 +39,18 @@ pub enum ProjectWorkspace {
impl fmt::Debug for ProjectWorkspace { impl fmt::Debug for ProjectWorkspace {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self { match self {
ProjectWorkspace::Cargo { cargo, .. } => { ProjectWorkspace::Cargo { cargo, sysroot } => f
f.debug_struct("Cargo").field("n_packages", &cargo.packages().len()).finish() .debug_struct("Cargo")
} .field("n_packages", &cargo.packages().len())
.field("n_sysroot_crates", &sysroot.crates().len())
.finish(),
ProjectWorkspace::Json { project } => { ProjectWorkspace::Json { project } => {
f.debug_struct("Json").field("n_crates", &project.n_crates()).finish() let mut debug_struct = f.debug_struct("Json");
debug_struct.field("n_crates", &project.n_crates());
if let Some(sysroot) = &project.sysroot {
debug_struct.field("n_sysroot_crates", &sysroot.crates().len());
}
debug_struct.finish()
} }
} }
} }
@ -210,6 +217,13 @@ impl ProjectWorkspace {
}) })
.collect::<FxHashSet<_>>() .collect::<FxHashSet<_>>()
.into_iter() .into_iter()
.chain(project.sysroot.as_ref().into_iter().flat_map(|sysroot| {
sysroot.crates().map(move |krate| PackageRoot {
is_member: false,
include: vec![sysroot[krate].root_dir().to_path_buf()],
exclude: Vec::new(),
})
}))
.collect::<Vec<_>>(), .collect::<Vec<_>>(),
ProjectWorkspace::Cargo { cargo, sysroot } => cargo ProjectWorkspace::Cargo { cargo, sysroot } => cargo
.packages() .packages()
@ -272,6 +286,11 @@ impl ProjectWorkspace {
let mut crate_graph = CrateGraph::default(); let mut crate_graph = CrateGraph::default();
match self { match self {
ProjectWorkspace::Json { project } => { ProjectWorkspace::Json { project } => {
let sysroot_dps = project
.sysroot
.as_ref()
.map(|sysroot| sysroot_to_crate_graph(&mut crate_graph, sysroot, target, load));
let mut cfg_cache: FxHashMap<Option<&str>, Vec<CfgFlag>> = FxHashMap::default(); let mut cfg_cache: FxHashMap<Option<&str>, Vec<CfgFlag>> = FxHashMap::default();
let crates: FxHashMap<_, _> = project let crates: FxHashMap<_, _> = project
.crates() .crates()
@ -309,25 +328,33 @@ impl ProjectWorkspace {
.collect(); .collect();
for (from, krate) in project.crates() { for (from, krate) in project.crates() {
if let Some(&from) = crates.get(&from) {
if let Some((public_deps, _proc_macro)) = &sysroot_dps {
for (name, to) in public_deps.iter() {
if let Err(_) = crate_graph.add_dep(from, name.clone(), *to) {
log::error!("cyclic dependency on {} for {:?}", name, from)
}
}
}
for dep in &krate.deps { for dep in &krate.deps {
let to_crate_id = dep.crate_id; let to_crate_id = dep.crate_id;
if let (Some(&from), Some(&to)) = if let Some(&to) = crates.get(&to_crate_id) {
(crates.get(&from), crates.get(&to_crate_id))
{
if let Err(_) = 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 {:?} -> {:?}", from, to_crate_id); log::error!("cyclic dependency {:?} -> {:?}", from, to);
}
} }
} }
} }
} }
} }
ProjectWorkspace::Cargo { cargo, sysroot } => { ProjectWorkspace::Cargo { cargo, sysroot } => {
let (public_deps, libproc_macro) =
sysroot_to_crate_graph(&mut crate_graph, sysroot, target, load);
let mut cfg_options = CfgOptions::default(); let mut cfg_options = CfgOptions::default();
cfg_options.extend(get_rustc_cfg_options(target)); cfg_options.extend(get_rustc_cfg_options(target));
let (public_deps, libproc_macro) =
sysroot_to_crate_graph(&mut crate_graph, sysroot, &cfg_options, load);
let mut pkg_to_lib_crate = FxHashMap::default(); let mut pkg_to_lib_crate = FxHashMap::default();
let mut pkg_crates = FxHashMap::default(); let mut pkg_crates = FxHashMap::default();
@ -410,7 +437,11 @@ impl ProjectWorkspace {
} }
for (name, krate) in public_deps.iter() { for (name, krate) in public_deps.iter() {
if let Err(_) = crate_graph.add_dep(from, name.clone(), *krate) { if let Err(_) = crate_graph.add_dep(from, name.clone(), *krate) {
log::error!("cyclic dependency on core for {}", &cargo[pkg].name) log::error!(
"cyclic dependency on {} for {}",
name,
&cargo[pkg].name
)
} }
} }
} }
@ -485,9 +516,11 @@ fn utf8_stdout(mut cmd: Command) -> Result<String> {
fn sysroot_to_crate_graph( fn sysroot_to_crate_graph(
crate_graph: &mut CrateGraph, crate_graph: &mut CrateGraph,
sysroot: &Sysroot, sysroot: &Sysroot,
cfg_options: &CfgOptions, target: Option<&str>,
load: &mut dyn FnMut(&AbsPath) -> Option<FileId>, load: &mut dyn FnMut(&AbsPath) -> Option<FileId>,
) -> (Vec<(CrateName, CrateId)>, Option<CrateId>) { ) -> (Vec<(CrateName, CrateId)>, Option<CrateId>) {
let mut cfg_options = CfgOptions::default();
cfg_options.extend(get_rustc_cfg_options(target));
let sysroot_crates: FxHashMap<_, _> = sysroot let sysroot_crates: FxHashMap<_, _> = sysroot
.crates() .crates()
.filter_map(|krate| { .filter_map(|krate| {

View file

@ -7,11 +7,12 @@ use paths::{AbsPath, AbsPathBuf};
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use serde::{de, Deserialize}; use serde::{de, Deserialize};
use crate::cfg_flag::CfgFlag; use crate::{cfg_flag::CfgFlag, Sysroot};
/// Roots and crates that compose this Rust project. /// Roots and crates that compose this Rust project.
#[derive(Clone, Debug, Eq, PartialEq)] #[derive(Clone, Debug, Eq, PartialEq)]
pub struct ProjectJson { pub struct ProjectJson {
pub(crate) sysroot: Option<Sysroot>,
crates: Vec<Crate>, crates: Vec<Crate>,
} }
@ -34,6 +35,7 @@ pub struct Crate {
impl ProjectJson { impl ProjectJson {
pub fn new(base: &AbsPath, data: ProjectJsonData) -> ProjectJson { pub fn new(base: &AbsPath, data: ProjectJsonData) -> ProjectJson {
ProjectJson { ProjectJson {
sysroot: data.sysroot_src.map(|it| base.join(it)).map(|it| Sysroot::load(&it)),
crates: data crates: data
.crates .crates
.into_iter() .into_iter()
@ -43,11 +45,13 @@ impl ProjectJson {
&& !crate_data.root_module.starts_with("..") && !crate_data.root_module.starts_with("..")
|| crate_data.root_module.starts_with(base) || crate_data.root_module.starts_with(base)
}); });
let root_module = base.join(crate_data.root_module); let root_module = base.join(crate_data.root_module).normalize();
let (include, exclude) = match crate_data.source { let (include, exclude) = match crate_data.source {
Some(src) => { Some(src) => {
let absolutize = |dirs: Vec<PathBuf>| { let absolutize = |dirs: Vec<PathBuf>| {
dirs.into_iter().map(|it| base.join(it)).collect::<Vec<_>>() dirs.into_iter()
.map(|it| base.join(it).normalize())
.collect::<Vec<_>>()
}; };
(absolutize(src.include_dirs), absolutize(src.exclude_dirs)) (absolutize(src.include_dirs), absolutize(src.exclude_dirs))
} }
@ -89,6 +93,7 @@ impl ProjectJson {
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct ProjectJsonData { pub struct ProjectJsonData {
sysroot_src: Option<PathBuf>,
crates: Vec<CrateData>, crates: Vec<CrateData>,
} }

View file

@ -273,6 +273,16 @@ However, if you use some other build system, you'll have to describe the structu
[source,TypeScript] [source,TypeScript]
---- ----
interface JsonProject { interface JsonProject {
/// Path to the directory with *source code* of sysroot crates.
///
/// It should point to the directory where std, core, and friends can be found:
/// https://github.com/rust-lang/rust/tree/master/library.
///
/// If provided, rust-analyzer automatically adds dependencies on sysroot
/// crates. Conversely, if you omit this path, you can specify sysroot
/// dependencies yourself and, for example, have several different "sysroots" in
/// one graph of crates.
sysroot_src?: string;
/// The set of crates comprising the current project. /// The set of crates comprising the current project.
/// Must include all transitive dependencies as well as sysroot crate (libstd, libcore and such). /// Must include all transitive dependencies as well as sysroot crate (libstd, libcore and such).
crates: Crate[]; crates: Crate[];