FIX: Better error messages when importing.

If the path or directory doesn't exist show the invalid path in the
error message.

Fixes #37
This commit is contained in:
Jeremy Wall 2019-03-19 19:47:21 -05:00
parent 8a1661982a
commit f86d9b8ec6
3 changed files with 63 additions and 16 deletions

View File

@ -569,3 +569,14 @@ fn test_select_missed_case_boolean_no_default_compile_failure() {
], ],
) )
} }
#[test]
fn test_bad_import_path_compile_failure() {
assert_build_failure(
"let bad = import \"no/such/path.ucg\";",
vec![
Regex::new(r"OSError: Path not found").unwrap(),
Regex::new(r"at <eval> line: 1, column: 18").unwrap(),
],
)
}

View File

@ -213,7 +213,7 @@ impl<'a> FileBuilder<'a> {
pub fn build<P: Into<PathBuf>>(&mut self, file: P) -> BuildResult { pub fn build<P: Into<PathBuf>>(&mut self, file: P) -> BuildResult {
let file = file.into(); let file = file.into();
self.working_dir = file.parent().unwrap().to_path_buf(); self.working_dir = file.parent().unwrap().to_path_buf();
let mut f = File::open(&file)?; let mut f = self.open_file(&Position::new(0, 0, 0), &file)?;
let mut s = String::new(); let mut s = String::new();
f.read_to_string(&mut s)?; f.read_to_string(&mut s)?;
let input = OffsetStrIter::new(&s).with_src_file(file.clone()); let input = OffsetStrIter::new(&s).with_src_file(file.clone());
@ -389,7 +389,15 @@ impl<'a> FileBuilder<'a> {
} else { } else {
normalized = path; normalized = path;
} }
Ok(normalized.canonicalize()?) match normalized.canonicalize() {
Ok(p) => Ok(p),
Err(e) => Err(error::BuildError::new(
format!("Path not found {}", normalized.to_string_lossy()),
error::ErrorType::OSError,
)
.wrap_cause(Box::new(e))
.to_boxed()),
}
} }
fn eval_import(&self, def: &ImportDef) -> Result<Rc<Val>, Box<dyn Error>> { fn eval_import(&self, def: &ImportDef) -> Result<Rc<Val>, Box<dyn Error>> {
@ -423,7 +431,18 @@ impl<'a> FileBuilder<'a> {
} }
} }
// Try a relative path first. // Try a relative path first.
let normalized = self.find_file(&def.path.fragment, true)?; let normalized = match self.find_file(&def.path.fragment, true) {
Ok(p) => p,
Err(e) => {
return Err(error::BuildError::with_pos(
"No Such Import",
error::ErrorType::ImportError,
def.path.pos.clone(),
)
.wrap_cause(e)
.to_boxed());
}
};
if self.detect_import_cycle(normalized.to_string_lossy().as_ref()) { if self.detect_import_cycle(normalized.to_string_lossy().as_ref()) {
return Err(error::BuildError::with_pos( return Err(error::BuildError::with_pos(
format!( format!(
@ -444,8 +463,18 @@ impl<'a> FileBuilder<'a> {
Some(v) => v.clone(), Some(v) => v.clone(),
None => { None => {
let mut b = self.clone_builder(); let mut b = self.clone_builder();
b.build(&normalized)?; match b.build(&normalized) {
b.get_outputs_as_val() Ok(_) => b.get_outputs_as_val(),
Err(e) => {
return Err(error::BuildError::with_pos(
"Import failed",
error::ErrorType::ImportError,
def.pos.clone(),
)
.wrap_cause(e)
.to_boxed());
}
}
} }
}; };
let mut mut_assets_cache = self.assets.borrow_mut(); let mut mut_assets_cache = self.assets.borrow_mut();
@ -1679,6 +1708,19 @@ impl<'a> FileBuilder<'a> {
Ok(ok) Ok(ok)
} }
fn open_file<P: Into<PathBuf>>(&self, pos: &Position, path: P) -> Result<File, Box<dyn Error>> {
let path = path.into();
match File::open(&path) {
Ok(f) => Ok(f),
Err(e) => Err(error::BuildError::with_pos(
format!("Error opening file {} {}", path.to_string_lossy(), e),
error::ErrorType::TypeFail,
pos.clone(),
)
.to_boxed()),
}
}
fn get_file_as_string(&self, pos: &Position, path: &str) -> Result<String, Box<dyn Error>> { fn get_file_as_string(&self, pos: &Position, path: &str) -> Result<String, Box<dyn Error>> {
let normalized = match self.find_file(path, false) { let normalized = match self.find_file(path, false) {
Ok(p) => p, Ok(p) => p,
@ -1691,17 +1733,7 @@ impl<'a> FileBuilder<'a> {
.to_boxed()); .to_boxed());
} }
}; };
let mut f = match File::open(&normalized) { let mut f = self.open_file(pos, normalized)?;
Ok(f) => f,
Err(e) => {
return Err(error::BuildError::with_pos(
format!("Error opening file {} {}", normalized.to_string_lossy(), e),
error::ErrorType::TypeFail,
pos.clone(),
)
.to_boxed());
}
};
let mut contents = String::new(); let mut contents = String::new();
f.read_to_string(&mut contents)?; f.read_to_string(&mut contents)?;
Ok(contents) Ok(contents)

View File

@ -31,10 +31,12 @@ pub enum ErrorType {
BadArgLen, BadArgLen,
FormatError, FormatError,
IncludeError, IncludeError,
ImportError,
ReservedWordError, ReservedWordError,
// Parsing Errors // Parsing Errors
ParseError, ParseError,
AssertError, AssertError,
OSError,
// User Defined Declarative Errors // User Defined Declarative Errors
UserDefined, UserDefined,
} }
@ -49,9 +51,11 @@ impl fmt::Display for ErrorType {
&ErrorType::BadArgLen => "BadArgLen", &ErrorType::BadArgLen => "BadArgLen",
&ErrorType::FormatError => "FormatError", &ErrorType::FormatError => "FormatError",
&ErrorType::IncludeError => "IncludeError", &ErrorType::IncludeError => "IncludeError",
&ErrorType::ImportError => "ImportError",
&ErrorType::ReservedWordError => "ReservedWordError", &ErrorType::ReservedWordError => "ReservedWordError",
&ErrorType::ParseError => "ParseError", &ErrorType::ParseError => "ParseError",
&ErrorType::AssertError => "AssertError", &ErrorType::AssertError => "AssertError",
&ErrorType::OSError => "OSError",
&ErrorType::UserDefined => "UserDefined", &ErrorType::UserDefined => "UserDefined",
}; };
w.write_str(name) w.write_str(name)