diff options
-rw-r--r-- | crates/ra_db/src/lib.rs | 5 | ||||
-rw-r--r-- | crates/ra_project_model/src/cargo_workspace.rs | 6 | ||||
-rw-r--r-- | crates/ra_project_model/src/lib.rs | 87 | ||||
-rw-r--r-- | crates/ra_project_model/src/sysroot.rs | 21 |
4 files changed, 89 insertions, 30 deletions
diff --git a/crates/ra_db/src/lib.rs b/crates/ra_db/src/lib.rs index 21341b769..db55c3bb2 100644 --- a/crates/ra_db/src/lib.rs +++ b/crates/ra_db/src/lib.rs | |||
@@ -10,7 +10,10 @@ use ra_syntax::{ast, Parse, SourceFile, TextRange, TextUnit}; | |||
10 | 10 | ||
11 | pub use crate::{ | 11 | pub use crate::{ |
12 | cancellation::Canceled, | 12 | cancellation::Canceled, |
13 | input::{CrateGraph, CrateId, Dependency, Edition, Env, FileId, SourceRoot, SourceRootId}, | 13 | input::{ |
14 | CrateGraph, CrateId, Dependency, Edition, Env, FileId, ParseEditionError, SourceRoot, | ||
15 | SourceRootId, | ||
16 | }, | ||
14 | }; | 17 | }; |
15 | pub use relative_path::{RelativePath, RelativePathBuf}; | 18 | pub use relative_path::{RelativePath, RelativePathBuf}; |
16 | pub use salsa; | 19 | pub use salsa; |
diff --git a/crates/ra_project_model/src/cargo_workspace.rs b/crates/ra_project_model/src/cargo_workspace.rs index 1b3c246c7..446ccfda0 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::Result; | 11 | use crate::WorkspaceError; |
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> { | 159 | ) -> Result<CargoWorkspace, WorkspaceError> { |
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| format!("cargo metadata failed: {}", e))?; | 174 | let meta = meta.exec().map_err(|e| WorkspaceError::CargoMetadataFailed(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 d71b7031a..49710b358 100644 --- a/crates/ra_project_model/src/lib.rs +++ b/crates/ra_project_model/src/lib.rs | |||
@@ -5,7 +5,7 @@ mod json_project; | |||
5 | mod sysroot; | 5 | mod sysroot; |
6 | 6 | ||
7 | use std::{ | 7 | use std::{ |
8 | error::Error, | 8 | fmt, |
9 | fs::File, | 9 | fs::File, |
10 | io::BufReader, | 10 | io::BufReader, |
11 | path::{Path, PathBuf}, | 11 | path::{Path, PathBuf}, |
@@ -13,7 +13,7 @@ use std::{ | |||
13 | }; | 13 | }; |
14 | 14 | ||
15 | use ra_cfg::CfgOptions; | 15 | use ra_cfg::CfgOptions; |
16 | use ra_db::{CrateGraph, CrateId, Edition, Env, FileId}; | 16 | use ra_db::{CrateGraph, CrateId, Edition, Env, FileId, ParseEditionError}; |
17 | use rustc_hash::FxHashMap; | 17 | use rustc_hash::FxHashMap; |
18 | use serde_json::from_reader; | 18 | use serde_json::from_reader; |
19 | 19 | ||
@@ -23,8 +23,57 @@ pub use crate::{ | |||
23 | sysroot::Sysroot, | 23 | sysroot::Sysroot, |
24 | }; | 24 | }; |
25 | 25 | ||
26 | // FIXME use proper error enum | 26 | #[derive(Debug)] |
27 | pub type Result<T> = ::std::result::Result<T, Box<dyn Error + Send + Sync>>; | 27 | pub enum WorkspaceError { |
28 | CargoMetadataFailed(cargo_metadata::Error), | ||
29 | CargoTomlNotFound(PathBuf), | ||
30 | NoStdLib(PathBuf), | ||
31 | OpenWorkspaceError(std::io::Error), | ||
32 | ParseEditionError(ParseEditionError), | ||
33 | ReadWorkspaceError(serde_json::Error), | ||
34 | RustcCfgError, | ||
35 | RustcError(std::io::Error), | ||
36 | RustcOutputError(std::string::FromUtf8Error), | ||
37 | SysrootNotFound, | ||
38 | } | ||
39 | |||
40 | impl fmt::Display for WorkspaceError { | ||
41 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
42 | match self { | ||
43 | Self::OpenWorkspaceError(err) | Self::RustcError(err) => write!(f, "{}", err), | ||
44 | Self::ParseEditionError(err) => write!(f, "{}", err), | ||
45 | Self::ReadWorkspaceError(err) => write!(f, "{}", err), | ||
46 | Self::RustcOutputError(err) => write!(f, "{}", err), | ||
47 | Self::CargoMetadataFailed(err) => write!(f, "cargo metadata failed: {}", err), | ||
48 | Self::RustcCfgError => write!(f, "failed to get rustc cfgs"), | ||
49 | Self::SysrootNotFound => write!(f, "failed to locate sysroot"), | ||
50 | Self::CargoTomlNotFound(path) => { | ||
51 | write!(f, "can't find Cargo.toml at {}", path.display()) | ||
52 | } | ||
53 | Self::NoStdLib(sysroot) => write!( | ||
54 | f, | ||
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 | sysroot, | ||
59 | ), | ||
60 | } | ||
61 | } | ||
62 | } | ||
63 | |||
64 | impl std::error::Error for WorkspaceError {} | ||
65 | |||
66 | impl From<ParseEditionError> for WorkspaceError { | ||
67 | fn from(err: ParseEditionError) -> Self { | ||
68 | Self::ParseEditionError(err.into()) | ||
69 | } | ||
70 | } | ||
71 | |||
72 | impl From<cargo_metadata::Error> for WorkspaceError { | ||
73 | fn from(err: cargo_metadata::Error) -> Self { | ||
74 | Self::CargoMetadataFailed(err.into()) | ||
75 | } | ||
76 | } | ||
28 | 77 | ||
29 | #[derive(Debug, Clone)] | 78 | #[derive(Debug, Clone)] |
30 | pub enum ProjectWorkspace { | 79 | pub enum ProjectWorkspace { |
@@ -60,7 +109,10 @@ impl PackageRoot { | |||
60 | } | 109 | } |
61 | 110 | ||
62 | impl ProjectWorkspace { | 111 | impl ProjectWorkspace { |
63 | pub fn discover(path: &Path, cargo_features: &CargoFeatures) -> Result<ProjectWorkspace> { | 112 | pub fn discover( |
113 | path: &Path, | ||
114 | cargo_features: &CargoFeatures, | ||
115 | ) -> Result<ProjectWorkspace, WorkspaceError> { | ||
64 | ProjectWorkspace::discover_with_sysroot(path, true, cargo_features) | 116 | ProjectWorkspace::discover_with_sysroot(path, true, cargo_features) |
65 | } | 117 | } |
66 | 118 | ||
@@ -68,12 +120,16 @@ impl ProjectWorkspace { | |||
68 | path: &Path, | 120 | path: &Path, |
69 | with_sysroot: bool, | 121 | with_sysroot: bool, |
70 | cargo_features: &CargoFeatures, | 122 | cargo_features: &CargoFeatures, |
71 | ) -> Result<ProjectWorkspace> { | 123 | ) -> Result<ProjectWorkspace, WorkspaceError> { |
72 | match find_rust_project_json(path) { | 124 | match find_rust_project_json(path) { |
73 | Some(json_path) => { | 125 | Some(json_path) => { |
74 | let file = File::open(json_path)?; | 126 | let file = |
127 | File::open(json_path).map_err(|err| WorkspaceError::OpenWorkspaceError(err))?; | ||
75 | let reader = BufReader::new(file); | 128 | let reader = BufReader::new(file); |
76 | Ok(ProjectWorkspace::Json { project: from_reader(reader)? }) | 129 | Ok(ProjectWorkspace::Json { |
130 | project: from_reader(reader) | ||
131 | .map_err(|err| WorkspaceError::ReadWorkspaceError(err))?, | ||
132 | }) | ||
77 | } | 133 | } |
78 | None => { | 134 | None => { |
79 | let cargo_toml = find_cargo_toml(path)?; | 135 | let cargo_toml = find_cargo_toml(path)?; |
@@ -350,7 +406,7 @@ fn find_rust_project_json(path: &Path) -> Option<PathBuf> { | |||
350 | None | 406 | None |
351 | } | 407 | } |
352 | 408 | ||
353 | fn find_cargo_toml(path: &Path) -> Result<PathBuf> { | 409 | fn find_cargo_toml(path: &Path) -> Result<PathBuf, WorkspaceError> { |
354 | if path.ends_with("Cargo.toml") { | 410 | if path.ends_with("Cargo.toml") { |
355 | return Ok(path.to_path_buf()); | 411 | return Ok(path.to_path_buf()); |
356 | } | 412 | } |
@@ -362,7 +418,7 @@ fn find_cargo_toml(path: &Path) -> Result<PathBuf> { | |||
362 | } | 418 | } |
363 | curr = path.parent(); | 419 | curr = path.parent(); |
364 | } | 420 | } |
365 | Err(format!("can't find Cargo.toml at {}", path.display()))? | 421 | Err(WorkspaceError::CargoTomlNotFound(path.to_path_buf())) |
366 | } | 422 | } |
367 | 423 | ||
368 | pub fn get_rustc_cfg_options() -> CfgOptions { | 424 | pub fn get_rustc_cfg_options() -> CfgOptions { |
@@ -376,13 +432,16 @@ pub fn get_rustc_cfg_options() -> CfgOptions { | |||
376 | } | 432 | } |
377 | } | 433 | } |
378 | 434 | ||
379 | match (|| -> Result<_> { | 435 | match (|| -> Result<_, WorkspaceError> { |
380 | // `cfg(test)` and `cfg(debug_assertion)` are handled outside, so we suppress them here. | 436 | // `cfg(test)` and `cfg(debug_assertion)` are handled outside, so we suppress them here. |
381 | let output = Command::new("rustc").args(&["--print", "cfg", "-O"]).output()?; | 437 | let output = Command::new("rustc") |
438 | .args(&["--print", "cfg", "-O"]) | ||
439 | .output() | ||
440 | .map_err(|err| WorkspaceError::RustcError(err))?; | ||
382 | if !output.status.success() { | 441 | if !output.status.success() { |
383 | Err("failed to get rustc cfgs")?; | 442 | Err(WorkspaceError::RustcCfgError)?; |
384 | } | 443 | } |
385 | Ok(String::from_utf8(output.stdout)?) | 444 | Ok(String::from_utf8(output.stdout).map_err(|err| WorkspaceError::RustcOutputError(err))?) |
386 | })() { | 445 | })() { |
387 | Ok(rustc_cfgs) => { | 446 | Ok(rustc_cfgs) => { |
388 | for line in rustc_cfgs.lines() { | 447 | 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 10ca391b6..24c3f47a2 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::Result; | 11 | use crate::WorkspaceError; |
12 | 12 | ||
13 | #[derive(Default, Debug, Clone)] | 13 | #[derive(Default, Debug, Clone)] |
14 | pub struct Sysroot { | 14 | pub struct Sysroot { |
@@ -47,16 +47,11 @@ 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> { | 50 | pub fn discover(cargo_toml: &Path) -> Result<Sysroot, WorkspaceError> { |
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 | Err(format!( | 54 | return Err(WorkspaceError::NoStdLib(src)); |
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 | ))?; | ||
60 | } | 55 | } |
61 | 56 | ||
62 | let mut sysroot = Sysroot { crates: Arena::default() }; | 57 | let mut sysroot = Sysroot { crates: Arena::default() }; |
@@ -90,7 +85,7 @@ impl Sysroot { | |||
90 | } | 85 | } |
91 | } | 86 | } |
92 | 87 | ||
93 | fn try_find_src_path(cargo_toml: &Path) -> Result<PathBuf> { | 88 | fn try_find_src_path(cargo_toml: &Path) -> Result<PathBuf, WorkspaceError> { |
94 | if let Ok(path) = env::var("RUST_SRC_PATH") { | 89 | if let Ok(path) = env::var("RUST_SRC_PATH") { |
95 | return Ok(path.into()); | 90 | return Ok(path.into()); |
96 | } | 91 | } |
@@ -98,11 +93,13 @@ fn try_find_src_path(cargo_toml: &Path) -> Result<PathBuf> { | |||
98 | let rustc_output = Command::new("rustc") | 93 | let rustc_output = Command::new("rustc") |
99 | .current_dir(cargo_toml.parent().unwrap()) | 94 | .current_dir(cargo_toml.parent().unwrap()) |
100 | .args(&["--print", "sysroot"]) | 95 | .args(&["--print", "sysroot"]) |
101 | .output()?; | 96 | .output() |
97 | .map_err(|err| WorkspaceError::RustcError(err))?; | ||
102 | if !rustc_output.status.success() { | 98 | if !rustc_output.status.success() { |
103 | Err("failed to locate sysroot")?; | 99 | Err(WorkspaceError::SysrootNotFound)?; |
104 | } | 100 | } |
105 | let stdout = String::from_utf8(rustc_output.stdout)?; | 101 | let stdout = String::from_utf8(rustc_output.stdout) |
102 | .map_err(|err| WorkspaceError::RustcOutputError(err))?; | ||
106 | let sysroot_path = Path::new(stdout.trim()); | 103 | let sysroot_path = Path::new(stdout.trim()); |
107 | Ok(sysroot_path.join("lib/rustlib/src/rust/src")) | 104 | Ok(sysroot_path.join("lib/rustlib/src/rust/src")) |
108 | } | 105 | } |