Add sysroot shortcut to rust-project.json

This commit is contained in:
Aleksey Kladov 2020-08-25 18:34:00 +02:00
parent 91bedefe49
commit 189521a4db
3 changed files with 70 additions and 22 deletions

View file

@ -39,11 +39,18 @@ pub enum ProjectWorkspace {
impl fmt::Debug for ProjectWorkspace {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ProjectWorkspace::Cargo { cargo, .. } => {
f.debug_struct("Cargo").field("n_packages", &cargo.packages().len()).finish()
}
ProjectWorkspace::Cargo { cargo, sysroot } => f
.debug_struct("Cargo")
.field("n_packages", &cargo.packages().len())
.field("n_sysroot_crates", &sysroot.crates().len())
.finish(),
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<_>>()
.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<_>>(),
ProjectWorkspace::Cargo { cargo, sysroot } => cargo
.packages()
@ -272,6 +286,11 @@ impl ProjectWorkspace {
let mut crate_graph = CrateGraph::default();
match self {
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 crates: FxHashMap<_, _> = project
.crates()
@ -309,25 +328,33 @@ impl ProjectWorkspace {
.collect();
for (from, krate) in project.crates() {
for dep in &krate.deps {
let to_crate_id = dep.crate_id;
if let (Some(&from), Some(&to)) =
(crates.get(&from), crates.get(&to_crate_id))
{
if let Err(_) = crate_graph.add_dep(from, dep.name.clone(), to) {
log::error!("cyclic dependency {:?} -> {:?}", from, to_crate_id);
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 {
let to_crate_id = dep.crate_id;
if let Some(&to) = crates.get(&to_crate_id) {
if let Err(_) = crate_graph.add_dep(from, dep.name.clone(), to) {
log::error!("cyclic dependency {:?} -> {:?}", from, to);
}
}
}
}
}
}
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();
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_crates = FxHashMap::default();
@ -410,7 +437,11 @@ impl ProjectWorkspace {
}
for (name, krate) in public_deps.iter() {
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(
crate_graph: &mut CrateGraph,
sysroot: &Sysroot,
cfg_options: &CfgOptions,
target: Option<&str>,
load: &mut dyn FnMut(&AbsPath) -> Option<FileId>,
) -> (Vec<(CrateName, CrateId)>, Option<CrateId>) {
let mut cfg_options = CfgOptions::default();
cfg_options.extend(get_rustc_cfg_options(target));
let sysroot_crates: FxHashMap<_, _> = sysroot
.crates()
.filter_map(|krate| {

View file

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

View file

@ -273,9 +273,19 @@ However, if you use some other build system, you'll have to describe the structu
[source,TypeScript]
----
interface JsonProject {
/// The set of crates comprising the current project.
/// Must include all transitive dependencies as well as sysroot crate (libstd, libcore and such).
crates: Crate[];
/// 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.
/// Must include all transitive dependencies as well as sysroot crate (libstd, libcore and such).
crates: Crate[];
}
interface Crate {