diff options
Diffstat (limited to 'crates/ra_project_model/src/lib.rs')
-rw-r--r-- | crates/ra_project_model/src/lib.rs | 60 |
1 files changed, 44 insertions, 16 deletions
diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs index a2e9f65ef..7ad941279 100644 --- a/crates/ra_project_model/src/lib.rs +++ b/crates/ra_project_model/src/lib.rs | |||
@@ -14,7 +14,7 @@ use std::{ | |||
14 | use anyhow::{bail, Context, Result}; | 14 | use anyhow::{bail, Context, Result}; |
15 | use ra_cfg::CfgOptions; | 15 | use ra_cfg::CfgOptions; |
16 | use ra_db::{CrateGraph, CrateName, Edition, Env, ExternSource, ExternSourceId, FileId}; | 16 | use ra_db::{CrateGraph, CrateName, Edition, Env, ExternSource, ExternSourceId, FileId}; |
17 | use rustc_hash::FxHashMap; | 17 | use rustc_hash::{FxHashMap, FxHashSet}; |
18 | use serde_json::from_reader; | 18 | use serde_json::from_reader; |
19 | 19 | ||
20 | pub use crate::{ | 20 | pub use crate::{ |
@@ -32,6 +32,12 @@ pub enum ProjectWorkspace { | |||
32 | Json { project: JsonProject }, | 32 | Json { project: JsonProject }, |
33 | } | 33 | } |
34 | 34 | ||
35 | impl From<JsonProject> for ProjectWorkspace { | ||
36 | fn from(project: JsonProject) -> ProjectWorkspace { | ||
37 | ProjectWorkspace::Json { project } | ||
38 | } | ||
39 | } | ||
40 | |||
35 | /// `PackageRoot` describes a package root folder. | 41 | /// `PackageRoot` describes a package root folder. |
36 | /// Which may be an external dependency, or a member of | 42 | /// Which may be an external dependency, or a member of |
37 | /// the current workspace. | 43 | /// the current workspace. |
@@ -57,25 +63,25 @@ impl PackageRoot { | |||
57 | } | 63 | } |
58 | } | 64 | } |
59 | 65 | ||
60 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 66 | #[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)] |
61 | pub enum ProjectRoot { | 67 | pub enum ProjectManifest { |
62 | ProjectJson(PathBuf), | 68 | ProjectJson(PathBuf), |
63 | CargoToml(PathBuf), | 69 | CargoToml(PathBuf), |
64 | } | 70 | } |
65 | 71 | ||
66 | impl ProjectRoot { | 72 | impl ProjectManifest { |
67 | pub fn from_manifest_file(path: PathBuf) -> Result<ProjectRoot> { | 73 | pub fn from_manifest_file(path: PathBuf) -> Result<ProjectManifest> { |
68 | if path.ends_with("rust-project.json") { | 74 | if path.ends_with("rust-project.json") { |
69 | return Ok(ProjectRoot::ProjectJson(path)); | 75 | return Ok(ProjectManifest::ProjectJson(path)); |
70 | } | 76 | } |
71 | if path.ends_with("Cargo.toml") { | 77 | if path.ends_with("Cargo.toml") { |
72 | return Ok(ProjectRoot::CargoToml(path)); | 78 | return Ok(ProjectManifest::CargoToml(path)); |
73 | } | 79 | } |
74 | bail!("project root must point to Cargo.toml or rust-project.json: {}", path.display()) | 80 | bail!("project root must point to Cargo.toml or rust-project.json: {}", path.display()) |
75 | } | 81 | } |
76 | 82 | ||
77 | pub fn discover_single(path: &Path) -> Result<ProjectRoot> { | 83 | pub fn discover_single(path: &Path) -> Result<ProjectManifest> { |
78 | let mut candidates = ProjectRoot::discover(path)?; | 84 | let mut candidates = ProjectManifest::discover(path)?; |
79 | let res = match candidates.pop() { | 85 | let res = match candidates.pop() { |
80 | None => bail!("no projects"), | 86 | None => bail!("no projects"), |
81 | Some(it) => it, | 87 | Some(it) => it, |
@@ -87,12 +93,12 @@ impl ProjectRoot { | |||
87 | Ok(res) | 93 | Ok(res) |
88 | } | 94 | } |
89 | 95 | ||
90 | pub fn discover(path: &Path) -> io::Result<Vec<ProjectRoot>> { | 96 | pub fn discover(path: &Path) -> io::Result<Vec<ProjectManifest>> { |
91 | if let Some(project_json) = find_in_parent_dirs(path, "rust-project.json") { | 97 | if let Some(project_json) = find_in_parent_dirs(path, "rust-project.json") { |
92 | return Ok(vec![ProjectRoot::ProjectJson(project_json)]); | 98 | return Ok(vec![ProjectManifest::ProjectJson(project_json)]); |
93 | } | 99 | } |
94 | return find_cargo_toml(path) | 100 | return find_cargo_toml(path) |
95 | .map(|paths| paths.into_iter().map(ProjectRoot::CargoToml).collect()); | 101 | .map(|paths| paths.into_iter().map(ProjectManifest::CargoToml).collect()); |
96 | 102 | ||
97 | fn find_cargo_toml(path: &Path) -> io::Result<Vec<PathBuf>> { | 103 | fn find_cargo_toml(path: &Path) -> io::Result<Vec<PathBuf>> { |
98 | match find_in_parent_dirs(path, "Cargo.toml") { | 104 | match find_in_parent_dirs(path, "Cargo.toml") { |
@@ -128,16 +134,28 @@ impl ProjectRoot { | |||
128 | .collect() | 134 | .collect() |
129 | } | 135 | } |
130 | } | 136 | } |
137 | |||
138 | pub fn discover_all(paths: &[impl AsRef<Path>]) -> Vec<ProjectManifest> { | ||
139 | let mut res = paths | ||
140 | .iter() | ||
141 | .filter_map(|it| ProjectManifest::discover(it.as_ref()).ok()) | ||
142 | .flatten() | ||
143 | .collect::<FxHashSet<_>>() | ||
144 | .into_iter() | ||
145 | .collect::<Vec<_>>(); | ||
146 | res.sort(); | ||
147 | res | ||
148 | } | ||
131 | } | 149 | } |
132 | 150 | ||
133 | impl ProjectWorkspace { | 151 | impl ProjectWorkspace { |
134 | pub fn load( | 152 | pub fn load( |
135 | root: ProjectRoot, | 153 | manifest: ProjectManifest, |
136 | cargo_features: &CargoConfig, | 154 | cargo_features: &CargoConfig, |
137 | with_sysroot: bool, | 155 | with_sysroot: bool, |
138 | ) -> Result<ProjectWorkspace> { | 156 | ) -> Result<ProjectWorkspace> { |
139 | let res = match root { | 157 | let res = match manifest { |
140 | ProjectRoot::ProjectJson(project_json) => { | 158 | ProjectManifest::ProjectJson(project_json) => { |
141 | let file = File::open(&project_json).with_context(|| { | 159 | let file = File::open(&project_json).with_context(|| { |
142 | format!("Failed to open json file {}", project_json.display()) | 160 | format!("Failed to open json file {}", project_json.display()) |
143 | })?; | 161 | })?; |
@@ -148,7 +166,7 @@ impl ProjectWorkspace { | |||
148 | })?, | 166 | })?, |
149 | } | 167 | } |
150 | } | 168 | } |
151 | ProjectRoot::CargoToml(cargo_toml) => { | 169 | ProjectManifest::CargoToml(cargo_toml) => { |
152 | let cargo = CargoWorkspace::from_cargo_metadata(&cargo_toml, cargo_features) | 170 | let cargo = CargoWorkspace::from_cargo_metadata(&cargo_toml, cargo_features) |
153 | .with_context(|| { | 171 | .with_context(|| { |
154 | format!( | 172 | format!( |
@@ -252,6 +270,16 @@ impl ProjectWorkspace { | |||
252 | }; | 270 | }; |
253 | let cfg_options = { | 271 | let cfg_options = { |
254 | let mut opts = default_cfg_options.clone(); | 272 | let mut opts = default_cfg_options.clone(); |
273 | for cfg in &krate.cfg { | ||
274 | match cfg.find('=') { | ||
275 | None => opts.insert_atom(cfg.into()), | ||
276 | Some(pos) => { | ||
277 | let key = &cfg[..pos]; | ||
278 | let value = cfg[pos + 1..].trim_matches('"'); | ||
279 | opts.insert_key_value(key.into(), value.into()); | ||
280 | } | ||
281 | } | ||
282 | } | ||
255 | for name in &krate.atom_cfgs { | 283 | for name in &krate.atom_cfgs { |
256 | opts.insert_atom(name.into()); | 284 | opts.insert_atom(name.into()); |
257 | } | 285 | } |