Skip to content

Commit 9391b1c

Browse files
committed
fixes and improvements
1 parent f1b7349 commit 9391b1c

File tree

2 files changed

+50
-24
lines changed

2 files changed

+50
-24
lines changed

crates/ra_project_model/src/lib.rs

Lines changed: 49 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@ mod sysroot;
66

77
use std::{
88
error::Error,
9-
fs::File,
10-
fs::read_dir,
9+
fs::{read_dir, File, ReadDir},
1110
io::BufReader,
1211
path::{Path, PathBuf},
1312
process::Command,
@@ -26,15 +25,35 @@ pub use crate::{
2625
};
2726

2827
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
29-
pub struct CargoTomlNotFoundError(pub PathBuf);
28+
pub struct CargoTomlNoneFoundError(pub PathBuf);
3029

31-
impl std::fmt::Display for CargoTomlNotFoundError {
30+
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
31+
pub struct CargoTomlMultipleValidFoundError(pub Vec<PathBuf>);
32+
33+
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
34+
pub struct CargoTomlSearchFileSystemError(pub PathBuf, pub String);
35+
36+
impl std::fmt::Display for CargoTomlNoneFoundError {
3237
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3338
write!(fmt, "can't find Cargo.toml at {}", self.0.display())
3439
}
3540
}
3641

37-
impl Error for CargoTomlNotFoundError {}
42+
impl std::fmt::Display for CargoTomlMultipleValidFoundError {
43+
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
44+
write!(fmt, "found multiple valid Cargo.toml files {:?}", self.0)
45+
}
46+
}
47+
48+
impl std::fmt::Display for CargoTomlSearchFileSystemError {
49+
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
50+
write!(fmt, "a filesystem error occurred while searching for Cargo.toml: {}", self.1)
51+
}
52+
}
53+
54+
impl Error for CargoTomlNoneFoundError {}
55+
impl Error for CargoTomlMultipleValidFoundError {}
56+
impl Error for CargoTomlSearchFileSystemError {}
3857

3958
#[derive(Debug, Clone)]
4059
pub enum ProjectWorkspace {
@@ -407,7 +426,7 @@ fn find_rust_project_json(path: &Path) -> Option<PathBuf> {
407426
None
408427
}
409428

410-
fn find_cargo_toml_down_the_fs(path: &Path) -> Option<PathBuf> {
429+
fn find_cargo_toml_in_parent_dir(path: &Path) -> Option<PathBuf> {
411430
let mut curr = Some(path);
412431
while let Some(path) = curr {
413432
let candidate = path.join("Cargo.toml");
@@ -416,41 +435,48 @@ fn find_cargo_toml_down_the_fs(path: &Path) -> Option<PathBuf> {
416435
}
417436
curr = path.parent();
418437
}
419-
438+
420439
None
421440
}
422441

423-
fn find_cargo_toml_up_the_fs(path: &Path) -> Option<PathBuf> {
424-
let entities = match read_dir(path) {
425-
Ok(entities) => entities,
426-
Err(_) => return None
427-
};
428-
429-
// Only one level up to avoid cycles the easy way and stop a runaway scan with large projects
442+
fn find_cargo_toml_in_child_dir(entities: ReadDir) -> Vec<PathBuf> {
443+
// Only one level down to avoid cycles the easy way and stop a runaway scan with large projects
444+
let mut valid_canditates = vec![];
430445
for entity in entities.filter_map(Result::ok) {
431446
let candidate = entity.path().join("Cargo.toml");
432447
if candidate.exists() {
433-
return Some(candidate);
448+
valid_canditates.push(candidate)
434449
}
435450
}
436-
437-
None
451+
valid_canditates
438452
}
439453

440454
fn find_cargo_toml(path: &Path) -> Result<PathBuf> {
455+
let path_as_buf = path.to_path_buf();
456+
441457
if path.ends_with("Cargo.toml") {
442458
return Ok(path.to_path_buf());
443459
}
444460

445-
if let Some(p) = find_cargo_toml_down_the_fs(path) {
446-
return Ok(p)
461+
if let Some(p) = find_cargo_toml_in_parent_dir(path) {
462+
return Ok(p);
447463
}
448464

449-
if let Some(p) = find_cargo_toml_up_the_fs(path) {
450-
return Ok(p)
451-
}
465+
let entities = match read_dir(path.join("does_not_exist")) {
466+
Ok(entities) => {
467+
entities
468+
},
469+
Err(e) => {
470+
return Err(CargoTomlSearchFileSystemError(path_as_buf, e.to_string()).into())
471+
},
472+
};
452473

453-
Err(CargoTomlNotFoundError(path.to_path_buf()).into())
474+
let mut valid_canditates = find_cargo_toml_in_child_dir(entities);
475+
match valid_canditates.len() {
476+
1 => Ok(valid_canditates.remove(0)),
477+
0 => Err(CargoTomlNoneFoundError(path_as_buf).into()),
478+
_ => Err(CargoTomlMultipleValidFoundError(valid_canditates).into()),
479+
}
454480
}
455481

456482
pub fn get_rustc_cfg_options() -> CfgOptions {

crates/rust-analyzer/src/main_loop.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ pub fn main_loop(
115115
Ok(workspace) => loaded_workspaces.push(workspace),
116116
Err(e) => {
117117
log::error!("loading workspace failed: {:?}", e);
118-
if let Some(ra_project_model::CargoTomlNotFoundError(_)) = e.downcast_ref()
118+
if let Some(ra_project_model::CargoTomlNoneFoundError(_)) = e.downcast_ref()
119119
{
120120
if !feature_flags.get("notifications.cargo-toml-not-found") {
121121
continue;

0 commit comments

Comments
 (0)