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
This commit is contained in:
parent
39abac8c91
commit
6f2cab1368
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -1247,6 +1247,7 @@ dependencies = [
|
|||||||
name = "ra_project_model"
|
name = "ra_project_model"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
"cargo_metadata",
|
"cargo_metadata",
|
||||||
"log",
|
"log",
|
||||||
"ra_arena",
|
"ra_arena",
|
||||||
|
@ -19,3 +19,5 @@ ra_cfg = { path = "../ra_cfg" }
|
|||||||
|
|
||||||
serde = { version = "1.0.89", features = ["derive"] }
|
serde = { version = "1.0.89", features = ["derive"] }
|
||||||
serde_json = "1.0.39"
|
serde_json = "1.0.39"
|
||||||
|
|
||||||
|
anyhow = "1.0.26"
|
||||||
|
@ -2,14 +2,13 @@
|
|||||||
|
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
|
use anyhow::{Context, Result};
|
||||||
use cargo_metadata::{CargoOpt, MetadataCommand};
|
use cargo_metadata::{CargoOpt, MetadataCommand};
|
||||||
use ra_arena::{impl_arena_id, Arena, RawId};
|
use ra_arena::{impl_arena_id, Arena, RawId};
|
||||||
use ra_db::Edition;
|
use ra_db::Edition;
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
use crate::Result;
|
|
||||||
|
|
||||||
/// `CargoWorkspace` represents the logical structure of, well, a Cargo
|
/// `CargoWorkspace` represents the logical structure of, well, a Cargo
|
||||||
/// workspace. It pretty closely mirrors `cargo metadata` output.
|
/// workspace. It pretty closely mirrors `cargo metadata` output.
|
||||||
///
|
///
|
||||||
@ -171,7 +170,9 @@ pub fn from_cargo_metadata(
|
|||||||
if let Some(parent) = cargo_toml.parent() {
|
if let Some(parent) = cargo_toml.parent() {
|
||||||
meta.current_dir(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 pkg_by_id = FxHashMap::default();
|
||||||
let mut packages = Arena::default();
|
let mut packages = Arena::default();
|
||||||
let mut targets = Arena::default();
|
let mut targets = Arena::default();
|
||||||
@ -181,7 +182,9 @@ pub fn from_cargo_metadata(
|
|||||||
for meta_pkg in meta.packages {
|
for meta_pkg in meta.packages {
|
||||||
let cargo_metadata::Package { id, edition, name, manifest_path, .. } = meta_pkg;
|
let cargo_metadata::Package { id, edition, name, manifest_path, .. } = meta_pkg;
|
||||||
let is_member = ws_members.contains(&id);
|
let is_member = ws_members.contains(&id);
|
||||||
let edition = edition.parse::<Edition>()?;
|
let edition = edition
|
||||||
|
.parse::<Edition>()
|
||||||
|
.with_context(|| format!("Failed to parse edition {}", edition))?;
|
||||||
let pkg = packages.alloc(PackageData {
|
let pkg = packages.alloc(PackageData {
|
||||||
name,
|
name,
|
||||||
manifest: manifest_path,
|
manifest: manifest_path,
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
process::Command,
|
process::Command,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use anyhow::{bail, Context, Result};
|
||||||
use ra_cfg::CfgOptions;
|
use ra_cfg::CfgOptions;
|
||||||
use ra_db::{CrateGraph, CrateId, CrateName, Edition, Env, FileId};
|
use ra_db::{CrateGraph, CrateId, CrateName, Edition, Env, FileId};
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
@ -23,8 +24,6 @@
|
|||||||
sysroot::Sysroot,
|
sysroot::Sysroot,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub type Result<T> = ::std::result::Result<T, Box<dyn Error + Send + Sync>>;
|
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
|
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
|
||||||
pub struct CargoTomlNotFoundError(pub PathBuf);
|
pub struct CargoTomlNotFoundError(pub PathBuf);
|
||||||
|
|
||||||
@ -81,15 +80,36 @@ pub fn discover_with_sysroot(
|
|||||||
) -> Result<ProjectWorkspace> {
|
) -> Result<ProjectWorkspace> {
|
||||||
match find_rust_project_json(path) {
|
match find_rust_project_json(path) {
|
||||||
Some(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);
|
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 => {
|
None => {
|
||||||
let cargo_toml = find_cargo_toml(path)?;
|
let cargo_toml = find_cargo_toml(path).with_context(|| {
|
||||||
let cargo = CargoWorkspace::from_cargo_metadata(&cargo_toml, cargo_features)?;
|
format!("Failed to find Cargo.toml for path {}", path.display())
|
||||||
let sysroot =
|
})?;
|
||||||
if with_sysroot { Sysroot::discover(&cargo_toml)? } else { Sysroot::default() };
|
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 })
|
Ok(ProjectWorkspace::Cargo { cargo, sysroot })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -403,11 +423,20 @@ pub fn get_rustc_cfg_options() -> CfgOptions {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match (|| -> Result<_> {
|
match (|| -> Result<String> {
|
||||||
// `cfg(test)` and `cfg(debug_assertion)` are handled outside, so we suppress them here.
|
// `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() {
|
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)?)
|
Ok(String::from_utf8(output.stdout)?)
|
||||||
})() {
|
})() {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
//! FIXME: write short doc here
|
//! FIXME: write short doc here
|
||||||
|
|
||||||
|
use anyhow::{anyhow, bail, Context, Result};
|
||||||
use std::{
|
use std::{
|
||||||
env,
|
env,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
@ -8,8 +9,6 @@
|
|||||||
|
|
||||||
use ra_arena::{impl_arena_id, Arena, RawId};
|
use ra_arena::{impl_arena_id, Arena, RawId};
|
||||||
|
|
||||||
use crate::Result;
|
|
||||||
|
|
||||||
#[derive(Default, Debug, Clone)]
|
#[derive(Default, Debug, Clone)]
|
||||||
pub struct Sysroot {
|
pub struct Sysroot {
|
||||||
crates: Arena<SysrootCrate, SysrootCrateData>,
|
crates: Arena<SysrootCrate, SysrootCrateData>,
|
||||||
@ -51,7 +50,7 @@ pub fn discover(cargo_toml: &Path) -> Result<Sysroot> {
|
|||||||
let src = try_find_src_path(cargo_toml)?;
|
let src = try_find_src_path(cargo_toml)?;
|
||||||
|
|
||||||
if !src.exists() {
|
if !src.exists() {
|
||||||
Err(format!(
|
Err(anyhow!(
|
||||||
"can't load standard library from sysroot\n\
|
"can't load standard library from sysroot\n\
|
||||||
{}\n\
|
{}\n\
|
||||||
(discovered via `rustc --print sysroot`)\n\
|
(discovered via `rustc --print sysroot`)\n\
|
||||||
@ -100,9 +99,14 @@ fn try_find_src_path(cargo_toml: &Path) -> Result<PathBuf> {
|
|||||||
.current_dir(cargo_toml.parent().unwrap())
|
.current_dir(cargo_toml.parent().unwrap())
|
||||||
.args(&["--print", "sysroot"])
|
.args(&["--print", "sysroot"])
|
||||||
.output()
|
.output()
|
||||||
.map_err(|e| format!("rustc --print sysroot failed: {}", e))?;
|
.context("rustc --print sysroot failed")?;
|
||||||
if !rustc_output.status.success() {
|
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 stdout = String::from_utf8(rustc_output.stdout)?;
|
||||||
let sysroot_path = Path::new(stdout.trim());
|
let sysroot_path = Path::new(stdout.trim());
|
||||||
|
Loading…
Reference in New Issue
Block a user