diff options
Diffstat (limited to 'crates/ra_project_model/src')
-rw-r--r-- | crates/ra_project_model/src/cargo_workspace.rs | 6 | ||||
-rw-r--r-- | crates/ra_project_model/src/lib.rs | 52 | ||||
-rw-r--r-- | crates/ra_project_model/src/sysroot.rs | 21 | ||||
-rw-r--r-- | crates/ra_project_model/src/workspace_error.rs | 57 |
4 files changed, 45 insertions, 91 deletions
diff --git a/crates/ra_project_model/src/cargo_workspace.rs b/crates/ra_project_model/src/cargo_workspace.rs index 446ccfda0..1b3c246c7 100644 --- a/crates/ra_project_model/src/cargo_workspace.rs +++ b/crates/ra_project_model/src/cargo_workspace.rs | |||
@@ -8,7 +8,7 @@ use ra_db::Edition; | |||
8 | use rustc_hash::FxHashMap; | 8 | use rustc_hash::FxHashMap; |
9 | use serde::Deserialize; | 9 | use serde::Deserialize; |
10 | 10 | ||
11 | use crate::WorkspaceError; | 11 | use crate::Result; |
12 | 12 | ||
13 | /// `CargoWorkspace` represents the logical structure of, well, a Cargo | 13 | /// `CargoWorkspace` represents the logical structure of, well, a Cargo |
14 | /// workspace. It pretty closely mirrors `cargo metadata` output. | 14 | /// workspace. It pretty closely mirrors `cargo metadata` output. |
@@ -156,7 +156,7 @@ impl CargoWorkspace { | |||
156 | pub fn from_cargo_metadata( | 156 | pub fn from_cargo_metadata( |
157 | cargo_toml: &Path, | 157 | cargo_toml: &Path, |
158 | cargo_features: &CargoFeatures, | 158 | cargo_features: &CargoFeatures, |
159 | ) -> Result<CargoWorkspace, WorkspaceError> { | 159 | ) -> Result<CargoWorkspace> { |
160 | let mut meta = MetadataCommand::new(); | 160 | let mut meta = MetadataCommand::new(); |
161 | meta.manifest_path(cargo_toml); | 161 | meta.manifest_path(cargo_toml); |
162 | if cargo_features.all_features { | 162 | if cargo_features.all_features { |
@@ -171,7 +171,7 @@ impl CargoWorkspace { | |||
171 | if let Some(parent) = cargo_toml.parent() { | 171 | if let Some(parent) = cargo_toml.parent() { |
172 | meta.current_dir(parent); | 172 | meta.current_dir(parent); |
173 | } | 173 | } |
174 | let meta = meta.exec().map_err(|e| WorkspaceError::CargoMetadataFailed(e))?; | 174 | let meta = meta.exec().map_err(|e| format!("cargo metadata failed: {}", e))?; |
175 | let mut pkg_by_id = FxHashMap::default(); | 175 | let mut pkg_by_id = FxHashMap::default(); |
176 | let mut packages = Arena::default(); | 176 | let mut packages = Arena::default(); |
177 | let mut targets = Arena::default(); | 177 | let mut targets = Arena::default(); |
diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs index 2aa9270c8..e36338860 100644 --- a/crates/ra_project_model/src/lib.rs +++ b/crates/ra_project_model/src/lib.rs | |||
@@ -3,9 +3,9 @@ | |||
3 | mod cargo_workspace; | 3 | mod cargo_workspace; |
4 | mod json_project; | 4 | mod json_project; |
5 | mod sysroot; | 5 | mod sysroot; |
6 | mod workspace_error; | ||
7 | 6 | ||
8 | use std::{ | 7 | use std::{ |
8 | error::Error, | ||
9 | fs::File, | 9 | fs::File, |
10 | io::BufReader, | 10 | io::BufReader, |
11 | path::{Path, PathBuf}, | 11 | path::{Path, PathBuf}, |
@@ -21,9 +21,27 @@ pub use crate::{ | |||
21 | cargo_workspace::{CargoFeatures, CargoWorkspace, Package, Target, TargetKind}, | 21 | cargo_workspace::{CargoFeatures, CargoWorkspace, Package, Target, TargetKind}, |
22 | json_project::JsonProject, | 22 | json_project::JsonProject, |
23 | sysroot::Sysroot, | 23 | sysroot::Sysroot, |
24 | workspace_error::WorkspaceError, | ||
25 | }; | 24 | }; |
26 | 25 | ||
26 | pub type Result<T> = ::std::result::Result<T, Box<dyn Error + Send + Sync>>; | ||
27 | |||
28 | #[derive(Clone, PartialEq, Eq, Hash)] | ||
29 | pub struct CargoTomlNotFoundError(pub PathBuf); | ||
30 | |||
31 | impl std::fmt::Display for CargoTomlNotFoundError { | ||
32 | fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
33 | write!(fmt, "can't find Cargo.toml at {}", self.0.display()) | ||
34 | } | ||
35 | } | ||
36 | |||
37 | impl std::fmt::Debug for CargoTomlNotFoundError { | ||
38 | fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
39 | write!(fmt, "can't find Cargo.toml at {}", self.0.display()) | ||
40 | } | ||
41 | } | ||
42 | |||
43 | impl Error for CargoTomlNotFoundError {} | ||
44 | |||
27 | #[derive(Debug, Clone)] | 45 | #[derive(Debug, Clone)] |
28 | pub enum ProjectWorkspace { | 46 | pub enum ProjectWorkspace { |
29 | /// Project workspace was discovered by running `cargo metadata` and `rustc --print sysroot`. | 47 | /// Project workspace was discovered by running `cargo metadata` and `rustc --print sysroot`. |
@@ -58,10 +76,7 @@ impl PackageRoot { | |||
58 | } | 76 | } |
59 | 77 | ||
60 | impl ProjectWorkspace { | 78 | impl ProjectWorkspace { |
61 | pub fn discover( | 79 | pub fn discover(path: &Path, cargo_features: &CargoFeatures) -> Result<ProjectWorkspace> { |
62 | path: &Path, | ||
63 | cargo_features: &CargoFeatures, | ||
64 | ) -> Result<ProjectWorkspace, WorkspaceError> { | ||
65 | ProjectWorkspace::discover_with_sysroot(path, true, cargo_features) | 80 | ProjectWorkspace::discover_with_sysroot(path, true, cargo_features) |
66 | } | 81 | } |
67 | 82 | ||
@@ -69,16 +84,12 @@ impl ProjectWorkspace { | |||
69 | path: &Path, | 84 | path: &Path, |
70 | with_sysroot: bool, | 85 | with_sysroot: bool, |
71 | cargo_features: &CargoFeatures, | 86 | cargo_features: &CargoFeatures, |
72 | ) -> Result<ProjectWorkspace, WorkspaceError> { | 87 | ) -> Result<ProjectWorkspace> { |
73 | match find_rust_project_json(path) { | 88 | match find_rust_project_json(path) { |
74 | Some(json_path) => { | 89 | Some(json_path) => { |
75 | let file = | 90 | let file = File::open(json_path)?; |
76 | File::open(json_path).map_err(|err| WorkspaceError::OpenWorkspaceError(err))?; | ||
77 | let reader = BufReader::new(file); | 91 | let reader = BufReader::new(file); |
78 | Ok(ProjectWorkspace::Json { | 92 | Ok(ProjectWorkspace::Json { project: from_reader(reader)? }) |
79 | project: from_reader(reader) | ||
80 | .map_err(|err| WorkspaceError::ReadWorkspaceError(err))?, | ||
81 | }) | ||
82 | } | 93 | } |
83 | None => { | 94 | None => { |
84 | let cargo_toml = find_cargo_toml(path)?; | 95 | let cargo_toml = find_cargo_toml(path)?; |
@@ -355,7 +366,7 @@ fn find_rust_project_json(path: &Path) -> Option<PathBuf> { | |||
355 | None | 366 | None |
356 | } | 367 | } |
357 | 368 | ||
358 | fn find_cargo_toml(path: &Path) -> Result<PathBuf, WorkspaceError> { | 369 | fn find_cargo_toml(path: &Path) -> Result<PathBuf> { |
359 | if path.ends_with("Cargo.toml") { | 370 | if path.ends_with("Cargo.toml") { |
360 | return Ok(path.to_path_buf()); | 371 | return Ok(path.to_path_buf()); |
361 | } | 372 | } |
@@ -367,7 +378,7 @@ fn find_cargo_toml(path: &Path) -> Result<PathBuf, WorkspaceError> { | |||
367 | } | 378 | } |
368 | curr = path.parent(); | 379 | curr = path.parent(); |
369 | } | 380 | } |
370 | Err(WorkspaceError::CargoTomlNotFound(path.to_path_buf())) | 381 | Err(Box::new(CargoTomlNotFoundError(path.to_path_buf()))) |
371 | } | 382 | } |
372 | 383 | ||
373 | pub fn get_rustc_cfg_options() -> CfgOptions { | 384 | pub fn get_rustc_cfg_options() -> CfgOptions { |
@@ -381,16 +392,13 @@ pub fn get_rustc_cfg_options() -> CfgOptions { | |||
381 | } | 392 | } |
382 | } | 393 | } |
383 | 394 | ||
384 | match (|| -> Result<_, WorkspaceError> { | 395 | match (|| -> Result<_> { |
385 | // `cfg(test)` and `cfg(debug_assertion)` are handled outside, so we suppress them here. | 396 | // `cfg(test)` and `cfg(debug_assertion)` are handled outside, so we suppress them here. |
386 | let output = Command::new("rustc") | 397 | let output = Command::new("rustc").args(&["--print", "cfg", "-O"]).output()?; |
387 | .args(&["--print", "cfg", "-O"]) | ||
388 | .output() | ||
389 | .map_err(|err| WorkspaceError::RustcError(err))?; | ||
390 | if !output.status.success() { | 398 | if !output.status.success() { |
391 | Err(WorkspaceError::RustcCfgError)?; | 399 | Err("failed to get rustc cfgs")?; |
392 | } | 400 | } |
393 | Ok(String::from_utf8(output.stdout).map_err(|err| WorkspaceError::RustcOutputError(err))?) | 401 | Ok(String::from_utf8(output.stdout)?) |
394 | })() { | 402 | })() { |
395 | Ok(rustc_cfgs) => { | 403 | Ok(rustc_cfgs) => { |
396 | for line in rustc_cfgs.lines() { | 404 | for line in rustc_cfgs.lines() { |
diff --git a/crates/ra_project_model/src/sysroot.rs b/crates/ra_project_model/src/sysroot.rs index 24c3f47a2..10ca391b6 100644 --- a/crates/ra_project_model/src/sysroot.rs +++ b/crates/ra_project_model/src/sysroot.rs | |||
@@ -8,7 +8,7 @@ use std::{ | |||
8 | 8 | ||
9 | use ra_arena::{impl_arena_id, Arena, RawId}; | 9 | use ra_arena::{impl_arena_id, Arena, RawId}; |
10 | 10 | ||
11 | use crate::WorkspaceError; | 11 | use crate::Result; |
12 | 12 | ||
13 | #[derive(Default, Debug, Clone)] | 13 | #[derive(Default, Debug, Clone)] |
14 | pub struct Sysroot { | 14 | pub struct Sysroot { |
@@ -47,11 +47,16 @@ impl Sysroot { | |||
47 | self.crates.iter().map(|(id, _data)| id) | 47 | self.crates.iter().map(|(id, _data)| id) |
48 | } | 48 | } |
49 | 49 | ||
50 | pub fn discover(cargo_toml: &Path) -> Result<Sysroot, WorkspaceError> { | 50 | pub fn discover(cargo_toml: &Path) -> Result<Sysroot> { |
51 | let src = try_find_src_path(cargo_toml)?; | 51 | let src = try_find_src_path(cargo_toml)?; |
52 | 52 | ||
53 | if !src.exists() { | 53 | if !src.exists() { |
54 | return Err(WorkspaceError::NoStdLib(src)); | 54 | Err(format!( |
55 | "can't load standard library from sysroot\n\ | ||
56 | {:?}\n\ | ||
57 | try running `rustup component add rust-src` or set `RUST_SRC_PATH`", | ||
58 | src, | ||
59 | ))?; | ||
55 | } | 60 | } |
56 | 61 | ||
57 | let mut sysroot = Sysroot { crates: Arena::default() }; | 62 | let mut sysroot = Sysroot { crates: Arena::default() }; |
@@ -85,7 +90,7 @@ impl Sysroot { | |||
85 | } | 90 | } |
86 | } | 91 | } |
87 | 92 | ||
88 | fn try_find_src_path(cargo_toml: &Path) -> Result<PathBuf, WorkspaceError> { | 93 | fn try_find_src_path(cargo_toml: &Path) -> Result<PathBuf> { |
89 | if let Ok(path) = env::var("RUST_SRC_PATH") { | 94 | if let Ok(path) = env::var("RUST_SRC_PATH") { |
90 | return Ok(path.into()); | 95 | return Ok(path.into()); |
91 | } | 96 | } |
@@ -93,13 +98,11 @@ fn try_find_src_path(cargo_toml: &Path) -> Result<PathBuf, WorkspaceError> { | |||
93 | let rustc_output = Command::new("rustc") | 98 | let rustc_output = Command::new("rustc") |
94 | .current_dir(cargo_toml.parent().unwrap()) | 99 | .current_dir(cargo_toml.parent().unwrap()) |
95 | .args(&["--print", "sysroot"]) | 100 | .args(&["--print", "sysroot"]) |
96 | .output() | 101 | .output()?; |
97 | .map_err(|err| WorkspaceError::RustcError(err))?; | ||
98 | if !rustc_output.status.success() { | 102 | if !rustc_output.status.success() { |
99 | Err(WorkspaceError::SysrootNotFound)?; | 103 | Err("failed to locate sysroot")?; |
100 | } | 104 | } |
101 | let stdout = String::from_utf8(rustc_output.stdout) | 105 | let stdout = String::from_utf8(rustc_output.stdout)?; |
102 | .map_err(|err| WorkspaceError::RustcOutputError(err))?; | ||
103 | let sysroot_path = Path::new(stdout.trim()); | 106 | let sysroot_path = Path::new(stdout.trim()); |
104 | Ok(sysroot_path.join("lib/rustlib/src/rust/src")) | 107 | Ok(sysroot_path.join("lib/rustlib/src/rust/src")) |
105 | } | 108 | } |
diff --git a/crates/ra_project_model/src/workspace_error.rs b/crates/ra_project_model/src/workspace_error.rs deleted file mode 100644 index 5f7384968..000000000 --- a/crates/ra_project_model/src/workspace_error.rs +++ /dev/null | |||
@@ -1,57 +0,0 @@ | |||
1 | //! Workspace-related errors | ||
2 | |||
3 | use std::{error::Error, fmt, io, path::PathBuf, string::FromUtf8Error}; | ||
4 | |||
5 | use ra_db::ParseEditionError; | ||
6 | |||
7 | #[derive(Debug)] | ||
8 | pub enum WorkspaceError { | ||
9 | CargoMetadataFailed(cargo_metadata::Error), | ||
10 | CargoTomlNotFound(PathBuf), | ||
11 | NoStdLib(PathBuf), | ||
12 | OpenWorkspaceError(io::Error), | ||
13 | ParseEditionError(ParseEditionError), | ||
14 | ReadWorkspaceError(serde_json::Error), | ||
15 | RustcCfgError, | ||
16 | RustcError(io::Error), | ||
17 | RustcOutputError(FromUtf8Error), | ||
18 | SysrootNotFound, | ||
19 | } | ||
20 | |||
21 | impl fmt::Display for WorkspaceError { | ||
22 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
23 | match self { | ||
24 | Self::OpenWorkspaceError(err) | Self::RustcError(err) => write!(f, "{}", err), | ||
25 | Self::ParseEditionError(err) => write!(f, "{}", err), | ||
26 | Self::ReadWorkspaceError(err) => write!(f, "{}", err), | ||
27 | Self::RustcOutputError(err) => write!(f, "{}", err), | ||
28 | Self::CargoMetadataFailed(err) => write!(f, "cargo metadata failed: {}", err), | ||
29 | Self::RustcCfgError => write!(f, "failed to get rustc cfgs"), | ||
30 | Self::SysrootNotFound => write!(f, "failed to locate sysroot"), | ||
31 | Self::CargoTomlNotFound(path) => { | ||
32 | write!(f, "can't find Cargo.toml at {}", path.display()) | ||
33 | } | ||
34 | Self::NoStdLib(sysroot) => write!( | ||
35 | f, | ||
36 | "can't load standard library from sysroot\n\ | ||
37 | {:?}\n\ | ||
38 | try running `rustup component add rust-src` or set `RUST_SRC_PATH`", | ||
39 | sysroot, | ||
40 | ), | ||
41 | } | ||
42 | } | ||
43 | } | ||
44 | |||
45 | impl From<ParseEditionError> for WorkspaceError { | ||
46 | fn from(err: ParseEditionError) -> Self { | ||
47 | Self::ParseEditionError(err.into()) | ||
48 | } | ||
49 | } | ||
50 | |||
51 | impl From<cargo_metadata::Error> for WorkspaceError { | ||
52 | fn from(err: cargo_metadata::Error) -> Self { | ||
53 | Self::CargoMetadataFailed(err.into()) | ||
54 | } | ||
55 | } | ||
56 | |||
57 | impl Error for WorkspaceError {} | ||