diff options
author | Aleksey Kladov <[email protected]> | 2020-08-25 17:34:00 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2020-08-25 18:41:56 +0100 |
commit | 189521a4db6e51e954f118367e07bb1cc6d2f40d (patch) | |
tree | 9ca14279d566ffa30e779a3178760d17962b624e | |
parent | 91bedefe491af3bf4eeb13bc7716cc419cafe067 (diff) |
Add sysroot shortcut to rust-project.json
-rw-r--r-- | crates/project_model/src/lib.rs | 65 | ||||
-rw-r--r-- | crates/project_model/src/project_json.rs | 11 | ||||
-rw-r--r-- | docs/user/manual.adoc | 16 |
3 files changed, 70 insertions, 22 deletions
diff --git a/crates/project_model/src/lib.rs b/crates/project_model/src/lib.rs index 724c586db..2d91939ce 100644 --- a/crates/project_model/src/lib.rs +++ b/crates/project_model/src/lib.rs | |||
@@ -39,11 +39,18 @@ pub enum ProjectWorkspace { | |||
39 | impl fmt::Debug for ProjectWorkspace { | 39 | impl fmt::Debug for ProjectWorkspace { |
40 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | 40 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
41 | match self { | 41 | match self { |
42 | ProjectWorkspace::Cargo { cargo, .. } => { | 42 | ProjectWorkspace::Cargo { cargo, sysroot } => f |
43 | f.debug_struct("Cargo").field("n_packages", &cargo.packages().len()).finish() | 43 | .debug_struct("Cargo") |
44 | } | 44 | .field("n_packages", &cargo.packages().len()) |
45 | .field("n_sysroot_crates", &sysroot.crates().len()) | ||
46 | .finish(), | ||
45 | ProjectWorkspace::Json { project } => { | 47 | ProjectWorkspace::Json { project } => { |
46 | f.debug_struct("Json").field("n_crates", &project.n_crates()).finish() | 48 | let mut debug_struct = f.debug_struct("Json"); |
49 | debug_struct.field("n_crates", &project.n_crates()); | ||
50 | if let Some(sysroot) = &project.sysroot { | ||
51 | debug_struct.field("n_sysroot_crates", &sysroot.crates().len()); | ||
52 | } | ||
53 | debug_struct.finish() | ||
47 | } | 54 | } |
48 | } | 55 | } |
49 | } | 56 | } |
@@ -210,6 +217,13 @@ impl ProjectWorkspace { | |||
210 | }) | 217 | }) |
211 | .collect::<FxHashSet<_>>() | 218 | .collect::<FxHashSet<_>>() |
212 | .into_iter() | 219 | .into_iter() |
220 | .chain(project.sysroot.as_ref().into_iter().flat_map(|sysroot| { | ||
221 | sysroot.crates().map(move |krate| PackageRoot { | ||
222 | is_member: false, | ||
223 | include: vec![sysroot[krate].root_dir().to_path_buf()], | ||
224 | exclude: Vec::new(), | ||
225 | }) | ||
226 | })) | ||
213 | .collect::<Vec<_>>(), | 227 | .collect::<Vec<_>>(), |
214 | ProjectWorkspace::Cargo { cargo, sysroot } => cargo | 228 | ProjectWorkspace::Cargo { cargo, sysroot } => cargo |
215 | .packages() | 229 | .packages() |
@@ -272,6 +286,11 @@ impl ProjectWorkspace { | |||
272 | let mut crate_graph = CrateGraph::default(); | 286 | let mut crate_graph = CrateGraph::default(); |
273 | match self { | 287 | match self { |
274 | ProjectWorkspace::Json { project } => { | 288 | ProjectWorkspace::Json { project } => { |
289 | let sysroot_dps = project | ||
290 | .sysroot | ||
291 | .as_ref() | ||
292 | .map(|sysroot| sysroot_to_crate_graph(&mut crate_graph, sysroot, target, load)); | ||
293 | |||
275 | let mut cfg_cache: FxHashMap<Option<&str>, Vec<CfgFlag>> = FxHashMap::default(); | 294 | let mut cfg_cache: FxHashMap<Option<&str>, Vec<CfgFlag>> = FxHashMap::default(); |
276 | let crates: FxHashMap<_, _> = project | 295 | let crates: FxHashMap<_, _> = project |
277 | .crates() | 296 | .crates() |
@@ -309,25 +328,33 @@ impl ProjectWorkspace { | |||
309 | .collect(); | 328 | .collect(); |
310 | 329 | ||
311 | for (from, krate) in project.crates() { | 330 | for (from, krate) in project.crates() { |
312 | for dep in &krate.deps { | 331 | if let Some(&from) = crates.get(&from) { |
313 | let to_crate_id = dep.crate_id; | 332 | if let Some((public_deps, _proc_macro)) = &sysroot_dps { |
314 | if let (Some(&from), Some(&to)) = | 333 | for (name, to) in public_deps.iter() { |
315 | (crates.get(&from), crates.get(&to_crate_id)) | 334 | if let Err(_) = crate_graph.add_dep(from, name.clone(), *to) { |
316 | { | 335 | log::error!("cyclic dependency on {} for {:?}", name, from) |
317 | if let Err(_) = crate_graph.add_dep(from, dep.name.clone(), to) { | 336 | } |
318 | log::error!("cyclic dependency {:?} -> {:?}", from, to_crate_id); | 337 | } |
338 | } | ||
339 | |||
340 | for dep in &krate.deps { | ||
341 | let to_crate_id = dep.crate_id; | ||
342 | if let Some(&to) = crates.get(&to_crate_id) { | ||
343 | if let Err(_) = crate_graph.add_dep(from, dep.name.clone(), to) { | ||
344 | log::error!("cyclic dependency {:?} -> {:?}", from, to); | ||
345 | } | ||
319 | } | 346 | } |
320 | } | 347 | } |
321 | } | 348 | } |
322 | } | 349 | } |
323 | } | 350 | } |
324 | ProjectWorkspace::Cargo { cargo, sysroot } => { | 351 | ProjectWorkspace::Cargo { cargo, sysroot } => { |
352 | let (public_deps, libproc_macro) = | ||
353 | sysroot_to_crate_graph(&mut crate_graph, sysroot, target, load); | ||
354 | |||
325 | let mut cfg_options = CfgOptions::default(); | 355 | let mut cfg_options = CfgOptions::default(); |
326 | cfg_options.extend(get_rustc_cfg_options(target)); | 356 | cfg_options.extend(get_rustc_cfg_options(target)); |
327 | 357 | ||
328 | let (public_deps, libproc_macro) = | ||
329 | sysroot_to_crate_graph(&mut crate_graph, sysroot, &cfg_options, load); | ||
330 | |||
331 | let mut pkg_to_lib_crate = FxHashMap::default(); | 358 | let mut pkg_to_lib_crate = FxHashMap::default(); |
332 | let mut pkg_crates = FxHashMap::default(); | 359 | let mut pkg_crates = FxHashMap::default(); |
333 | 360 | ||
@@ -410,7 +437,11 @@ impl ProjectWorkspace { | |||
410 | } | 437 | } |
411 | for (name, krate) in public_deps.iter() { | 438 | for (name, krate) in public_deps.iter() { |
412 | if let Err(_) = crate_graph.add_dep(from, name.clone(), *krate) { | 439 | if let Err(_) = crate_graph.add_dep(from, name.clone(), *krate) { |
413 | log::error!("cyclic dependency on core for {}", &cargo[pkg].name) | 440 | log::error!( |
441 | "cyclic dependency on {} for {}", | ||
442 | name, | ||
443 | &cargo[pkg].name | ||
444 | ) | ||
414 | } | 445 | } |
415 | } | 446 | } |
416 | } | 447 | } |
@@ -485,9 +516,11 @@ fn utf8_stdout(mut cmd: Command) -> Result<String> { | |||
485 | fn sysroot_to_crate_graph( | 516 | fn sysroot_to_crate_graph( |
486 | crate_graph: &mut CrateGraph, | 517 | crate_graph: &mut CrateGraph, |
487 | sysroot: &Sysroot, | 518 | sysroot: &Sysroot, |
488 | cfg_options: &CfgOptions, | 519 | target: Option<&str>, |
489 | load: &mut dyn FnMut(&AbsPath) -> Option<FileId>, | 520 | load: &mut dyn FnMut(&AbsPath) -> Option<FileId>, |
490 | ) -> (Vec<(CrateName, CrateId)>, Option<CrateId>) { | 521 | ) -> (Vec<(CrateName, CrateId)>, Option<CrateId>) { |
522 | let mut cfg_options = CfgOptions::default(); | ||
523 | cfg_options.extend(get_rustc_cfg_options(target)); | ||
491 | let sysroot_crates: FxHashMap<_, _> = sysroot | 524 | let sysroot_crates: FxHashMap<_, _> = sysroot |
492 | .crates() | 525 | .crates() |
493 | .filter_map(|krate| { | 526 | .filter_map(|krate| { |
diff --git a/crates/project_model/src/project_json.rs b/crates/project_model/src/project_json.rs index ae14e5126..5a0fe749a 100644 --- a/crates/project_model/src/project_json.rs +++ b/crates/project_model/src/project_json.rs | |||
@@ -7,11 +7,12 @@ use paths::{AbsPath, AbsPathBuf}; | |||
7 | use rustc_hash::FxHashMap; | 7 | use rustc_hash::FxHashMap; |
8 | use serde::{de, Deserialize}; | 8 | use serde::{de, Deserialize}; |
9 | 9 | ||
10 | use crate::cfg_flag::CfgFlag; | 10 | use crate::{cfg_flag::CfgFlag, Sysroot}; |
11 | 11 | ||
12 | /// Roots and crates that compose this Rust project. | 12 | /// Roots and crates that compose this Rust project. |
13 | #[derive(Clone, Debug, Eq, PartialEq)] | 13 | #[derive(Clone, Debug, Eq, PartialEq)] |
14 | pub struct ProjectJson { | 14 | pub struct ProjectJson { |
15 | pub(crate) sysroot: Option<Sysroot>, | ||
15 | crates: Vec<Crate>, | 16 | crates: Vec<Crate>, |
16 | } | 17 | } |
17 | 18 | ||
@@ -34,6 +35,7 @@ pub struct Crate { | |||
34 | impl ProjectJson { | 35 | impl ProjectJson { |
35 | pub fn new(base: &AbsPath, data: ProjectJsonData) -> ProjectJson { | 36 | pub fn new(base: &AbsPath, data: ProjectJsonData) -> ProjectJson { |
36 | ProjectJson { | 37 | ProjectJson { |
38 | sysroot: data.sysroot_src.map(|it| base.join(it)).map(|it| Sysroot::load(&it)), | ||
37 | crates: data | 39 | crates: data |
38 | .crates | 40 | .crates |
39 | .into_iter() | 41 | .into_iter() |
@@ -43,11 +45,13 @@ impl ProjectJson { | |||
43 | && !crate_data.root_module.starts_with("..") | 45 | && !crate_data.root_module.starts_with("..") |
44 | || crate_data.root_module.starts_with(base) | 46 | || crate_data.root_module.starts_with(base) |
45 | }); | 47 | }); |
46 | let root_module = base.join(crate_data.root_module); | 48 | let root_module = base.join(crate_data.root_module).normalize(); |
47 | let (include, exclude) = match crate_data.source { | 49 | let (include, exclude) = match crate_data.source { |
48 | Some(src) => { | 50 | Some(src) => { |
49 | let absolutize = |dirs: Vec<PathBuf>| { | 51 | let absolutize = |dirs: Vec<PathBuf>| { |
50 | dirs.into_iter().map(|it| base.join(it)).collect::<Vec<_>>() | 52 | dirs.into_iter() |
53 | .map(|it| base.join(it).normalize()) | ||
54 | .collect::<Vec<_>>() | ||
51 | }; | 55 | }; |
52 | (absolutize(src.include_dirs), absolutize(src.exclude_dirs)) | 56 | (absolutize(src.include_dirs), absolutize(src.exclude_dirs)) |
53 | } | 57 | } |
@@ -89,6 +93,7 @@ impl ProjectJson { | |||
89 | 93 | ||
90 | #[derive(Deserialize)] | 94 | #[derive(Deserialize)] |
91 | pub struct ProjectJsonData { | 95 | pub struct ProjectJsonData { |
96 | sysroot_src: Option<PathBuf>, | ||
92 | crates: Vec<CrateData>, | 97 | crates: Vec<CrateData>, |
93 | } | 98 | } |
94 | 99 | ||
diff --git a/docs/user/manual.adoc b/docs/user/manual.adoc index bebcee023..144130b51 100644 --- a/docs/user/manual.adoc +++ b/docs/user/manual.adoc | |||
@@ -273,9 +273,19 @@ However, if you use some other build system, you'll have to describe the structu | |||
273 | [source,TypeScript] | 273 | [source,TypeScript] |
274 | ---- | 274 | ---- |
275 | interface JsonProject { | 275 | interface JsonProject { |
276 | /// The set of crates comprising the current project. | 276 | /// Path to the directory with *source code* of sysroot crates. |
277 | /// Must include all transitive dependencies as well as sysroot crate (libstd, libcore and such). | 277 | /// |
278 | crates: Crate[]; | 278 | /// It should point to the directory where std, core, and friends can be found: |
279 | /// https://github.com/rust-lang/rust/tree/master/library. | ||
280 | /// | ||
281 | /// If provided, rust-analyzer automatically adds dependencies on sysroot | ||
282 | /// crates. Conversely, if you omit this path, you can specify sysroot | ||
283 | /// dependencies yourself and, for example, have several different "sysroots" in | ||
284 | /// one graph of crates. | ||
285 | sysroot_src?: string; | ||
286 | /// The set of crates comprising the current project. | ||
287 | /// Must include all transitive dependencies as well as sysroot crate (libstd, libcore and such). | ||
288 | crates: Crate[]; | ||
279 | } | 289 | } |
280 | 290 | ||
281 | interface Crate { | 291 | interface Crate { |