diff options
Diffstat (limited to 'crates/project_model/src')
-rw-r--r-- | crates/project_model/src/cargo_workspace.rs | 48 | ||||
-rw-r--r-- | crates/project_model/src/lib.rs | 7 | ||||
-rw-r--r-- | crates/project_model/src/project_json.rs | 10 | ||||
-rw-r--r-- | crates/project_model/src/workspace.rs | 22 |
4 files changed, 66 insertions, 21 deletions
diff --git a/crates/project_model/src/cargo_workspace.rs b/crates/project_model/src/cargo_workspace.rs index 1700cb8a7..2ee4e88b2 100644 --- a/crates/project_model/src/cargo_workspace.rs +++ b/crates/project_model/src/cargo_workspace.rs | |||
@@ -3,9 +3,10 @@ | |||
3 | use std::{ | 3 | use std::{ |
4 | convert::TryInto, | 4 | convert::TryInto, |
5 | ffi::OsStr, | 5 | ffi::OsStr, |
6 | io::BufReader, | ||
6 | ops, | 7 | ops, |
7 | path::{Path, PathBuf}, | 8 | path::{Path, PathBuf}, |
8 | process::Command, | 9 | process::{Command, Stdio}, |
9 | }; | 10 | }; |
10 | 11 | ||
11 | use anyhow::{Context, Result}; | 12 | use anyhow::{Context, Result}; |
@@ -15,6 +16,7 @@ use cargo_metadata::{BuildScript, CargoOpt, Message, MetadataCommand, PackageId} | |||
15 | use itertools::Itertools; | 16 | use itertools::Itertools; |
16 | use paths::{AbsPath, AbsPathBuf}; | 17 | use paths::{AbsPath, AbsPathBuf}; |
17 | use rustc_hash::FxHashMap; | 18 | use rustc_hash::FxHashMap; |
19 | use stdx::JodChild; | ||
18 | 20 | ||
19 | use crate::cfg_flag::CfgFlag; | 21 | use crate::cfg_flag::CfgFlag; |
20 | use crate::utf8_stdout; | 22 | use crate::utf8_stdout; |
@@ -80,19 +82,35 @@ pub type Package = Idx<PackageData>; | |||
80 | 82 | ||
81 | pub type Target = Idx<TargetData>; | 83 | pub type Target = Idx<TargetData>; |
82 | 84 | ||
85 | /// Information associated with a cargo crate | ||
83 | #[derive(Debug, Clone, Eq, PartialEq)] | 86 | #[derive(Debug, Clone, Eq, PartialEq)] |
84 | pub struct PackageData { | 87 | pub struct PackageData { |
88 | /// Version given in the `Cargo.toml` | ||
85 | pub version: String, | 89 | pub version: String, |
90 | /// Name as given in the `Cargo.toml` | ||
86 | pub name: String, | 91 | pub name: String, |
92 | /// Path containing the `Cargo.toml` | ||
87 | pub manifest: AbsPathBuf, | 93 | pub manifest: AbsPathBuf, |
94 | /// Targets provided by the crate (lib, bin, example, test, ...) | ||
88 | pub targets: Vec<Target>, | 95 | pub targets: Vec<Target>, |
96 | /// Is this package a member of the current workspace | ||
89 | pub is_member: bool, | 97 | pub is_member: bool, |
98 | /// List of packages this package depends on | ||
90 | pub dependencies: Vec<PackageDependency>, | 99 | pub dependencies: Vec<PackageDependency>, |
100 | /// Rust edition for this package | ||
91 | pub edition: Edition, | 101 | pub edition: Edition, |
102 | /// List of features to activate | ||
92 | pub features: Vec<String>, | 103 | pub features: Vec<String>, |
104 | /// List of config flags defined by this package's build script | ||
93 | pub cfgs: Vec<CfgFlag>, | 105 | pub cfgs: Vec<CfgFlag>, |
106 | /// List of cargo-related environment variables with their value | ||
107 | /// | ||
108 | /// If the package has a build script which defines environment variables, | ||
109 | /// they can also be found here. | ||
94 | pub envs: Vec<(String, String)>, | 110 | pub envs: Vec<(String, String)>, |
111 | /// Directory where a build script might place its output | ||
95 | pub out_dir: Option<AbsPathBuf>, | 112 | pub out_dir: Option<AbsPathBuf>, |
113 | /// Path to the proc-macro library file if this package exposes proc-macros | ||
96 | pub proc_macro_dylib_path: Option<AbsPathBuf>, | 114 | pub proc_macro_dylib_path: Option<AbsPathBuf>, |
97 | } | 115 | } |
98 | 116 | ||
@@ -102,12 +120,18 @@ pub struct PackageDependency { | |||
102 | pub name: String, | 120 | pub name: String, |
103 | } | 121 | } |
104 | 122 | ||
123 | /// Information associated with a package's target | ||
105 | #[derive(Debug, Clone, Eq, PartialEq)] | 124 | #[derive(Debug, Clone, Eq, PartialEq)] |
106 | pub struct TargetData { | 125 | pub struct TargetData { |
126 | /// Package that provided this target | ||
107 | pub package: Package, | 127 | pub package: Package, |
128 | /// Name as given in the `Cargo.toml` or generated from the file name | ||
108 | pub name: String, | 129 | pub name: String, |
130 | /// Path to the main source file of the target | ||
109 | pub root: AbsPathBuf, | 131 | pub root: AbsPathBuf, |
132 | /// Kind of target | ||
110 | pub kind: TargetKind, | 133 | pub kind: TargetKind, |
134 | /// Is this target a proc-macro | ||
111 | pub is_proc_macro: bool, | 135 | pub is_proc_macro: bool, |
112 | } | 136 | } |
113 | 137 | ||
@@ -149,6 +173,7 @@ impl CargoWorkspace { | |||
149 | pub fn from_cargo_metadata( | 173 | pub fn from_cargo_metadata( |
150 | cargo_toml: &AbsPath, | 174 | cargo_toml: &AbsPath, |
151 | config: &CargoConfig, | 175 | config: &CargoConfig, |
176 | progress: &dyn Fn(String), | ||
152 | ) -> Result<CargoWorkspace> { | 177 | ) -> Result<CargoWorkspace> { |
153 | let mut meta = MetadataCommand::new(); | 178 | let mut meta = MetadataCommand::new(); |
154 | meta.cargo_path(toolchain::cargo()); | 179 | meta.cargo_path(toolchain::cargo()); |
@@ -198,6 +223,9 @@ impl CargoWorkspace { | |||
198 | meta.other_options(vec![String::from("--filter-platform"), target]); | 223 | meta.other_options(vec![String::from("--filter-platform"), target]); |
199 | } | 224 | } |
200 | 225 | ||
226 | // FIXME: Currently MetadataCommand is not based on parse_stream, | ||
227 | // So we just report it as a whole | ||
228 | progress("metadata".to_string()); | ||
201 | let mut meta = meta.exec().with_context(|| { | 229 | let mut meta = meta.exec().with_context(|| { |
202 | let cwd: Option<AbsPathBuf> = | 230 | let cwd: Option<AbsPathBuf> = |
203 | std::env::current_dir().ok().and_then(|p| p.try_into().ok()); | 231 | std::env::current_dir().ok().and_then(|p| p.try_into().ok()); |
@@ -221,7 +249,7 @@ impl CargoWorkspace { | |||
221 | let mut envs = FxHashMap::default(); | 249 | let mut envs = FxHashMap::default(); |
222 | let mut proc_macro_dylib_paths = FxHashMap::default(); | 250 | let mut proc_macro_dylib_paths = FxHashMap::default(); |
223 | if config.load_out_dirs_from_check { | 251 | if config.load_out_dirs_from_check { |
224 | let resources = load_extern_resources(cargo_toml, config)?; | 252 | let resources = load_extern_resources(cargo_toml, config, progress)?; |
225 | out_dir_by_id = resources.out_dirs; | 253 | out_dir_by_id = resources.out_dirs; |
226 | cfgs = resources.cfgs; | 254 | cfgs = resources.cfgs; |
227 | envs = resources.env; | 255 | envs = resources.env; |
@@ -346,6 +374,7 @@ pub(crate) struct ExternResources { | |||
346 | pub(crate) fn load_extern_resources( | 374 | pub(crate) fn load_extern_resources( |
347 | cargo_toml: &Path, | 375 | cargo_toml: &Path, |
348 | cargo_features: &CargoConfig, | 376 | cargo_features: &CargoConfig, |
377 | progress: &dyn Fn(String), | ||
349 | ) -> Result<ExternResources> { | 378 | ) -> Result<ExternResources> { |
350 | let mut cmd = Command::new(toolchain::cargo()); | 379 | let mut cmd = Command::new(toolchain::cargo()); |
351 | cmd.args(&["check", "--message-format=json", "--manifest-path"]).arg(cargo_toml); | 380 | cmd.args(&["check", "--message-format=json", "--manifest-path"]).arg(cargo_toml); |
@@ -373,11 +402,14 @@ pub(crate) fn load_extern_resources( | |||
373 | } | 402 | } |
374 | } | 403 | } |
375 | 404 | ||
376 | let output = cmd.output()?; | 405 | cmd.stdout(Stdio::piped()).stderr(Stdio::null()).stdin(Stdio::null()); |
377 | 406 | ||
378 | let mut res = ExternResources::default(); | 407 | let mut child = cmd.spawn().map(JodChild)?; |
408 | let child_stdout = child.stdout.take().unwrap(); | ||
409 | let stdout = BufReader::new(child_stdout); | ||
379 | 410 | ||
380 | for message in cargo_metadata::Message::parse_stream(output.stdout.as_slice()) { | 411 | let mut res = ExternResources::default(); |
412 | for message in cargo_metadata::Message::parse_stream(stdout) { | ||
381 | if let Ok(message) = message { | 413 | if let Ok(message) = message { |
382 | match message { | 414 | match message { |
383 | Message::BuildScriptExecuted(BuildScript { | 415 | Message::BuildScriptExecuted(BuildScript { |
@@ -410,6 +442,8 @@ pub(crate) fn load_extern_resources( | |||
410 | res.env.insert(package_id, env); | 442 | res.env.insert(package_id, env); |
411 | } | 443 | } |
412 | Message::CompilerArtifact(message) => { | 444 | Message::CompilerArtifact(message) => { |
445 | progress(format!("metadata {}", message.target.name)); | ||
446 | |||
413 | if message.target.kind.contains(&"proc-macro".to_string()) { | 447 | if message.target.kind.contains(&"proc-macro".to_string()) { |
414 | let package_id = message.package_id; | 448 | let package_id = message.package_id; |
415 | // Skip rmeta file | 449 | // Skip rmeta file |
@@ -420,7 +454,9 @@ pub(crate) fn load_extern_resources( | |||
420 | } | 454 | } |
421 | } | 455 | } |
422 | } | 456 | } |
423 | Message::CompilerMessage(_) => (), | 457 | Message::CompilerMessage(message) => { |
458 | progress(message.target.name.clone()); | ||
459 | } | ||
424 | Message::Unknown => (), | 460 | Message::Unknown => (), |
425 | Message::BuildFinished(_) => {} | 461 | Message::BuildFinished(_) => {} |
426 | Message::TextLine(_) => {} | 462 | Message::TextLine(_) => {} |
diff --git a/crates/project_model/src/lib.rs b/crates/project_model/src/lib.rs index 24aa9b8fa..aabb7a47d 100644 --- a/crates/project_model/src/lib.rs +++ b/crates/project_model/src/lib.rs | |||
@@ -1,9 +1,9 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | mod cargo_workspace; | 3 | mod cargo_workspace; |
4 | mod cfg_flag; | ||
4 | mod project_json; | 5 | mod project_json; |
5 | mod sysroot; | 6 | mod sysroot; |
6 | mod cfg_flag; | ||
7 | mod workspace; | 7 | mod workspace; |
8 | 8 | ||
9 | use std::{ | 9 | use std::{ |
@@ -17,7 +17,10 @@ use paths::{AbsPath, AbsPathBuf}; | |||
17 | use rustc_hash::FxHashSet; | 17 | use rustc_hash::FxHashSet; |
18 | 18 | ||
19 | pub use crate::{ | 19 | pub use crate::{ |
20 | cargo_workspace::{CargoConfig, CargoWorkspace, Package, Target, TargetKind}, | 20 | cargo_workspace::{ |
21 | CargoConfig, CargoWorkspace, Package, PackageData, PackageDependency, Target, TargetData, | ||
22 | TargetKind, | ||
23 | }, | ||
21 | project_json::{ProjectJson, ProjectJsonData}, | 24 | project_json::{ProjectJson, ProjectJsonData}, |
22 | sysroot::Sysroot, | 25 | sysroot::Sysroot, |
23 | workspace::{PackageRoot, ProjectWorkspace}, | 26 | workspace::{PackageRoot, ProjectWorkspace}, |
diff --git a/crates/project_model/src/project_json.rs b/crates/project_model/src/project_json.rs index af884eb84..41a2ac03e 100644 --- a/crates/project_model/src/project_json.rs +++ b/crates/project_model/src/project_json.rs | |||
@@ -110,13 +110,13 @@ impl ProjectJson { | |||
110 | } | 110 | } |
111 | } | 111 | } |
112 | 112 | ||
113 | #[derive(Deserialize)] | 113 | #[derive(Deserialize, Debug, Clone)] |
114 | pub struct ProjectJsonData { | 114 | pub struct ProjectJsonData { |
115 | sysroot_src: Option<PathBuf>, | 115 | sysroot_src: Option<PathBuf>, |
116 | crates: Vec<CrateData>, | 116 | crates: Vec<CrateData>, |
117 | } | 117 | } |
118 | 118 | ||
119 | #[derive(Deserialize)] | 119 | #[derive(Deserialize, Debug, Clone)] |
120 | struct CrateData { | 120 | struct CrateData { |
121 | display_name: Option<String>, | 121 | display_name: Option<String>, |
122 | root_module: PathBuf, | 122 | root_module: PathBuf, |
@@ -132,7 +132,7 @@ struct CrateData { | |||
132 | source: Option<CrateSource>, | 132 | source: Option<CrateSource>, |
133 | } | 133 | } |
134 | 134 | ||
135 | #[derive(Deserialize)] | 135 | #[derive(Deserialize, Debug, Clone)] |
136 | #[serde(rename = "edition")] | 136 | #[serde(rename = "edition")] |
137 | enum EditionData { | 137 | enum EditionData { |
138 | #[serde(rename = "2015")] | 138 | #[serde(rename = "2015")] |
@@ -153,7 +153,7 @@ impl From<EditionData> for Edition { | |||
153 | } | 153 | } |
154 | } | 154 | } |
155 | 155 | ||
156 | #[derive(Deserialize)] | 156 | #[derive(Deserialize, Debug, Clone)] |
157 | struct DepData { | 157 | struct DepData { |
158 | /// Identifies a crate by position in the crates array. | 158 | /// Identifies a crate by position in the crates array. |
159 | #[serde(rename = "crate")] | 159 | #[serde(rename = "crate")] |
@@ -162,7 +162,7 @@ struct DepData { | |||
162 | name: CrateName, | 162 | name: CrateName, |
163 | } | 163 | } |
164 | 164 | ||
165 | #[derive(Deserialize)] | 165 | #[derive(Deserialize, Debug, Clone)] |
166 | struct CrateSource { | 166 | struct CrateSource { |
167 | include_dirs: Vec<PathBuf>, | 167 | include_dirs: Vec<PathBuf>, |
168 | exclude_dirs: Vec<PathBuf>, | 168 | exclude_dirs: Vec<PathBuf>, |
diff --git a/crates/project_model/src/workspace.rs b/crates/project_model/src/workspace.rs index 68a235ce3..06a0be284 100644 --- a/crates/project_model/src/workspace.rs +++ b/crates/project_model/src/workspace.rs | |||
@@ -64,7 +64,11 @@ impl fmt::Debug for ProjectWorkspace { | |||
64 | } | 64 | } |
65 | 65 | ||
66 | impl ProjectWorkspace { | 66 | impl ProjectWorkspace { |
67 | pub fn load(manifest: ProjectManifest, config: &CargoConfig) -> Result<ProjectWorkspace> { | 67 | pub fn load( |
68 | manifest: ProjectManifest, | ||
69 | config: &CargoConfig, | ||
70 | progress: &dyn Fn(String), | ||
71 | ) -> Result<ProjectWorkspace> { | ||
68 | let res = match manifest { | 72 | let res = match manifest { |
69 | ProjectManifest::ProjectJson(project_json) => { | 73 | ProjectManifest::ProjectJson(project_json) => { |
70 | let file = fs::read_to_string(&project_json).with_context(|| { | 74 | let file = fs::read_to_string(&project_json).with_context(|| { |
@@ -84,15 +88,14 @@ impl ProjectWorkspace { | |||
84 | cmd | 88 | cmd |
85 | })?; | 89 | })?; |
86 | 90 | ||
87 | let cargo = CargoWorkspace::from_cargo_metadata(&cargo_toml, config).with_context( | 91 | let cargo = CargoWorkspace::from_cargo_metadata(&cargo_toml, config, progress) |
88 | || { | 92 | .with_context(|| { |
89 | format!( | 93 | format!( |
90 | "Failed to read Cargo metadata from Cargo.toml file {}, {}", | 94 | "Failed to read Cargo metadata from Cargo.toml file {}, {}", |
91 | cargo_toml.display(), | 95 | cargo_toml.display(), |
92 | cargo_version | 96 | cargo_version |
93 | ) | 97 | ) |
94 | }, | 98 | })?; |
95 | )?; | ||
96 | let sysroot = if config.no_sysroot { | 99 | let sysroot = if config.no_sysroot { |
97 | Sysroot::default() | 100 | Sysroot::default() |
98 | } else { | 101 | } else { |
@@ -105,9 +108,12 @@ impl ProjectWorkspace { | |||
105 | }; | 108 | }; |
106 | 109 | ||
107 | let rustc = if let Some(rustc_dir) = &config.rustc_source { | 110 | let rustc = if let Some(rustc_dir) = &config.rustc_source { |
108 | Some(CargoWorkspace::from_cargo_metadata(&rustc_dir, config).with_context( | 111 | Some( |
109 | || format!("Failed to read Cargo metadata for Rust sources"), | 112 | CargoWorkspace::from_cargo_metadata(&rustc_dir, config, progress) |
110 | )?) | 113 | .with_context(|| { |
114 | format!("Failed to read Cargo metadata for Rust sources") | ||
115 | })?, | ||
116 | ) | ||
111 | } else { | 117 | } else { |
112 | None | 118 | None |
113 | }; | 119 | }; |