aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_db/src/lib.rs5
-rw-r--r--crates/ra_project_model/src/cargo_workspace.rs6
-rw-r--r--crates/ra_project_model/src/lib.rs87
-rw-r--r--crates/ra_project_model/src/sysroot.rs21
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
11pub use crate::{ 11pub 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};
15pub use relative_path::{RelativePath, RelativePathBuf}; 18pub use relative_path::{RelativePath, RelativePathBuf};
16pub use salsa; 19pub 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;
8use rustc_hash::FxHashMap; 8use rustc_hash::FxHashMap;
9use serde::Deserialize; 9use serde::Deserialize;
10 10
11use crate::Result; 11use 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;
5mod sysroot; 5mod sysroot;
6 6
7use std::{ 7use 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
15use ra_cfg::CfgOptions; 15use ra_cfg::CfgOptions;
16use ra_db::{CrateGraph, CrateId, Edition, Env, FileId}; 16use ra_db::{CrateGraph, CrateId, Edition, Env, FileId, ParseEditionError};
17use rustc_hash::FxHashMap; 17use rustc_hash::FxHashMap;
18use serde_json::from_reader; 18use 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)]
27pub type Result<T> = ::std::result::Result<T, Box<dyn Error + Send + Sync>>; 27pub 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
40impl 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
64impl std::error::Error for WorkspaceError {}
65
66impl From<ParseEditionError> for WorkspaceError {
67 fn from(err: ParseEditionError) -> Self {
68 Self::ParseEditionError(err.into())
69 }
70}
71
72impl 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)]
30pub enum ProjectWorkspace { 79pub enum ProjectWorkspace {
@@ -60,7 +109,10 @@ impl PackageRoot {
60} 109}
61 110
62impl ProjectWorkspace { 111impl 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
353fn find_cargo_toml(path: &Path) -> Result<PathBuf> { 409fn 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
368pub fn get_rustc_cfg_options() -> CfgOptions { 424pub 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
9use ra_arena::{impl_arena_id, Arena, RawId}; 9use ra_arena::{impl_arena_id, Arena, RawId};
10 10
11use crate::Result; 11use crate::WorkspaceError;
12 12
13#[derive(Default, Debug, Clone)] 13#[derive(Default, Debug, Clone)]
14pub struct Sysroot { 14pub 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
93fn try_find_src_path(cargo_toml: &Path) -> Result<PathBuf> { 88fn 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}