From 6f2cab1368dafc5663bb591a45062280a94a4ef9 Mon Sep 17 00:00:00 2001 From: Adam Bratschi-Kaye Date: Thu, 13 Feb 2020 11:10:50 +0100 Subject: Add error context to failures in `ra_project_model` using `anyhow` crate (#3119) Add error context to failures in ra_project_model using anyhow crate --- Cargo.lock | 1 + crates/ra_project_model/Cargo.toml | 2 + crates/ra_project_model/src/cargo_workspace.rs | 11 ++++-- crates/ra_project_model/src/lib.rs | 51 ++++++++++++++++++++------ crates/ra_project_model/src/sysroot.rs | 14 ++++--- 5 files changed, 59 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 45804c087..f1651edaa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1247,6 +1247,7 @@ dependencies = [ name = "ra_project_model" version = "0.1.0" dependencies = [ + "anyhow", "cargo_metadata", "log", "ra_arena", diff --git a/crates/ra_project_model/Cargo.toml b/crates/ra_project_model/Cargo.toml index 69edc3c66..653d5bd14 100644 --- a/crates/ra_project_model/Cargo.toml +++ b/crates/ra_project_model/Cargo.toml @@ -19,3 +19,5 @@ ra_cfg = { path = "../ra_cfg" } serde = { version = "1.0.89", features = ["derive"] } serde_json = "1.0.39" + +anyhow = "1.0.26" diff --git a/crates/ra_project_model/src/cargo_workspace.rs b/crates/ra_project_model/src/cargo_workspace.rs index 60cb8c1eb..22d226a74 100644 --- a/crates/ra_project_model/src/cargo_workspace.rs +++ b/crates/ra_project_model/src/cargo_workspace.rs @@ -2,14 +2,13 @@ use std::path::{Path, PathBuf}; +use anyhow::{Context, Result}; use cargo_metadata::{CargoOpt, MetadataCommand}; use ra_arena::{impl_arena_id, Arena, RawId}; use ra_db::Edition; use rustc_hash::FxHashMap; use serde::Deserialize; -use crate::Result; - /// `CargoWorkspace` represents the logical structure of, well, a Cargo /// workspace. It pretty closely mirrors `cargo metadata` output. /// @@ -171,7 +170,9 @@ 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().with_context(|| { + format!("Failed to run `cargo metadata --manifest-path {}`", cargo_toml.display()) + })?; let mut pkg_by_id = FxHashMap::default(); let mut packages = Arena::default(); let mut targets = Arena::default(); @@ -181,7 +182,9 @@ impl CargoWorkspace { for meta_pkg in meta.packages { let cargo_metadata::Package { id, edition, name, manifest_path, .. } = meta_pkg; let is_member = ws_members.contains(&id); - let edition = edition.parse::()?; + let edition = edition + .parse::() + .with_context(|| format!("Failed to parse edition {}", edition))?; let pkg = packages.alloc(PackageData { name, manifest: manifest_path, diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs index bc1d15406..fef405b7f 100644 --- a/crates/ra_project_model/src/lib.rs +++ b/crates/ra_project_model/src/lib.rs @@ -12,6 +12,7 @@ use std::{ process::Command, }; +use anyhow::{bail, Context, Result}; use ra_cfg::CfgOptions; use ra_db::{CrateGraph, CrateId, CrateName, Edition, Env, FileId}; use rustc_hash::FxHashMap; @@ -23,8 +24,6 @@ pub use crate::{ sysroot::Sysroot, }; -pub type Result = ::std::result::Result>; - #[derive(Clone, PartialEq, Eq, Hash, Debug)] pub struct CargoTomlNotFoundError(pub PathBuf); @@ -81,15 +80,36 @@ impl ProjectWorkspace { ) -> Result { match find_rust_project_json(path) { Some(json_path) => { - let file = File::open(json_path)?; + let file = File::open(&json_path) + .with_context(|| format!("Failed to open json file {}", json_path.display()))?; let reader = BufReader::new(file); - Ok(ProjectWorkspace::Json { project: from_reader(reader)? }) + Ok(ProjectWorkspace::Json { + project: from_reader(reader).with_context(|| { + format!("Failed to deserialize json file {}", json_path.display()) + })?, + }) } None => { - let cargo_toml = find_cargo_toml(path)?; - let cargo = CargoWorkspace::from_cargo_metadata(&cargo_toml, cargo_features)?; - let sysroot = - if with_sysroot { Sysroot::discover(&cargo_toml)? } else { Sysroot::default() }; + let cargo_toml = find_cargo_toml(path).with_context(|| { + format!("Failed to find Cargo.toml for path {}", path.display()) + })?; + let cargo = CargoWorkspace::from_cargo_metadata(&cargo_toml, cargo_features) + .with_context(|| { + format!( + "Failed to read Cargo metadata from Cargo.toml file {}", + cargo_toml.display() + ) + })?; + let sysroot = if with_sysroot { + Sysroot::discover(&cargo_toml).with_context(|| { + format!( + "Failed to find sysroot for Cargo.toml file {}", + cargo_toml.display() + ) + })? + } else { + Sysroot::default() + }; Ok(ProjectWorkspace::Cargo { cargo, sysroot }) } } @@ -403,11 +423,20 @@ pub fn get_rustc_cfg_options() -> CfgOptions { } } - match (|| -> Result<_> { + match (|| -> Result { // `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() + .context("Failed to get output from rustc --print cfg -O")?; if !output.status.success() { - Err("failed to get rustc cfgs")?; + bail!( + "rustc --print cfg -O exited with exit code ({})", + output + .status + .code() + .map_or(String::from("no exit code"), |code| format!("{}", code)) + ); } Ok(String::from_utf8(output.stdout)?) })() { diff --git a/crates/ra_project_model/src/sysroot.rs b/crates/ra_project_model/src/sysroot.rs index a23265fc0..7b9cc899c 100644 --- a/crates/ra_project_model/src/sysroot.rs +++ b/crates/ra_project_model/src/sysroot.rs @@ -1,5 +1,6 @@ //! FIXME: write short doc here +use anyhow::{anyhow, bail, Context, Result}; use std::{ env, path::{Path, PathBuf}, @@ -8,8 +9,6 @@ use std::{ use ra_arena::{impl_arena_id, Arena, RawId}; -use crate::Result; - #[derive(Default, Debug, Clone)] pub struct Sysroot { crates: Arena, @@ -51,7 +50,7 @@ impl Sysroot { let src = try_find_src_path(cargo_toml)?; if !src.exists() { - Err(format!( + Err(anyhow!( "can't load standard library from sysroot\n\ {}\n\ (discovered via `rustc --print sysroot`)\n\ @@ -100,9 +99,14 @@ fn try_find_src_path(cargo_toml: &Path) -> Result { .current_dir(cargo_toml.parent().unwrap()) .args(&["--print", "sysroot"]) .output() - .map_err(|e| format!("rustc --print sysroot failed: {}", e))?; + .context("rustc --print sysroot failed")?; if !rustc_output.status.success() { - Err("failed to locate sysroot")?; + match rustc_output.status.code() { + Some(code) => { + bail!("failed to locate sysroot: rustc --print sysroot exited with code {}", code) + } + None => bail!("failed to locate sysroot: rustc --print sysroot terminated by signal"), + }; } let stdout = String::from_utf8(rustc_output.stdout)?; let sysroot_path = Path::new(stdout.trim()); -- cgit v1.2.3