aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_project_model/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_project_model/src')
-rw-r--r--crates/ra_project_model/src/cargo_workspace.rs6
-rw-r--r--crates/ra_project_model/src/lib.rs52
-rw-r--r--crates/ra_project_model/src/sysroot.rs21
-rw-r--r--crates/ra_project_model/src/workspace_error.rs57
4 files changed, 45 insertions, 91 deletions
diff --git a/crates/ra_project_model/src/cargo_workspace.rs b/crates/ra_project_model/src/cargo_workspace.rs
index 446ccfda0..1b3c246c7 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::WorkspaceError; 11use crate::Result;
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, WorkspaceError> { 159 ) -> Result<CargoWorkspace> {
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| WorkspaceError::CargoMetadataFailed(e))?; 174 let meta = meta.exec().map_err(|e| format!("cargo metadata failed: {}", 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 2aa9270c8..e36338860 100644
--- a/crates/ra_project_model/src/lib.rs
+++ b/crates/ra_project_model/src/lib.rs
@@ -3,9 +3,9 @@
3mod cargo_workspace; 3mod cargo_workspace;
4mod json_project; 4mod json_project;
5mod sysroot; 5mod sysroot;
6mod workspace_error;
7 6
8use std::{ 7use std::{
8 error::Error,
9 fs::File, 9 fs::File,
10 io::BufReader, 10 io::BufReader,
11 path::{Path, PathBuf}, 11 path::{Path, PathBuf},
@@ -21,9 +21,27 @@ pub use crate::{
21 cargo_workspace::{CargoFeatures, CargoWorkspace, Package, Target, TargetKind}, 21 cargo_workspace::{CargoFeatures, CargoWorkspace, Package, Target, TargetKind},
22 json_project::JsonProject, 22 json_project::JsonProject,
23 sysroot::Sysroot, 23 sysroot::Sysroot,
24 workspace_error::WorkspaceError,
25}; 24};
26 25
26pub type Result<T> = ::std::result::Result<T, Box<dyn Error + Send + Sync>>;
27
28#[derive(Clone, PartialEq, Eq, Hash)]
29pub struct CargoTomlNotFoundError(pub PathBuf);
30
31impl std::fmt::Display for CargoTomlNotFoundError {
32 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
33 write!(fmt, "can't find Cargo.toml at {}", self.0.display())
34 }
35}
36
37impl std::fmt::Debug for CargoTomlNotFoundError {
38 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
39 write!(fmt, "can't find Cargo.toml at {}", self.0.display())
40 }
41}
42
43impl Error for CargoTomlNotFoundError {}
44
27#[derive(Debug, Clone)] 45#[derive(Debug, Clone)]
28pub enum ProjectWorkspace { 46pub enum ProjectWorkspace {
29 /// Project workspace was discovered by running `cargo metadata` and `rustc --print sysroot`. 47 /// Project workspace was discovered by running `cargo metadata` and `rustc --print sysroot`.
@@ -58,10 +76,7 @@ impl PackageRoot {
58} 76}
59 77
60impl ProjectWorkspace { 78impl ProjectWorkspace {
61 pub fn discover( 79 pub fn discover(path: &Path, cargo_features: &CargoFeatures) -> Result<ProjectWorkspace> {
62 path: &Path,
63 cargo_features: &CargoFeatures,
64 ) -> Result<ProjectWorkspace, WorkspaceError> {
65 ProjectWorkspace::discover_with_sysroot(path, true, cargo_features) 80 ProjectWorkspace::discover_with_sysroot(path, true, cargo_features)
66 } 81 }
67 82
@@ -69,16 +84,12 @@ impl ProjectWorkspace {
69 path: &Path, 84 path: &Path,
70 with_sysroot: bool, 85 with_sysroot: bool,
71 cargo_features: &CargoFeatures, 86 cargo_features: &CargoFeatures,
72 ) -> Result<ProjectWorkspace, WorkspaceError> { 87 ) -> Result<ProjectWorkspace> {
73 match find_rust_project_json(path) { 88 match find_rust_project_json(path) {
74 Some(json_path) => { 89 Some(json_path) => {
75 let file = 90 let file = File::open(json_path)?;
76 File::open(json_path).map_err(|err| WorkspaceError::OpenWorkspaceError(err))?;
77 let reader = BufReader::new(file); 91 let reader = BufReader::new(file);
78 Ok(ProjectWorkspace::Json { 92 Ok(ProjectWorkspace::Json { project: from_reader(reader)? })
79 project: from_reader(reader)
80 .map_err(|err| WorkspaceError::ReadWorkspaceError(err))?,
81 })
82 } 93 }
83 None => { 94 None => {
84 let cargo_toml = find_cargo_toml(path)?; 95 let cargo_toml = find_cargo_toml(path)?;
@@ -355,7 +366,7 @@ fn find_rust_project_json(path: &Path) -> Option<PathBuf> {
355 None 366 None
356} 367}
357 368
358fn find_cargo_toml(path: &Path) -> Result<PathBuf, WorkspaceError> { 369fn find_cargo_toml(path: &Path) -> Result<PathBuf> {
359 if path.ends_with("Cargo.toml") { 370 if path.ends_with("Cargo.toml") {
360 return Ok(path.to_path_buf()); 371 return Ok(path.to_path_buf());
361 } 372 }
@@ -367,7 +378,7 @@ fn find_cargo_toml(path: &Path) -> Result<PathBuf, WorkspaceError> {
367 } 378 }
368 curr = path.parent(); 379 curr = path.parent();
369 } 380 }
370 Err(WorkspaceError::CargoTomlNotFound(path.to_path_buf())) 381 Err(Box::new(CargoTomlNotFoundError(path.to_path_buf())))
371} 382}
372 383
373pub fn get_rustc_cfg_options() -> CfgOptions { 384pub fn get_rustc_cfg_options() -> CfgOptions {
@@ -381,16 +392,13 @@ pub fn get_rustc_cfg_options() -> CfgOptions {
381 } 392 }
382 } 393 }
383 394
384 match (|| -> Result<_, WorkspaceError> { 395 match (|| -> Result<_> {
385 // `cfg(test)` and `cfg(debug_assertion)` are handled outside, so we suppress them here. 396 // `cfg(test)` and `cfg(debug_assertion)` are handled outside, so we suppress them here.
386 let output = Command::new("rustc") 397 let output = Command::new("rustc").args(&["--print", "cfg", "-O"]).output()?;
387 .args(&["--print", "cfg", "-O"])
388 .output()
389 .map_err(|err| WorkspaceError::RustcError(err))?;
390 if !output.status.success() { 398 if !output.status.success() {
391 Err(WorkspaceError::RustcCfgError)?; 399 Err("failed to get rustc cfgs")?;
392 } 400 }
393 Ok(String::from_utf8(output.stdout).map_err(|err| WorkspaceError::RustcOutputError(err))?) 401 Ok(String::from_utf8(output.stdout)?)
394 })() { 402 })() {
395 Ok(rustc_cfgs) => { 403 Ok(rustc_cfgs) => {
396 for line in rustc_cfgs.lines() { 404 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 24c3f47a2..10ca391b6 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::WorkspaceError; 11use crate::Result;
12 12
13#[derive(Default, Debug, Clone)] 13#[derive(Default, Debug, Clone)]
14pub struct Sysroot { 14pub struct Sysroot {
@@ -47,11 +47,16 @@ 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, WorkspaceError> { 50 pub fn discover(cargo_toml: &Path) -> Result<Sysroot> {
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 return Err(WorkspaceError::NoStdLib(src)); 54 Err(format!(
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 ))?;
55 } 60 }
56 61
57 let mut sysroot = Sysroot { crates: Arena::default() }; 62 let mut sysroot = Sysroot { crates: Arena::default() };
@@ -85,7 +90,7 @@ impl Sysroot {
85 } 90 }
86} 91}
87 92
88fn try_find_src_path(cargo_toml: &Path) -> Result<PathBuf, WorkspaceError> { 93fn try_find_src_path(cargo_toml: &Path) -> Result<PathBuf> {
89 if let Ok(path) = env::var("RUST_SRC_PATH") { 94 if let Ok(path) = env::var("RUST_SRC_PATH") {
90 return Ok(path.into()); 95 return Ok(path.into());
91 } 96 }
@@ -93,13 +98,11 @@ fn try_find_src_path(cargo_toml: &Path) -> Result<PathBuf, WorkspaceError> {
93 let rustc_output = Command::new("rustc") 98 let rustc_output = Command::new("rustc")
94 .current_dir(cargo_toml.parent().unwrap()) 99 .current_dir(cargo_toml.parent().unwrap())
95 .args(&["--print", "sysroot"]) 100 .args(&["--print", "sysroot"])
96 .output() 101 .output()?;
97 .map_err(|err| WorkspaceError::RustcError(err))?;
98 if !rustc_output.status.success() { 102 if !rustc_output.status.success() {
99 Err(WorkspaceError::SysrootNotFound)?; 103 Err("failed to locate sysroot")?;
100 } 104 }
101 let stdout = String::from_utf8(rustc_output.stdout) 105 let stdout = String::from_utf8(rustc_output.stdout)?;
102 .map_err(|err| WorkspaceError::RustcOutputError(err))?;
103 let sysroot_path = Path::new(stdout.trim()); 106 let sysroot_path = Path::new(stdout.trim());
104 Ok(sysroot_path.join("lib/rustlib/src/rust/src")) 107 Ok(sysroot_path.join("lib/rustlib/src/rust/src"))
105} 108}
diff --git a/crates/ra_project_model/src/workspace_error.rs b/crates/ra_project_model/src/workspace_error.rs
deleted file mode 100644
index 5f7384968..000000000
--- a/crates/ra_project_model/src/workspace_error.rs
+++ /dev/null
@@ -1,57 +0,0 @@
1//! Workspace-related errors
2
3use std::{error::Error, fmt, io, path::PathBuf, string::FromUtf8Error};
4
5use ra_db::ParseEditionError;
6
7#[derive(Debug)]
8pub enum WorkspaceError {
9 CargoMetadataFailed(cargo_metadata::Error),
10 CargoTomlNotFound(PathBuf),
11 NoStdLib(PathBuf),
12 OpenWorkspaceError(io::Error),
13 ParseEditionError(ParseEditionError),
14 ReadWorkspaceError(serde_json::Error),
15 RustcCfgError,
16 RustcError(io::Error),
17 RustcOutputError(FromUtf8Error),
18 SysrootNotFound,
19}
20
21impl fmt::Display for WorkspaceError {
22 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23 match self {
24 Self::OpenWorkspaceError(err) | Self::RustcError(err) => write!(f, "{}", err),
25 Self::ParseEditionError(err) => write!(f, "{}", err),
26 Self::ReadWorkspaceError(err) => write!(f, "{}", err),
27 Self::RustcOutputError(err) => write!(f, "{}", err),
28 Self::CargoMetadataFailed(err) => write!(f, "cargo metadata failed: {}", err),
29 Self::RustcCfgError => write!(f, "failed to get rustc cfgs"),
30 Self::SysrootNotFound => write!(f, "failed to locate sysroot"),
31 Self::CargoTomlNotFound(path) => {
32 write!(f, "can't find Cargo.toml at {}", path.display())
33 }
34 Self::NoStdLib(sysroot) => write!(
35 f,
36 "can't load standard library from sysroot\n\
37 {:?}\n\
38 try running `rustup component add rust-src` or set `RUST_SRC_PATH`",
39 sysroot,
40 ),
41 }
42 }
43}
44
45impl From<ParseEditionError> for WorkspaceError {
46 fn from(err: ParseEditionError) -> Self {
47 Self::ParseEditionError(err.into())
48 }
49}
50
51impl From<cargo_metadata::Error> for WorkspaceError {
52 fn from(err: cargo_metadata::Error) -> Self {
53 Self::CargoMetadataFailed(err.into())
54 }
55}
56
57impl Error for WorkspaceError {}