From cec92407f412b3c8e01d17eab84101a2b858e59e Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 30 Jun 2020 22:12:27 +0200 Subject: Don't crash on empty out_dirs with older cargos closes #5125 --- crates/ra_project_model/src/cargo_workspace.rs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'crates/ra_project_model/src') diff --git a/crates/ra_project_model/src/cargo_workspace.rs b/crates/ra_project_model/src/cargo_workspace.rs index 3b124020d..47a1d393d 100644 --- a/crates/ra_project_model/src/cargo_workspace.rs +++ b/crates/ra_project_model/src/cargo_workspace.rs @@ -1,6 +1,11 @@ //! FIXME: write short doc here -use std::{ffi::OsStr, ops, path::Path, process::Command}; +use std::{ + ffi::OsStr, + ops, + path::{Path, PathBuf}, + process::Command, +}; use anyhow::{Context, Result}; use cargo_metadata::{BuildScript, CargoOpt, Message, MetadataCommand, PackageId}; @@ -308,9 +313,13 @@ pub fn load_extern_resources( if let Ok(message) = message { match message { Message::BuildScriptExecuted(BuildScript { package_id, out_dir, cfgs, .. }) => { - let out_dir = AbsPathBuf::assert(out_dir); - res.out_dirs.insert(package_id.clone(), out_dir); - res.cfgs.insert(package_id, cfgs); + // cargo_metadata crate returns default (empty) path for + // older cargos, which is not absolute, so work around that. + if out_dir != PathBuf::default() { + let out_dir = AbsPathBuf::assert(out_dir); + res.out_dirs.insert(package_id.clone(), out_dir); + res.cfgs.insert(package_id, cfgs); + } } Message::CompilerArtifact(message) => { if message.target.kind.contains(&"proc-macro".to_string()) { -- cgit v1.2.3 From 307c6fec618d5e509c754362687253ef44bb5f3f Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 1 Jul 2020 09:53:53 +0200 Subject: Use CrateName for semantic names --- crates/ra_project_model/src/lib.rs | 5 +---- crates/ra_project_model/src/project_json.rs | 17 +++++++++++++---- 2 files changed, 14 insertions(+), 8 deletions(-) (limited to 'crates/ra_project_model/src') diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs index 8b85b4831..1533d32c9 100644 --- a/crates/ra_project_model/src/lib.rs +++ b/crates/ra_project_model/src/lib.rs @@ -288,10 +288,7 @@ impl ProjectWorkspace { if let (Some(&from), Some(&to)) = (crates.get(&from_crate_id), crates.get(&to_crate_id)) { - if crate_graph - .add_dep(from, CrateName::new(&dep.name).unwrap(), to) - .is_err() - { + if crate_graph.add_dep(from, dep.name.clone(), to).is_err() { log::error!( "cyclic dependency {:?} -> {:?}", from_crate_id, diff --git a/crates/ra_project_model/src/project_json.rs b/crates/ra_project_model/src/project_json.rs index 4b5dcd634..9fe1e2dcb 100644 --- a/crates/ra_project_model/src/project_json.rs +++ b/crates/ra_project_model/src/project_json.rs @@ -4,9 +4,9 @@ use std::path::PathBuf; use paths::{AbsPath, AbsPathBuf}; use ra_cfg::CfgOptions; -use ra_db::{CrateId, Dependency, Edition}; +use ra_db::{CrateId, CrateName, Dependency, Edition}; use rustc_hash::FxHashSet; -use serde::Deserialize; +use serde::{de, Deserialize}; use stdx::split_delim; /// Roots and crates that compose this Rust project. @@ -50,7 +50,7 @@ impl ProjectJson { .into_iter() .map(|dep_data| Dependency { crate_id: CrateId(dep_data.krate as u32), - name: dep_data.name.into(), + name: dep_data.name, }) .collect::>(), cfg: { @@ -113,5 +113,14 @@ struct DepData { /// Identifies a crate by position in the crates array. #[serde(rename = "crate")] krate: usize, - name: String, + #[serde(deserialize_with = "deserialize_crate_name")] + name: CrateName, +} + +fn deserialize_crate_name<'de, D>(de: D) -> Result +where + D: de::Deserializer<'de>, +{ + let name = String::deserialize(de)?; + CrateName::new(&name).map_err(|err| de::Error::custom(format!("invalid crate name: {:?}", err))) } -- cgit v1.2.3 From 80386ca5be78d8ea65483df3edeec1a89b09a5a3 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 1 Jul 2020 10:03:07 +0200 Subject: Use Strings for display names --- crates/ra_project_model/src/lib.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'crates/ra_project_model/src') diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs index 1533d32c9..8dbf4e6ea 100644 --- a/crates/ra_project_model/src/lib.rs +++ b/crates/ra_project_model/src/lib.rs @@ -309,13 +309,11 @@ impl ProjectWorkspace { let env = Env::default(); let proc_macro = vec![]; - let crate_name = CrateName::new(&sysroot[krate].name) - .expect("Sysroot crate names should not contain dashes"); - + let name = sysroot[krate].name.clone(); let crate_id = crate_graph.add_crate_root( file_id, Edition::Edition2018, - Some(crate_name), + Some(name), cfg_options.clone(), env, proc_macro, @@ -389,7 +387,7 @@ impl ProjectWorkspace { let crate_id = crate_graph.add_crate_root( file_id, edition, - Some(CrateName::normalize_dashes(&cargo[pkg].name)), + Some(cargo[pkg].name.clone()), cfg_options, env, proc_macro.clone(), -- cgit v1.2.3 From a03cfa49268d3938b55ceff046d04a75de8972b9 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 1 Jul 2020 16:42:14 +0200 Subject: Automatically reload project on config change --- crates/ra_project_model/src/project_json.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'crates/ra_project_model/src') diff --git a/crates/ra_project_model/src/project_json.rs b/crates/ra_project_model/src/project_json.rs index 9fe1e2dcb..b0fe09333 100644 --- a/crates/ra_project_model/src/project_json.rs +++ b/crates/ra_project_model/src/project_json.rs @@ -10,7 +10,7 @@ use serde::{de, Deserialize}; use stdx::split_delim; /// Roots and crates that compose this Rust project. -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct ProjectJson { pub(crate) roots: Vec, pub(crate) crates: Vec, @@ -18,14 +18,14 @@ pub struct ProjectJson { /// A root points to the directory which contains Rust crates. rust-analyzer watches all files in /// all roots. Roots might be nested. -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct Root { pub(crate) path: AbsPathBuf, } /// A crate points to the root module of a crate and lists the dependencies of the crate. This is /// useful in creating the crate graph. -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct Crate { pub(crate) root_module: AbsPathBuf, pub(crate) edition: Edition, -- cgit v1.2.3 From 6a694ad047802e6e5aec8522556d2db09c10b18f Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 2 Jul 2020 16:06:00 +0200 Subject: Minor --- crates/ra_project_model/src/cargo_workspace.rs | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) (limited to 'crates/ra_project_model/src') diff --git a/crates/ra_project_model/src/cargo_workspace.rs b/crates/ra_project_model/src/cargo_workspace.rs index 47a1d393d..361fc8eea 100644 --- a/crates/ra_project_model/src/cargo_workspace.rs +++ b/crates/ra_project_model/src/cargo_workspace.rs @@ -45,7 +45,7 @@ impl ops::Index for CargoWorkspace { } } -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Default, Clone, Debug, PartialEq, Eq)] pub struct CargoConfig { /// Do not activate the `default` feature. pub no_default_features: bool, @@ -64,18 +64,6 @@ pub struct CargoConfig { pub target: Option, } -impl Default for CargoConfig { - fn default() -> Self { - CargoConfig { - no_default_features: false, - all_features: false, - features: Vec::new(), - load_out_dirs_from_check: false, - target: None, - } - } -} - pub type Package = Idx; pub type Target = Idx; -- cgit v1.2.3 From 6c7578bd7a67b0f8fd1fdb6a043c8523104c5807 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 2 Jul 2020 16:47:42 +0200 Subject: Move cargo metadata off the main loop --- crates/ra_project_model/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'crates/ra_project_model/src') diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs index 8dbf4e6ea..464c3b2e3 100644 --- a/crates/ra_project_model/src/lib.rs +++ b/crates/ra_project_model/src/lib.rs @@ -150,7 +150,7 @@ impl ProjectManifest { impl ProjectWorkspace { pub fn load( manifest: ProjectManifest, - cargo_features: &CargoConfig, + cargo_config: &CargoConfig, with_sysroot: bool, ) -> Result { let res = match manifest { @@ -166,7 +166,7 @@ impl ProjectWorkspace { ProjectWorkspace::Json { project } } ProjectManifest::CargoToml(cargo_toml) => { - let cargo = CargoWorkspace::from_cargo_metadata(&cargo_toml, cargo_features) + let cargo = CargoWorkspace::from_cargo_metadata(&cargo_toml, cargo_config) .with_context(|| { format!( "Failed to read Cargo metadata from Cargo.toml file {}", -- cgit v1.2.3 From db99f2dd7e8e244b858926bbf1d2a49e25f44733 Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Fri, 12 Jun 2020 13:08:51 -0400 Subject: Add optional target to crates in json project, lookup default cfgs per target when generating cfg list --- crates/ra_project_model/src/lib.rs | 11 ++++++++++- crates/ra_project_model/src/project_json.rs | 3 +++ 2 files changed, 13 insertions(+), 1 deletion(-) (limited to 'crates/ra_project_model/src') diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs index 464c3b2e3..4b50b9b69 100644 --- a/crates/ra_project_model/src/lib.rs +++ b/crates/ra_project_model/src/lib.rs @@ -246,6 +246,7 @@ impl ProjectWorkspace { let mut crate_graph = CrateGraph::default(); match self { ProjectWorkspace::Json { project } => { + let mut target_cfg_map = FxHashMap::, CfgOptions>::default(); let crates: FxHashMap<_, _> = project .crates .iter() @@ -265,6 +266,14 @@ impl ProjectWorkspace { .proc_macro_dylib_path .clone() .map(|it| proc_macro_client.by_dylib_path(&it)); + + let target = krate.target.as_deref(); + let target_cfgs = target_cfg_map + .entry(target.clone()) + .or_insert_with(|| get_rustc_cfg_options(target.as_deref())); + let mut cfg_options = krate.cfg.clone(); + cfg_options.append(target_cfgs); + // FIXME: No crate name in json definition such that we cannot add OUT_DIR to env Some(( CrateId(seq_index as u32), @@ -273,7 +282,7 @@ impl ProjectWorkspace { krate.edition, // FIXME json definitions can store the crate name None, - krate.cfg.clone(), + cfg_options, env, proc_macro.unwrap_or_default(), ), diff --git a/crates/ra_project_model/src/project_json.rs b/crates/ra_project_model/src/project_json.rs index b0fe09333..b96227949 100644 --- a/crates/ra_project_model/src/project_json.rs +++ b/crates/ra_project_model/src/project_json.rs @@ -31,6 +31,7 @@ pub struct Crate { pub(crate) edition: Edition, pub(crate) deps: Vec, pub(crate) cfg: CfgOptions, + pub(crate) target: Option, pub(crate) out_dir: Option, pub(crate) proc_macro_dylib_path: Option, } @@ -65,6 +66,7 @@ impl ProjectJson { } cfg }, + target: crate_data.target, out_dir: crate_data.out_dir.map(|it| base.join(it)), proc_macro_dylib_path: crate_data.proc_macro_dylib_path.map(|it| base.join(it)), }) @@ -86,6 +88,7 @@ struct CrateData { deps: Vec, #[serde(default)] cfg: FxHashSet, + target: Option, out_dir: Option, proc_macro_dylib_path: Option, } -- cgit v1.2.3 From 5b96d4103ea25a2dbb9811b082365ff77a89c94d Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Sat, 4 Jul 2020 13:50:27 -0400 Subject: Fallback to target in cfg if not specified in project json config --- crates/ra_project_model/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'crates/ra_project_model/src') diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs index 4b50b9b69..5d1f871c4 100644 --- a/crates/ra_project_model/src/lib.rs +++ b/crates/ra_project_model/src/lib.rs @@ -267,7 +267,7 @@ impl ProjectWorkspace { .clone() .map(|it| proc_macro_client.by_dylib_path(&it)); - let target = krate.target.as_deref(); + let target = krate.target.as_deref().or(target); let target_cfgs = target_cfg_map .entry(target.clone()) .or_insert_with(|| get_rustc_cfg_options(target.as_deref())); -- cgit v1.2.3 From 4be73c2b7f85b75be69bbe99ed4b1f82659a11c9 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 5 Jul 2020 11:15:35 +0200 Subject: AbsPath --- crates/ra_project_model/src/cargo_workspace.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'crates/ra_project_model/src') diff --git a/crates/ra_project_model/src/cargo_workspace.rs b/crates/ra_project_model/src/cargo_workspace.rs index 361fc8eea..04f7eb741 100644 --- a/crates/ra_project_model/src/cargo_workspace.rs +++ b/crates/ra_project_model/src/cargo_workspace.rs @@ -134,12 +134,12 @@ impl PackageData { impl CargoWorkspace { pub fn from_cargo_metadata( - cargo_toml: &Path, + cargo_toml: &AbsPath, cargo_features: &CargoConfig, ) -> Result { let mut meta = MetadataCommand::new(); meta.cargo_path(ra_toolchain::cargo()); - meta.manifest_path(cargo_toml); + meta.manifest_path(cargo_toml.to_path_buf()); if cargo_features.all_features { meta.features(CargoOpt::AllFeatures); } else if cargo_features.no_default_features { @@ -150,7 +150,7 @@ impl CargoWorkspace { meta.features(CargoOpt::SomeFeatures(cargo_features.features.clone())); } if let Some(parent) = cargo_toml.parent() { - meta.current_dir(parent); + meta.current_dir(parent.to_path_buf()); } if let Some(target) = cargo_features.target.as_ref() { meta.other_options(vec![String::from("--filter-platform"), target.clone()]); -- cgit v1.2.3 From 69b79e3a73f9a1b820cf6d5ebc9968d8b08d4e68 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 7 Jul 2020 22:53:12 +0200 Subject: Replace ad hocery with science --- crates/ra_project_model/src/sysroot.rs | 1 - 1 file changed, 1 deletion(-) (limited to 'crates/ra_project_model/src') diff --git a/crates/ra_project_model/src/sysroot.rs b/crates/ra_project_model/src/sysroot.rs index 943ff92df..fc1673ede 100644 --- a/crates/ra_project_model/src/sysroot.rs +++ b/crates/ra_project_model/src/sysroot.rs @@ -126,7 +126,6 @@ core alloc collections libc -panic_unwind proc_macro rustc_unicode std_unicode -- cgit v1.2.3 From d0a8f6a3eb5094af36a72ca01b290a494dfd7b16 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 10 Jul 2020 15:27:34 +0200 Subject: Automatically reload project info on Cargo.toml changes --- crates/ra_project_model/src/cargo_workspace.rs | 8 ++++---- crates/ra_project_model/src/lib.rs | 2 +- crates/ra_project_model/src/sysroot.rs | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) (limited to 'crates/ra_project_model/src') diff --git a/crates/ra_project_model/src/cargo_workspace.rs b/crates/ra_project_model/src/cargo_workspace.rs index 04f7eb741..6d1154056 100644 --- a/crates/ra_project_model/src/cargo_workspace.rs +++ b/crates/ra_project_model/src/cargo_workspace.rs @@ -24,7 +24,7 @@ use rustc_hash::FxHashMap; /// /// We use absolute paths here, `cargo metadata` guarantees to always produce /// abs paths. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Eq, PartialEq)] pub struct CargoWorkspace { packages: Arena, targets: Arena, @@ -68,7 +68,7 @@ pub type Package = Idx; pub type Target = Idx; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Eq, PartialEq)] pub struct PackageData { pub version: String, pub name: String, @@ -83,13 +83,13 @@ pub struct PackageData { pub proc_macro_dylib_path: Option, } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Eq, PartialEq)] pub struct PackageDependency { pub pkg: Package, pub name: String, } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Eq, PartialEq)] pub struct TargetData { pub package: Package, pub name: String, diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs index 5d1f871c4..b9c5424bf 100644 --- a/crates/ra_project_model/src/lib.rs +++ b/crates/ra_project_model/src/lib.rs @@ -24,7 +24,7 @@ pub use crate::{ }; pub use ra_proc_macro::ProcMacroClient; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Eq, PartialEq)] pub enum ProjectWorkspace { /// Project workspace was discovered by running `cargo metadata` and `rustc --print sysroot`. Cargo { cargo: CargoWorkspace, sysroot: Sysroot }, diff --git a/crates/ra_project_model/src/sysroot.rs b/crates/ra_project_model/src/sysroot.rs index fc1673ede..68d134da4 100644 --- a/crates/ra_project_model/src/sysroot.rs +++ b/crates/ra_project_model/src/sysroot.rs @@ -3,19 +3,19 @@ use std::{convert::TryFrom, env, ops, path::Path, process::Command}; use anyhow::{bail, format_err, Result}; +use paths::{AbsPath, AbsPathBuf}; use ra_arena::{Arena, Idx}; use crate::output; -use paths::{AbsPath, AbsPathBuf}; -#[derive(Default, Debug, Clone)] +#[derive(Default, Debug, Clone, Eq, PartialEq)] pub struct Sysroot { crates: Arena, } pub type SysrootCrate = Idx; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Eq, PartialEq)] pub struct SysrootCrateData { pub name: String, pub root: AbsPathBuf, -- cgit v1.2.3 From 676d2e040dfe619d666d5b3068db47346655f23b Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 10 Jul 2020 22:28:41 +0200 Subject: Sort cargo metadata See https://github.com/rust-lang/cargo/issues/8477 We need this to prevent spurious workspace reloads --- crates/ra_project_model/src/cargo_workspace.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'crates/ra_project_model/src') diff --git a/crates/ra_project_model/src/cargo_workspace.rs b/crates/ra_project_model/src/cargo_workspace.rs index 6d1154056..4182ca156 100644 --- a/crates/ra_project_model/src/cargo_workspace.rs +++ b/crates/ra_project_model/src/cargo_workspace.rs @@ -155,7 +155,7 @@ impl CargoWorkspace { if let Some(target) = cargo_features.target.as_ref() { meta.other_options(vec![String::from("--filter-platform"), target.clone()]); } - let meta = meta.exec().with_context(|| { + let mut meta = meta.exec().with_context(|| { format!("Failed to run `cargo metadata --manifest-path {}`", cargo_toml.display()) })?; @@ -175,6 +175,7 @@ impl CargoWorkspace { let ws_members = &meta.workspace_members; + meta.packages.sort_by(|a, b| a.id.cmp(&b.id)); for meta_pkg in meta.packages { let cargo_metadata::Package { id, edition, name, manifest_path, version, .. } = meta_pkg; @@ -210,7 +211,7 @@ impl CargoWorkspace { } } let resolve = meta.resolve.expect("metadata executed with deps"); - for node in resolve.nodes { + for mut node in resolve.nodes { let source = match pkg_by_id.get(&node.id) { Some(&src) => src, // FIXME: replace this and a similar branch below with `.unwrap`, once @@ -221,6 +222,7 @@ impl CargoWorkspace { continue; } }; + node.deps.sort_by(|a, b| a.pkg.cmp(&b.pkg)); for dep_node in node.deps { let pkg = match pkg_by_id.get(&dep_node.pkg) { Some(&pkg) => pkg, -- cgit v1.2.3 From bc4d047267232db485e24f74c05ad03f76b1786b Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Mon, 20 Jul 2020 17:57:10 +0200 Subject: Add is_workspace_member for rust-project.json It is currently unused, but, in the future, it will be used to: * drive certain UX (symbols search by default will look only in the members) * improve performance (rust-analyzer will assume that non-members change rarely) If not specified, is_workspace member is inferred from the path --- crates/ra_project_model/src/project_json.rs | 60 +++++++++++++++++------------ 1 file changed, 36 insertions(+), 24 deletions(-) (limited to 'crates/ra_project_model/src') diff --git a/crates/ra_project_model/src/project_json.rs b/crates/ra_project_model/src/project_json.rs index b96227949..778cc84ef 100644 --- a/crates/ra_project_model/src/project_json.rs +++ b/crates/ra_project_model/src/project_json.rs @@ -34,6 +34,7 @@ pub struct Crate { pub(crate) target: Option, pub(crate) out_dir: Option, pub(crate) proc_macro_dylib_path: Option, + pub(crate) is_workspace_member: bool, } impl ProjectJson { @@ -43,32 +44,42 @@ impl ProjectJson { crates: data .crates .into_iter() - .map(|crate_data| Crate { - root_module: base.join(crate_data.root_module), - edition: crate_data.edition.into(), - deps: crate_data - .deps - .into_iter() - .map(|dep_data| Dependency { - crate_id: CrateId(dep_data.krate as u32), - name: dep_data.name, - }) - .collect::>(), - cfg: { - let mut cfg = CfgOptions::default(); - for entry in &crate_data.cfg { - match split_delim(entry, '=') { - Some((key, value)) => { - cfg.insert_key_value(key.into(), value.into()); + .map(|crate_data| { + let is_workspace_member = crate_data.is_workspace_member.unwrap_or_else(|| { + crate_data.root_module.is_relative() + && !crate_data.root_module.starts_with("..") + || crate_data.root_module.starts_with(base) + }); + Crate { + root_module: base.join(crate_data.root_module), + edition: crate_data.edition.into(), + deps: crate_data + .deps + .into_iter() + .map(|dep_data| Dependency { + crate_id: CrateId(dep_data.krate as u32), + name: dep_data.name, + }) + .collect::>(), + cfg: { + let mut cfg = CfgOptions::default(); + for entry in &crate_data.cfg { + match split_delim(entry, '=') { + Some((key, value)) => { + cfg.insert_key_value(key.into(), value.into()); + } + None => cfg.insert_atom(entry.into()), } - None => cfg.insert_atom(entry.into()), } - } - cfg - }, - target: crate_data.target, - out_dir: crate_data.out_dir.map(|it| base.join(it)), - proc_macro_dylib_path: crate_data.proc_macro_dylib_path.map(|it| base.join(it)), + cfg + }, + target: crate_data.target, + out_dir: crate_data.out_dir.map(|it| base.join(it)), + proc_macro_dylib_path: crate_data + .proc_macro_dylib_path + .map(|it| base.join(it)), + is_workspace_member, + } }) .collect::>(), } @@ -91,6 +102,7 @@ struct CrateData { target: Option, out_dir: Option, proc_macro_dylib_path: Option, + is_workspace_member: Option, } #[derive(Deserialize)] -- cgit v1.2.3 From 39a2bc5e3cd86876eef6f3a96bef188f88e85114 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 21 Jul 2020 12:52:51 +0200 Subject: Expose package roots more directly --- crates/ra_project_model/src/lib.rs | 62 ++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 30 deletions(-) (limited to 'crates/ra_project_model/src') diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs index b9c5424bf..cf46048e5 100644 --- a/crates/ra_project_model/src/lib.rs +++ b/crates/ra_project_model/src/lib.rs @@ -37,28 +37,10 @@ pub enum ProjectWorkspace { /// the current workspace. #[derive(Debug, Clone)] pub struct PackageRoot { - /// Path to the root folder - path: AbsPathBuf, /// Is a member of the current workspace - is_member: bool, - out_dir: Option, -} -impl PackageRoot { - pub fn new_member(path: AbsPathBuf) -> PackageRoot { - Self { path, is_member: true, out_dir: None } - } - pub fn new_non_member(path: AbsPathBuf) -> PackageRoot { - Self { path, is_member: false, out_dir: None } - } - pub fn path(&self) -> &AbsPath { - &self.path - } - pub fn out_dir(&self) -> Option<&AbsPath> { - self.out_dir.as_deref() - } - pub fn is_member(&self) -> bool { - self.is_member - } + pub is_member: bool, + pub include: Vec, + pub exclude: Vec, } #[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)] @@ -195,18 +177,38 @@ impl ProjectWorkspace { /// the root is a member of the current workspace pub fn to_roots(&self) -> Vec { match self { - ProjectWorkspace::Json { project } => { - project.roots.iter().map(|r| PackageRoot::new_member(r.path.clone())).collect() - } + ProjectWorkspace::Json { project } => project + .roots + .iter() + .map(|r| { + let path = r.path.clone(); + let include = vec![path]; + PackageRoot { is_member: true, include, exclude: Vec::new() } + }) + .collect(), ProjectWorkspace::Cargo { cargo, sysroot } => cargo .packages() - .map(|pkg| PackageRoot { - path: cargo[pkg].root().to_path_buf(), - is_member: cargo[pkg].is_member, - out_dir: cargo[pkg].out_dir.clone(), + .map(|pkg| { + let is_member = cargo[pkg].is_member; + let pkg_root = cargo[pkg].root().to_path_buf(); + + let mut include = vec![pkg_root.clone()]; + include.extend(cargo[pkg].out_dir.clone()); + + let mut exclude = vec![pkg_root.join(".git")]; + if is_member { + exclude.push(pkg_root.join("target")); + } else { + exclude.push(pkg_root.join("tests")); + exclude.push(pkg_root.join("examples")); + exclude.push(pkg_root.join("benches")); + } + PackageRoot { is_member, include, exclude } }) - .chain(sysroot.crates().map(|krate| { - PackageRoot::new_non_member(sysroot[krate].root_dir().to_path_buf()) + .chain(sysroot.crates().map(|krate| PackageRoot { + is_member: false, + include: vec![sysroot[krate].root_dir().to_path_buf()], + exclude: Vec::new(), })) .collect(), } -- cgit v1.2.3 From fe87aec7b61c7cf4c62162f257655507c4fd9422 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 21 Jul 2020 14:57:20 +0200 Subject: Replace roots with include/exclude directories --- crates/ra_project_model/src/lib.rs | 29 ++++++++---------------- crates/ra_project_model/src/project_json.rs | 34 +++++++++++++++++++---------- 2 files changed, 32 insertions(+), 31 deletions(-) (limited to 'crates/ra_project_model/src') diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs index cf46048e5..05f2e7b7a 100644 --- a/crates/ra_project_model/src/lib.rs +++ b/crates/ra_project_model/src/lib.rs @@ -7,7 +7,6 @@ mod sysroot; use std::{ fs::{self, read_dir, ReadDir}, io, - path::Path, process::{Command, Output}, }; @@ -35,7 +34,7 @@ pub enum ProjectWorkspace { /// `PackageRoot` describes a package root folder. /// Which may be an external dependency, or a member of /// the current workspace. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Eq, PartialEq, Hash)] pub struct PackageRoot { /// Is a member of the current workspace pub is_member: bool, @@ -178,14 +177,16 @@ impl ProjectWorkspace { pub fn to_roots(&self) -> Vec { match self { ProjectWorkspace::Json { project } => project - .roots + .crates .iter() - .map(|r| { - let path = r.path.clone(); - let include = vec![path]; - PackageRoot { is_member: true, include, exclude: Vec::new() } + .map(|krate| PackageRoot { + is_member: krate.is_workspace_member, + include: krate.include.clone(), + exclude: krate.exclude.clone(), }) - .collect(), + .collect::>() + .into_iter() + .collect::>(), ProjectWorkspace::Cargo { cargo, sysroot } => cargo .packages() .map(|pkg| { @@ -505,18 +506,6 @@ impl ProjectWorkspace { } crate_graph } - - pub fn workspace_root_for(&self, path: &Path) -> Option<&AbsPath> { - match self { - ProjectWorkspace::Cargo { cargo, .. } => { - Some(cargo.workspace_root()).filter(|root| path.starts_with(root)) - } - ProjectWorkspace::Json { project: ProjectJson { roots, .. }, .. } => roots - .iter() - .find(|root| path.starts_with(&root.path)) - .map(|root| root.path.as_path()), - } - } } fn get_rustc_cfg_options(target: Option<&str>) -> CfgOptions { diff --git a/crates/ra_project_model/src/project_json.rs b/crates/ra_project_model/src/project_json.rs index 778cc84ef..e0052ac6d 100644 --- a/crates/ra_project_model/src/project_json.rs +++ b/crates/ra_project_model/src/project_json.rs @@ -12,17 +12,9 @@ use stdx::split_delim; /// Roots and crates that compose this Rust project. #[derive(Clone, Debug, Eq, PartialEq)] pub struct ProjectJson { - pub(crate) roots: Vec, pub(crate) crates: Vec, } -/// A root points to the directory which contains Rust crates. rust-analyzer watches all files in -/// all roots. Roots might be nested. -#[derive(Clone, Debug, Eq, PartialEq)] -pub struct Root { - pub(crate) path: AbsPathBuf, -} - /// A crate points to the root module of a crate and lists the dependencies of the crate. This is /// useful in creating the crate graph. #[derive(Clone, Debug, Eq, PartialEq)] @@ -35,12 +27,13 @@ pub struct Crate { pub(crate) out_dir: Option, pub(crate) proc_macro_dylib_path: Option, pub(crate) is_workspace_member: bool, + pub(crate) include: Vec, + pub(crate) exclude: Vec, } impl ProjectJson { pub fn new(base: &AbsPath, data: ProjectJsonData) -> ProjectJson { ProjectJson { - roots: data.roots.into_iter().map(|path| Root { path: base.join(path) }).collect(), crates: data .crates .into_iter() @@ -50,8 +43,19 @@ 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 (include, exclude) = match crate_data.source { + Some(src) => { + let absolutize = |dirs: Vec| { + dirs.into_iter().map(|it| base.join(it)).collect::>() + }; + (absolutize(src.include_dirs), absolutize(src.exclude_dirs)) + } + None => (vec![root_module.parent().unwrap().to_path_buf()], Vec::new()), + }; + Crate { - root_module: base.join(crate_data.root_module), + root_module, edition: crate_data.edition.into(), deps: crate_data .deps @@ -79,6 +83,8 @@ impl ProjectJson { .proc_macro_dylib_path .map(|it| base.join(it)), is_workspace_member, + include, + exclude, } }) .collect::>(), @@ -88,7 +94,6 @@ impl ProjectJson { #[derive(Deserialize)] pub struct ProjectJsonData { - roots: Vec, crates: Vec, } @@ -103,6 +108,7 @@ struct CrateData { out_dir: Option, proc_macro_dylib_path: Option, is_workspace_member: Option, + source: Option, } #[derive(Deserialize)] @@ -132,6 +138,12 @@ struct DepData { name: CrateName, } +#[derive(Deserialize)] +struct CrateSource { + include_dirs: Vec, + exclude_dirs: Vec, +} + fn deserialize_crate_name<'de, D>(de: D) -> Result where D: de::Deserializer<'de>, -- cgit v1.2.3 From b48336bf940ce1b55e72d244ff9f28573f2e5548 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 21 Jul 2020 15:12:12 +0200 Subject: Replace OUT_DIR in project.json with general env OUT_DIR doesn't make sense here, as this is a cargo-specific concept --- crates/ra_project_model/src/lib.rs | 7 ++----- crates/ra_project_model/src/project_json.rs | 9 +++++---- 2 files changed, 7 insertions(+), 9 deletions(-) (limited to 'crates/ra_project_model/src') diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs index 05f2e7b7a..2bb156610 100644 --- a/crates/ra_project_model/src/lib.rs +++ b/crates/ra_project_model/src/lib.rs @@ -259,11 +259,8 @@ impl ProjectWorkspace { let file_id = load(&file_path)?; let mut env = Env::default(); - if let Some(out_dir) = &krate.out_dir { - // NOTE: cargo and rustc seem to hide non-UTF-8 strings from env! and option_env!() - if let Some(out_dir) = out_dir.to_str().map(|s| s.to_owned()) { - env.set("OUT_DIR", out_dir); - } + for (k, v) in &krate.env { + env.set(k, v.clone()); } let proc_macro = krate .proc_macro_dylib_path diff --git a/crates/ra_project_model/src/project_json.rs b/crates/ra_project_model/src/project_json.rs index e0052ac6d..e9a333191 100644 --- a/crates/ra_project_model/src/project_json.rs +++ b/crates/ra_project_model/src/project_json.rs @@ -5,7 +5,7 @@ use std::path::PathBuf; use paths::{AbsPath, AbsPathBuf}; use ra_cfg::CfgOptions; use ra_db::{CrateId, CrateName, Dependency, Edition}; -use rustc_hash::FxHashSet; +use rustc_hash::{FxHashMap, FxHashSet}; use serde::{de, Deserialize}; use stdx::split_delim; @@ -24,7 +24,7 @@ pub struct Crate { pub(crate) deps: Vec, pub(crate) cfg: CfgOptions, pub(crate) target: Option, - pub(crate) out_dir: Option, + pub(crate) env: FxHashMap, pub(crate) proc_macro_dylib_path: Option, pub(crate) is_workspace_member: bool, pub(crate) include: Vec, @@ -78,7 +78,7 @@ impl ProjectJson { cfg }, target: crate_data.target, - out_dir: crate_data.out_dir.map(|it| base.join(it)), + env: crate_data.env, proc_macro_dylib_path: crate_data .proc_macro_dylib_path .map(|it| base.join(it)), @@ -105,7 +105,8 @@ struct CrateData { #[serde(default)] cfg: FxHashSet, target: Option, - out_dir: Option, + #[serde(default)] + env: FxHashMap, proc_macro_dylib_path: Option, is_workspace_member: Option, source: Option, -- cgit v1.2.3 From b68ef1231daf6eb1abeb06a30dc89af1254b833d Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 21 Jul 2020 17:17:21 +0200 Subject: More Rustic API for Env --- crates/ra_project_model/src/lib.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'crates/ra_project_model/src') diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs index 2bb156610..6da4d7928 100644 --- a/crates/ra_project_model/src/lib.rs +++ b/crates/ra_project_model/src/lib.rs @@ -258,10 +258,7 @@ impl ProjectWorkspace { let file_path = &krate.root_module; let file_id = load(&file_path)?; - let mut env = Env::default(); - for (k, v) in &krate.env { - env.set(k, v.clone()); - } + let env = krate.env.clone().into_iter().collect(); let proc_macro = krate .proc_macro_dylib_path .clone() -- cgit v1.2.3 From 38e38d9b290ff90973c25a06962b81dbbb5d3d9e Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 23 Jul 2020 16:22:17 +0200 Subject: Cleanup CFG API --- crates/ra_project_model/src/lib.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'crates/ra_project_model/src') diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs index b9c5424bf..6ca53c6d8 100644 --- a/crates/ra_project_model/src/lib.rs +++ b/crates/ra_project_model/src/lib.rs @@ -16,6 +16,7 @@ use paths::{AbsPath, AbsPathBuf}; use ra_cfg::CfgOptions; use ra_db::{CrateGraph, CrateId, CrateName, Edition, Env, FileId}; use rustc_hash::{FxHashMap, FxHashSet}; +use stdx::split_delim; pub use crate::{ cargo_workspace::{CargoConfig, CargoWorkspace, Package, Target, TargetKind}, @@ -544,11 +545,10 @@ fn get_rustc_cfg_options(target: Option<&str>) -> CfgOptions { match rustc_cfgs { Ok(rustc_cfgs) => { for line in rustc_cfgs.lines() { - match line.find('=') { + match split_delim(line, '=') { None => cfg_options.insert_atom(line.into()), - Some(pos) => { - let key = &line[..pos]; - let value = line[pos + 1..].trim_matches('"'); + Some((key, value)) => { + let value = value.trim_matches('"'); cfg_options.insert_key_value(key.into(), value.into()); } } -- cgit v1.2.3 From 7c0743293e5720a5be7b44b4a781b2982d63152a Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 23 Jul 2020 18:57:27 +0200 Subject: Require quotes around key-value cfg flags in rust-project.json This matches rustc command-line flags, as well as the build.rs format. --- crates/ra_project_model/src/cargo_workspace.rs | 18 +++++- crates/ra_project_model/src/cfg_flag.rs | 51 +++++++++++++++++ crates/ra_project_model/src/lib.rs | 77 ++++++++++---------------- crates/ra_project_model/src/project_json.rs | 23 ++------ crates/ra_project_model/src/sysroot.rs | 7 +-- 5 files changed, 106 insertions(+), 70 deletions(-) create mode 100644 crates/ra_project_model/src/cfg_flag.rs (limited to 'crates/ra_project_model/src') diff --git a/crates/ra_project_model/src/cargo_workspace.rs b/crates/ra_project_model/src/cargo_workspace.rs index 4182ca156..fb88e0f06 100644 --- a/crates/ra_project_model/src/cargo_workspace.rs +++ b/crates/ra_project_model/src/cargo_workspace.rs @@ -14,6 +14,8 @@ use ra_arena::{Arena, Idx}; use ra_db::Edition; use rustc_hash::FxHashMap; +use crate::cfg_flag::CfgFlag; + /// `CargoWorkspace` represents the logical structure of, well, a Cargo /// workspace. It pretty closely mirrors `cargo metadata` output. /// @@ -78,7 +80,7 @@ pub struct PackageData { pub dependencies: Vec, pub edition: Edition, pub features: Vec, - pub cfgs: Vec, + pub cfgs: Vec, pub out_dir: Option, pub proc_macro_dylib_path: Option, } @@ -276,7 +278,7 @@ impl CargoWorkspace { pub struct ExternResources { out_dirs: FxHashMap, proc_dylib_paths: FxHashMap, - cfgs: FxHashMap>, + cfgs: FxHashMap>, } pub fn load_extern_resources( @@ -303,6 +305,18 @@ pub fn load_extern_resources( if let Ok(message) = message { match message { Message::BuildScriptExecuted(BuildScript { package_id, out_dir, cfgs, .. }) => { + let cfgs = { + let mut acc = Vec::new(); + for cfg in cfgs { + match cfg.parse::() { + Ok(it) => acc.push(it), + Err(err) => { + anyhow::bail!("invalid cfg from cargo-metadata: {}", err) + } + }; + } + acc + }; // cargo_metadata crate returns default (empty) path for // older cargos, which is not absolute, so work around that. if out_dir != PathBuf::default() { diff --git a/crates/ra_project_model/src/cfg_flag.rs b/crates/ra_project_model/src/cfg_flag.rs new file mode 100644 index 000000000..1bc5d4832 --- /dev/null +++ b/crates/ra_project_model/src/cfg_flag.rs @@ -0,0 +1,51 @@ +//! Parsing of CfgFlags as command line arguments, as in +//! +//! rustc main.rs --cfg foo --cfg 'feature="bar"' +use std::str::FromStr; + +use ra_cfg::CfgOptions; +use stdx::split_delim; + +#[derive(Clone, Eq, PartialEq, Debug)] +pub enum CfgFlag { + Atom(String), + KeyValue { key: String, value: String }, +} + +impl FromStr for CfgFlag { + type Err = String; + fn from_str(s: &str) -> Result { + let res = match split_delim(s, '=') { + Some((key, value)) => { + if !(value.starts_with('"') && value.ends_with('"')) { + return Err(format!("Invalid cfg ({:?}), value should be in quotes", s)); + } + let key = key.to_string(); + let value = value[1..value.len() - 1].to_string(); + CfgFlag::KeyValue { key, value } + } + None => CfgFlag::Atom(s.into()), + }; + Ok(res) + } +} + +impl<'de> serde::Deserialize<'de> for CfgFlag { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + String::deserialize(deserializer)?.parse().map_err(serde::de::Error::custom) + } +} + +impl Extend for CfgOptions { + fn extend>(&mut self, iter: T) { + for cfg_flag in iter { + match cfg_flag { + CfgFlag::Atom(it) => self.insert_atom(it.into()), + CfgFlag::KeyValue { key, value } => self.insert_key_value(key.into(), value.into()), + } + } + } +} diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs index 8053712ff..300e75135 100644 --- a/crates/ra_project_model/src/lib.rs +++ b/crates/ra_project_model/src/lib.rs @@ -3,11 +3,12 @@ mod cargo_workspace; mod project_json; mod sysroot; +mod cfg_flag; use std::{ fs::{self, read_dir, ReadDir}, io, - process::{Command, Output}, + process::Command, }; use anyhow::{bail, Context, Result}; @@ -15,13 +16,15 @@ use paths::{AbsPath, AbsPathBuf}; use ra_cfg::CfgOptions; use ra_db::{CrateGraph, CrateId, CrateName, Edition, Env, FileId}; use rustc_hash::{FxHashMap, FxHashSet}; -use stdx::split_delim; + +use crate::cfg_flag::CfgFlag; pub use crate::{ cargo_workspace::{CargoConfig, CargoWorkspace, Package, Target, TargetKind}, project_json::{ProjectJson, ProjectJsonData}, sysroot::Sysroot, }; + pub use ra_proc_macro::ProcMacroClient; #[derive(Debug, Clone, Eq, PartialEq)] @@ -250,7 +253,7 @@ impl ProjectWorkspace { let mut crate_graph = CrateGraph::default(); match self { ProjectWorkspace::Json { project } => { - let mut target_cfg_map = FxHashMap::, CfgOptions>::default(); + let mut cfg_cache: FxHashMap, Vec> = FxHashMap::default(); let crates: FxHashMap<_, _> = project .crates .iter() @@ -266,11 +269,12 @@ impl ProjectWorkspace { .map(|it| proc_macro_client.by_dylib_path(&it)); let target = krate.target.as_deref().or(target); - let target_cfgs = target_cfg_map - .entry(target.clone()) - .or_insert_with(|| get_rustc_cfg_options(target.as_deref())); - let mut cfg_options = krate.cfg.clone(); - cfg_options.append(target_cfgs); + let target_cfgs = cfg_cache + .entry(target) + .or_insert_with(|| get_rustc_cfg_options(target)); + + let mut cfg_options = CfgOptions::default(); + cfg_options.extend(target_cfgs.iter().chain(krate.cfg.iter()).cloned()); // FIXME: No crate name in json definition such that we cannot add OUT_DIR to env Some(( @@ -307,7 +311,8 @@ impl ProjectWorkspace { } } ProjectWorkspace::Cargo { cargo, sysroot } => { - let mut cfg_options = get_rustc_cfg_options(target); + let mut cfg_options = CfgOptions::default(); + cfg_options.extend(get_rustc_cfg_options(target)); let sysroot_crates: FxHashMap<_, _> = sysroot .crates() @@ -354,6 +359,7 @@ impl ProjectWorkspace { // Add test cfg for non-sysroot crates cfg_options.insert_atom("test".into()); + cfg_options.insert_atom("debug_assertions".into()); // Next, create crates for each package, target pair for pkg in cargo.packages() { @@ -367,15 +373,7 @@ impl ProjectWorkspace { for feature in cargo[pkg].features.iter() { opts.insert_key_value("feature".into(), feature.into()); } - for cfg in cargo[pkg].cfgs.iter() { - match cfg.find('=') { - Some(split) => opts.insert_key_value( - cfg[..split].into(), - cfg[split + 1..].trim_matches('"').into(), - ), - None => opts.insert_atom(cfg.into()), - }; - } + opts.extend(cargo[pkg].cfgs.iter().cloned()); opts }; let mut env = Env::default(); @@ -503,51 +501,35 @@ impl ProjectWorkspace { } } -fn get_rustc_cfg_options(target: Option<&str>) -> CfgOptions { - let mut cfg_options = CfgOptions::default(); +fn get_rustc_cfg_options(target: Option<&str>) -> Vec { + let mut res = Vec::new(); // Some nightly-only cfgs, which are required for stdlib - { - cfg_options.insert_atom("target_thread_local".into()); - for &target_has_atomic in ["8", "16", "32", "64", "cas", "ptr"].iter() { - cfg_options.insert_key_value("target_has_atomic".into(), target_has_atomic.into()); - cfg_options - .insert_key_value("target_has_atomic_load_store".into(), target_has_atomic.into()); + res.push(CfgFlag::Atom("target_thread_local".into())); + for &ty in ["8", "16", "32", "64", "cas", "ptr"].iter() { + for &key in ["target_has_atomic", "target_has_atomic_load_store"].iter() { + res.push(CfgFlag::KeyValue { key: key.to_string(), value: ty.into() }); } } - let rustc_cfgs = || -> Result { - // `cfg(test)` and `cfg(debug_assertion)` are handled outside, so we suppress them here. + let rustc_cfgs = { let mut cmd = Command::new(ra_toolchain::rustc()); cmd.args(&["--print", "cfg", "-O"]); if let Some(target) = target { cmd.args(&["--target", target]); } - let output = output(cmd)?; - Ok(String::from_utf8(output.stdout)?) - }(); + utf8_stdout(cmd) + }; match rustc_cfgs { - Ok(rustc_cfgs) => { - for line in rustc_cfgs.lines() { - match split_delim(line, '=') { - None => cfg_options.insert_atom(line.into()), - Some((key, value)) => { - let value = value.trim_matches('"'); - cfg_options.insert_key_value(key.into(), value.into()); - } - } - } - } + Ok(rustc_cfgs) => res.extend(rustc_cfgs.lines().map(|it| it.parse().unwrap())), Err(e) => log::error!("failed to get rustc cfgs: {:#}", e), } - cfg_options.insert_atom("debug_assertions".into()); - - cfg_options + res } -fn output(mut cmd: Command) -> Result { +fn utf8_stdout(mut cmd: Command) -> Result { let output = cmd.output().with_context(|| format!("{:?} failed", cmd))?; if !output.status.success() { match String::from_utf8(output.stderr) { @@ -557,5 +539,6 @@ fn output(mut cmd: Command) -> Result { _ => bail!("{:?} failed, {}", cmd, output.status), } } - Ok(output) + let stdout = String::from_utf8(output.stdout)?; + Ok(stdout) } diff --git a/crates/ra_project_model/src/project_json.rs b/crates/ra_project_model/src/project_json.rs index e9a333191..e3f3163f6 100644 --- a/crates/ra_project_model/src/project_json.rs +++ b/crates/ra_project_model/src/project_json.rs @@ -3,11 +3,11 @@ use std::path::PathBuf; use paths::{AbsPath, AbsPathBuf}; -use ra_cfg::CfgOptions; use ra_db::{CrateId, CrateName, Dependency, Edition}; -use rustc_hash::{FxHashMap, FxHashSet}; +use rustc_hash::FxHashMap; use serde::{de, Deserialize}; -use stdx::split_delim; + +use crate::cfg_flag::CfgFlag; /// Roots and crates that compose this Rust project. #[derive(Clone, Debug, Eq, PartialEq)] @@ -22,7 +22,7 @@ pub struct Crate { pub(crate) root_module: AbsPathBuf, pub(crate) edition: Edition, pub(crate) deps: Vec, - pub(crate) cfg: CfgOptions, + pub(crate) cfg: Vec, pub(crate) target: Option, pub(crate) env: FxHashMap, pub(crate) proc_macro_dylib_path: Option, @@ -65,18 +65,7 @@ impl ProjectJson { name: dep_data.name, }) .collect::>(), - cfg: { - let mut cfg = CfgOptions::default(); - for entry in &crate_data.cfg { - match split_delim(entry, '=') { - Some((key, value)) => { - cfg.insert_key_value(key.into(), value.into()); - } - None => cfg.insert_atom(entry.into()), - } - } - cfg - }, + cfg: crate_data.cfg, target: crate_data.target, env: crate_data.env, proc_macro_dylib_path: crate_data @@ -103,7 +92,7 @@ struct CrateData { edition: EditionData, deps: Vec, #[serde(default)] - cfg: FxHashSet, + cfg: Vec, target: Option, #[serde(default)] env: FxHashMap, diff --git a/crates/ra_project_model/src/sysroot.rs b/crates/ra_project_model/src/sysroot.rs index 68d134da4..8a92acea5 100644 --- a/crates/ra_project_model/src/sysroot.rs +++ b/crates/ra_project_model/src/sysroot.rs @@ -6,7 +6,7 @@ use anyhow::{bail, format_err, Result}; use paths::{AbsPath, AbsPathBuf}; use ra_arena::{Arena, Idx}; -use crate::output; +use crate::utf8_stdout; #[derive(Default, Debug, Clone, Eq, PartialEq)] pub struct Sysroot { @@ -92,15 +92,14 @@ fn get_or_install_rust_src(cargo_toml: &AbsPath) -> Result { let current_dir = cargo_toml.parent().unwrap(); let mut rustc = Command::new(ra_toolchain::rustc()); rustc.current_dir(current_dir).args(&["--print", "sysroot"]); - let rustc_output = output(rustc)?; - let stdout = String::from_utf8(rustc_output.stdout)?; + let stdout = utf8_stdout(rustc)?; let sysroot_path = AbsPath::assert(Path::new(stdout.trim())); let src_path = sysroot_path.join("lib/rustlib/src/rust/src"); if !src_path.exists() { let mut rustup = Command::new(ra_toolchain::rustup()); rustup.current_dir(current_dir).args(&["component", "add", "rust-src"]); - let _output = output(rustup)?; + utf8_stdout(rustup)?; } if !src_path.exists() { bail!( -- cgit v1.2.3 From a538e0fbe815a4543f3b547d7a20469bebc2e3ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Thu, 30 Jul 2020 15:04:41 +0300 Subject: Add workaround for changing sysroot paths --- crates/ra_project_model/src/sysroot.rs | 42 +++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 8 deletions(-) (limited to 'crates/ra_project_model/src') diff --git a/crates/ra_project_model/src/sysroot.rs b/crates/ra_project_model/src/sysroot.rs index 8a92acea5..9e23b5805 100644 --- a/crates/ra_project_model/src/sysroot.rs +++ b/crates/ra_project_model/src/sysroot.rs @@ -54,6 +54,8 @@ impl Sysroot { let src = get_or_install_rust_src(cargo_toml)?; let mut sysroot = Sysroot { crates: Arena::default() }; for name in SYSROOT_CRATES.trim().lines() { + // FIXME: remove this path when 1.47 comes out + // https://github.com/rust-lang/rust/pull/73265 let root = src.join(format!("lib{}", name)).join("lib.rs"); if root.exists() { sysroot.crates.alloc(SysrootCrateData { @@ -61,6 +63,15 @@ impl Sysroot { root, deps: Vec::new(), }); + } else { + let root = src.join(name).join("src/lib.rs"); + if root.exists() { + sysroot.crates.alloc(SysrootCrateData { + name: name.into(), + root, + deps: Vec::new(), + }); + } } } if let Some(std) = sysroot.std() { @@ -94,23 +105,38 @@ fn get_or_install_rust_src(cargo_toml: &AbsPath) -> Result { rustc.current_dir(current_dir).args(&["--print", "sysroot"]); let stdout = utf8_stdout(rustc)?; let sysroot_path = AbsPath::assert(Path::new(stdout.trim())); - let src_path = sysroot_path.join("lib/rustlib/src/rust/src"); - - if !src_path.exists() { + let mut src = get_rust_src(sysroot_path); + if src.is_none() { let mut rustup = Command::new(ra_toolchain::rustup()); rustup.current_dir(current_dir).args(&["component", "add", "rust-src"]); utf8_stdout(rustup)?; + src = get_rust_src(sysroot_path); } - if !src_path.exists() { - bail!( + match src { + Some(r) => Ok(r), + None => bail!( "can't load standard library from sysroot\n\ {}\n\ (discovered via `rustc --print sysroot`)\n\ try running `rustup component add rust-src` or set `RUST_SRC_PATH`", - src_path.display(), - ) + sysroot_path.display(), + ), + } +} + +fn get_rust_src(sysroot_path: &AbsPath) -> Option { + // try the new path first since the old one still exists + let mut src_path = sysroot_path.join("lib/rustlib/src/rust/library"); + if !src_path.exists() { + // FIXME: remove this path when 1.47 comes out + // https://github.com/rust-lang/rust/pull/73265 + src_path = sysroot_path.join("lib/rustlib/src/rust/src"); + } + if src_path.exists() { + Some(src_path) + } else { + None } - Ok(src_path) } impl SysrootCrateData { -- cgit v1.2.3 From afd02461bcb9bccd9372352dc9115209753fee4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Thu, 30 Jul 2020 17:17:59 +0300 Subject: Update sysroot crates --- crates/ra_project_model/src/sysroot.rs | 48 ++++++++++++---------------------- 1 file changed, 17 insertions(+), 31 deletions(-) (limited to 'crates/ra_project_model/src') diff --git a/crates/ra_project_model/src/sysroot.rs b/crates/ra_project_model/src/sysroot.rs index 9e23b5805..a10ade375 100644 --- a/crates/ra_project_model/src/sysroot.rs +++ b/crates/ra_project_model/src/sysroot.rs @@ -146,42 +146,28 @@ impl SysrootCrateData { } const SYSROOT_CRATES: &str = " -std -core alloc -collections -libc -proc_macro -rustc_unicode -std_unicode -test -alloc_jemalloc -alloc_system -compiler_builtins -getopts -panic_unwind +core panic_abort -rand +panic_unwind +proc_macro +profiler_builtins +rtstartup +std +stdarch term -unwind -build_helper -rustc_asan -rustc_lsan -rustc_msan -rustc_tsan -syntax"; +test +unwind"; const STD_DEPS: &str = " alloc -alloc_jemalloc -alloc_system core panic_abort -rand -compiler_builtins -unwind -rustc_asan -rustc_lsan -rustc_msan -rustc_tsan -build_helper"; +panic_unwind +profiler_builtins +rtstartup +proc_macro +stdarch +term +test +unwind"; -- cgit v1.2.3 From 2e562c158fd43d105c0c3f035aafe24c0e648b1e Mon Sep 17 00:00:00 2001 From: Clemens Wasser Date: Thu, 30 Jul 2020 16:23:07 +0200 Subject: ra_project_model: Fix configuration of features This commit fixes the handling of user-defined configuration of some cargo options. Previously you could either specify `--all-features`, `--no-default-features` or `--features`. Now you can specify either `--all-features` or `--no-default-features` and `--features`. This commit also corrects the `--features` command-line argument creation inside of `load_extern_resources`. --- crates/ra_project_model/src/cargo_workspace.rs | 29 ++++++++++++++++---------- 1 file changed, 18 insertions(+), 11 deletions(-) (limited to 'crates/ra_project_model/src') diff --git a/crates/ra_project_model/src/cargo_workspace.rs b/crates/ra_project_model/src/cargo_workspace.rs index fb88e0f06..10513542e 100644 --- a/crates/ra_project_model/src/cargo_workspace.rs +++ b/crates/ra_project_model/src/cargo_workspace.rs @@ -144,12 +144,15 @@ impl CargoWorkspace { meta.manifest_path(cargo_toml.to_path_buf()); if cargo_features.all_features { meta.features(CargoOpt::AllFeatures); - } else if cargo_features.no_default_features { - // FIXME: `NoDefaultFeatures` is mutual exclusive with `SomeFeatures` - // https://github.com/oli-obk/cargo_metadata/issues/79 - meta.features(CargoOpt::NoDefaultFeatures); - } else if !cargo_features.features.is_empty() { - meta.features(CargoOpt::SomeFeatures(cargo_features.features.clone())); + } else { + if cargo_features.no_default_features { + // FIXME: `NoDefaultFeatures` is mutual exclusive with `SomeFeatures` + // https://github.com/oli-obk/cargo_metadata/issues/79 + meta.features(CargoOpt::NoDefaultFeatures); + } + if !cargo_features.features.is_empty() { + meta.features(CargoOpt::SomeFeatures(cargo_features.features.clone())); + } } if let Some(parent) = cargo_toml.parent() { meta.current_dir(parent.to_path_buf()); @@ -289,12 +292,16 @@ pub fn load_extern_resources( cmd.args(&["check", "--message-format=json", "--manifest-path"]).arg(cargo_toml); if cargo_features.all_features { cmd.arg("--all-features"); - } else if cargo_features.no_default_features { - // FIXME: `NoDefaultFeatures` is mutual exclusive with `SomeFeatures` - // https://github.com/oli-obk/cargo_metadata/issues/79 - cmd.arg("--no-default-features"); } else { - cmd.args(&cargo_features.features); + if cargo_features.no_default_features { + // FIXME: `NoDefaultFeatures` is mutual exclusive with `SomeFeatures` + // https://github.com/oli-obk/cargo_metadata/issues/79 + cmd.arg("--no-default-features"); + } + if !cargo_features.features.is_empty() { + cmd.arg("--features"); + cmd.arg(cargo_features.features.join(" ")); + } } let output = cmd.output()?; -- cgit v1.2.3 From be49547b446cba240f8f2a9592284e77d4a6896f Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 30 Jul 2020 22:19:58 +0200 Subject: Use split_once polyfill --- crates/ra_project_model/src/cfg_flag.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'crates/ra_project_model/src') diff --git a/crates/ra_project_model/src/cfg_flag.rs b/crates/ra_project_model/src/cfg_flag.rs index 1bc5d4832..bd50056c6 100644 --- a/crates/ra_project_model/src/cfg_flag.rs +++ b/crates/ra_project_model/src/cfg_flag.rs @@ -4,7 +4,7 @@ use std::str::FromStr; use ra_cfg::CfgOptions; -use stdx::split_delim; +use stdx::split_once; #[derive(Clone, Eq, PartialEq, Debug)] pub enum CfgFlag { @@ -15,7 +15,7 @@ pub enum CfgFlag { impl FromStr for CfgFlag { type Err = String; fn from_str(s: &str) -> Result { - let res = match split_delim(s, '=') { + let res = match split_once(s, '=') { Some((key, value)) => { if !(value.starts_with('"') && value.ends_with('"')) { return Err(format!("Invalid cfg ({:?}), value should be in quotes", s)); -- cgit v1.2.3