fixes and improvements

This commit is contained in:
nmio 2020-02-27 21:52:10 +00:00
parent f1b7349e7a
commit 9391b1c8ce
2 changed files with 50 additions and 24 deletions

View file

@ -6,8 +6,7 @@ mod sysroot;
use std::{ use std::{
error::Error, error::Error,
fs::File, fs::{read_dir, File, ReadDir},
fs::read_dir,
io::BufReader, io::BufReader,
path::{Path, PathBuf}, path::{Path, PathBuf},
process::Command, process::Command,
@ -26,15 +25,35 @@ pub use crate::{
}; };
#[derive(Clone, PartialEq, Eq, Hash, Debug)] #[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub struct CargoTomlNotFoundError(pub PathBuf); pub struct CargoTomlNoneFoundError(pub PathBuf);
impl std::fmt::Display for CargoTomlNotFoundError { #[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub struct CargoTomlMultipleValidFoundError(pub Vec<PathBuf>);
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub struct CargoTomlSearchFileSystemError(pub PathBuf, pub String);
impl std::fmt::Display for CargoTomlNoneFoundError {
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(fmt, "can't find Cargo.toml at {}", self.0.display()) write!(fmt, "can't find Cargo.toml at {}", self.0.display())
} }
} }
impl Error for CargoTomlNotFoundError {} impl std::fmt::Display for CargoTomlMultipleValidFoundError {
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(fmt, "found multiple valid Cargo.toml files {:?}", self.0)
}
}
impl std::fmt::Display for CargoTomlSearchFileSystemError {
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(fmt, "a filesystem error occurred while searching for Cargo.toml: {}", self.1)
}
}
impl Error for CargoTomlNoneFoundError {}
impl Error for CargoTomlMultipleValidFoundError {}
impl Error for CargoTomlSearchFileSystemError {}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum ProjectWorkspace { pub enum ProjectWorkspace {
@ -407,7 +426,7 @@ fn find_rust_project_json(path: &Path) -> Option<PathBuf> {
None None
} }
fn find_cargo_toml_down_the_fs(path: &Path) -> Option<PathBuf> { fn find_cargo_toml_in_parent_dir(path: &Path) -> Option<PathBuf> {
let mut curr = Some(path); let mut curr = Some(path);
while let Some(path) = curr { while let Some(path) = curr {
let candidate = path.join("Cargo.toml"); let candidate = path.join("Cargo.toml");
@ -416,41 +435,48 @@ fn find_cargo_toml_down_the_fs(path: &Path) -> Option<PathBuf> {
} }
curr = path.parent(); curr = path.parent();
} }
None None
} }
fn find_cargo_toml_up_the_fs(path: &Path) -> Option<PathBuf> { fn find_cargo_toml_in_child_dir(entities: ReadDir) -> Vec<PathBuf> {
let entities = match read_dir(path) { // Only one level down to avoid cycles the easy way and stop a runaway scan with large projects
Ok(entities) => entities, let mut valid_canditates = vec![];
Err(_) => return None
};
// Only one level up to avoid cycles the easy way and stop a runaway scan with large projects
for entity in entities.filter_map(Result::ok) { for entity in entities.filter_map(Result::ok) {
let candidate = entity.path().join("Cargo.toml"); let candidate = entity.path().join("Cargo.toml");
if candidate.exists() { if candidate.exists() {
return Some(candidate); valid_canditates.push(candidate)
} }
} }
valid_canditates
None
} }
fn find_cargo_toml(path: &Path) -> Result<PathBuf> { fn find_cargo_toml(path: &Path) -> Result<PathBuf> {
let path_as_buf = path.to_path_buf();
if path.ends_with("Cargo.toml") { if path.ends_with("Cargo.toml") {
return Ok(path.to_path_buf()); return Ok(path.to_path_buf());
} }
if let Some(p) = find_cargo_toml_down_the_fs(path) { if let Some(p) = find_cargo_toml_in_parent_dir(path) {
return Ok(p) return Ok(p);
} }
if let Some(p) = find_cargo_toml_up_the_fs(path) { let entities = match read_dir(path.join("does_not_exist")) {
return Ok(p) Ok(entities) => {
} entities
},
Err(e) => {
return Err(CargoTomlSearchFileSystemError(path_as_buf, e.to_string()).into())
},
};
Err(CargoTomlNotFoundError(path.to_path_buf()).into()) let mut valid_canditates = find_cargo_toml_in_child_dir(entities);
match valid_canditates.len() {
1 => Ok(valid_canditates.remove(0)),
0 => Err(CargoTomlNoneFoundError(path_as_buf).into()),
_ => Err(CargoTomlMultipleValidFoundError(valid_canditates).into()),
}
} }
pub fn get_rustc_cfg_options() -> CfgOptions { pub fn get_rustc_cfg_options() -> CfgOptions {

View file

@ -115,7 +115,7 @@ pub fn main_loop(
Ok(workspace) => loaded_workspaces.push(workspace), Ok(workspace) => loaded_workspaces.push(workspace),
Err(e) => { Err(e) => {
log::error!("loading workspace failed: {:?}", e); log::error!("loading workspace failed: {:?}", e);
if let Some(ra_project_model::CargoTomlNotFoundError(_)) = e.downcast_ref() if let Some(ra_project_model::CargoTomlNoneFoundError(_)) = e.downcast_ref()
{ {
if !feature_flags.get("notifications.cargo-toml-not-found") { if !feature_flags.get("notifications.cargo-toml-not-found") {
continue; continue;