From 2202891221647c9c1a1c6bd47c0b0214b364803d Mon Sep 17 00:00:00 2001 From: Wilco Kusee Date: Fri, 3 Jan 2020 14:04:46 +0100 Subject: Split errors into WorkspaceError enum --- crates/ra_project_model/src/cargo_workspace.rs | 6 +- crates/ra_project_model/src/lib.rs | 87 +++++++++++++++++++++----- crates/ra_project_model/src/sysroot.rs | 21 +++---- 3 files changed, 85 insertions(+), 29 deletions(-) (limited to 'crates/ra_project_model') 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; use rustc_hash::FxHashMap; use serde::Deserialize; -use crate::Result; +use crate::WorkspaceError; /// `CargoWorkspace` represents the logical structure of, well, a Cargo /// workspace. It pretty closely mirrors `cargo metadata` output. @@ -156,7 +156,7 @@ impl CargoWorkspace { pub fn from_cargo_metadata( cargo_toml: &Path, cargo_features: &CargoFeatures, - ) -> Result { + ) -> Result { let mut meta = MetadataCommand::new(); meta.manifest_path(cargo_toml); if cargo_features.all_features { @@ -171,7 +171,7 @@ impl CargoWorkspace { if let Some(parent) = cargo_toml.parent() { meta.current_dir(parent); } - let meta = meta.exec().map_err(|e| format!("cargo metadata failed: {}", e))?; + let meta = meta.exec().map_err(|e| WorkspaceError::CargoMetadataFailed(e))?; let mut pkg_by_id = FxHashMap::default(); let mut packages = Arena::default(); 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; mod sysroot; use std::{ - error::Error, + fmt, fs::File, io::BufReader, path::{Path, PathBuf}, @@ -13,7 +13,7 @@ use std::{ }; use ra_cfg::CfgOptions; -use ra_db::{CrateGraph, CrateId, Edition, Env, FileId}; +use ra_db::{CrateGraph, CrateId, Edition, Env, FileId, ParseEditionError}; use rustc_hash::FxHashMap; use serde_json::from_reader; @@ -23,8 +23,57 @@ pub use crate::{ sysroot::Sysroot, }; -// FIXME use proper error enum -pub type Result = ::std::result::Result>; +#[derive(Debug)] +pub enum WorkspaceError { + CargoMetadataFailed(cargo_metadata::Error), + CargoTomlNotFound(PathBuf), + NoStdLib(PathBuf), + OpenWorkspaceError(std::io::Error), + ParseEditionError(ParseEditionError), + ReadWorkspaceError(serde_json::Error), + RustcCfgError, + RustcError(std::io::Error), + RustcOutputError(std::string::FromUtf8Error), + SysrootNotFound, +} + +impl fmt::Display for WorkspaceError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::OpenWorkspaceError(err) | Self::RustcError(err) => write!(f, "{}", err), + Self::ParseEditionError(err) => write!(f, "{}", err), + Self::ReadWorkspaceError(err) => write!(f, "{}", err), + Self::RustcOutputError(err) => write!(f, "{}", err), + Self::CargoMetadataFailed(err) => write!(f, "cargo metadata failed: {}", err), + Self::RustcCfgError => write!(f, "failed to get rustc cfgs"), + Self::SysrootNotFound => write!(f, "failed to locate sysroot"), + Self::CargoTomlNotFound(path) => { + write!(f, "can't find Cargo.toml at {}", path.display()) + } + Self::NoStdLib(sysroot) => write!( + f, + "can't load standard library from sysroot\n\ + {:?}\n\ + try running `rustup component add rust-src` or set `RUST_SRC_PATH`", + sysroot, + ), + } + } +} + +impl std::error::Error for WorkspaceError {} + +impl From for WorkspaceError { + fn from(err: ParseEditionError) -> Self { + Self::ParseEditionError(err.into()) + } +} + +impl From for WorkspaceError { + fn from(err: cargo_metadata::Error) -> Self { + Self::CargoMetadataFailed(err.into()) + } +} #[derive(Debug, Clone)] pub enum ProjectWorkspace { @@ -60,7 +109,10 @@ impl PackageRoot { } impl ProjectWorkspace { - pub fn discover(path: &Path, cargo_features: &CargoFeatures) -> Result { + pub fn discover( + path: &Path, + cargo_features: &CargoFeatures, + ) -> Result { ProjectWorkspace::discover_with_sysroot(path, true, cargo_features) } @@ -68,12 +120,16 @@ impl ProjectWorkspace { path: &Path, with_sysroot: bool, cargo_features: &CargoFeatures, - ) -> Result { + ) -> Result { match find_rust_project_json(path) { Some(json_path) => { - let file = File::open(json_path)?; + let file = + File::open(json_path).map_err(|err| WorkspaceError::OpenWorkspaceError(err))?; let reader = BufReader::new(file); - Ok(ProjectWorkspace::Json { project: from_reader(reader)? }) + Ok(ProjectWorkspace::Json { + project: from_reader(reader) + .map_err(|err| WorkspaceError::ReadWorkspaceError(err))?, + }) } None => { let cargo_toml = find_cargo_toml(path)?; @@ -350,7 +406,7 @@ fn find_rust_project_json(path: &Path) -> Option { None } -fn find_cargo_toml(path: &Path) -> Result { +fn find_cargo_toml(path: &Path) -> Result { if path.ends_with("Cargo.toml") { return Ok(path.to_path_buf()); } @@ -362,7 +418,7 @@ fn find_cargo_toml(path: &Path) -> Result { } curr = path.parent(); } - Err(format!("can't find Cargo.toml at {}", path.display()))? + Err(WorkspaceError::CargoTomlNotFound(path.to_path_buf())) } pub fn get_rustc_cfg_options() -> CfgOptions { @@ -376,13 +432,16 @@ pub fn get_rustc_cfg_options() -> CfgOptions { } } - match (|| -> Result<_> { + match (|| -> Result<_, WorkspaceError> { // `cfg(test)` and `cfg(debug_assertion)` are handled outside, so we suppress them here. - let output = Command::new("rustc").args(&["--print", "cfg", "-O"]).output()?; + let output = Command::new("rustc") + .args(&["--print", "cfg", "-O"]) + .output() + .map_err(|err| WorkspaceError::RustcError(err))?; if !output.status.success() { - Err("failed to get rustc cfgs")?; + Err(WorkspaceError::RustcCfgError)?; } - Ok(String::from_utf8(output.stdout)?) + Ok(String::from_utf8(output.stdout).map_err(|err| WorkspaceError::RustcOutputError(err))?) })() { Ok(rustc_cfgs) => { 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::{ use ra_arena::{impl_arena_id, Arena, RawId}; -use crate::Result; +use crate::WorkspaceError; #[derive(Default, Debug, Clone)] pub struct Sysroot { @@ -47,16 +47,11 @@ impl Sysroot { self.crates.iter().map(|(id, _data)| id) } - pub fn discover(cargo_toml: &Path) -> Result { + pub fn discover(cargo_toml: &Path) -> Result { let src = try_find_src_path(cargo_toml)?; if !src.exists() { - Err(format!( - "can't load standard library from sysroot\n\ - {:?}\n\ - try running `rustup component add rust-src` or set `RUST_SRC_PATH`", - src, - ))?; + return Err(WorkspaceError::NoStdLib(src)); } let mut sysroot = Sysroot { crates: Arena::default() }; @@ -90,7 +85,7 @@ impl Sysroot { } } -fn try_find_src_path(cargo_toml: &Path) -> Result { +fn try_find_src_path(cargo_toml: &Path) -> Result { if let Ok(path) = env::var("RUST_SRC_PATH") { return Ok(path.into()); } @@ -98,11 +93,13 @@ fn try_find_src_path(cargo_toml: &Path) -> Result { let rustc_output = Command::new("rustc") .current_dir(cargo_toml.parent().unwrap()) .args(&["--print", "sysroot"]) - .output()?; + .output() + .map_err(|err| WorkspaceError::RustcError(err))?; if !rustc_output.status.success() { - Err("failed to locate sysroot")?; + Err(WorkspaceError::SysrootNotFound)?; } - let stdout = String::from_utf8(rustc_output.stdout)?; + let stdout = String::from_utf8(rustc_output.stdout) + .map_err(|err| WorkspaceError::RustcOutputError(err))?; let sysroot_path = Path::new(stdout.trim()); Ok(sysroot_path.join("lib/rustlib/src/rust/src")) } -- cgit v1.2.3