mirror of
https://github.com/roc-lang/roc.git
synced 2025-07-24 06:55:15 +00:00
make file loading errors that happen late in compilation still fatal
This commit is contained in:
parent
21d063da26
commit
8f4945f286
9 changed files with 189 additions and 114 deletions
|
@ -730,6 +730,16 @@ pub fn build(
|
||||||
Ok(problems.exit_code())
|
Ok(problems.exit_code())
|
||||||
}
|
}
|
||||||
BuildAndRun => {
|
BuildAndRun => {
|
||||||
|
if problems.fatally_errored {
|
||||||
|
problems.print_to_stdout(total_time);
|
||||||
|
println!(
|
||||||
|
".\n\nCannot run program due to fatal error…\n\n\x1B[36m{}\x1B[39m",
|
||||||
|
"─".repeat(80)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Return a nonzero exit code due to falta problem
|
||||||
|
return Ok(problems.exit_code());
|
||||||
|
}
|
||||||
if problems.errors > 0 || problems.warnings > 0 {
|
if problems.errors > 0 || problems.warnings > 0 {
|
||||||
problems.print_to_stdout(total_time);
|
problems.print_to_stdout(total_time);
|
||||||
println!(
|
println!(
|
||||||
|
|
|
@ -735,28 +735,54 @@ pub fn canonicalize_expr<'a>(
|
||||||
|
|
||||||
ast::Expr::Str(literal) => flatten_str_literal(env, var_store, scope, literal),
|
ast::Expr::Str(literal) => flatten_str_literal(env, var_store, scope, literal),
|
||||||
|
|
||||||
ast::Expr::IngestedFile(file_path, type_ann) => {
|
ast::Expr::IngestedFile(file_path, type_ann) => match File::open(file_path) {
|
||||||
let mut file = File::open(file_path).expect("file should exist due to earlier check. In the rare case the file got deleted, we should create a can error here too.");
|
Ok(mut file) => {
|
||||||
let mut bytes = vec![];
|
let mut bytes = vec![];
|
||||||
match file.read_to_end(&mut bytes) {
|
match file.read_to_end(&mut bytes) {
|
||||||
Ok(_) => (
|
Ok(_) => (
|
||||||
Expr::IngestedFile(
|
Expr::IngestedFile(
|
||||||
bytes,
|
bytes,
|
||||||
annotation::canonicalize_annotation(
|
annotation::canonicalize_annotation(
|
||||||
env,
|
env,
|
||||||
scope,
|
scope,
|
||||||
&type_ann.value,
|
&type_ann.value,
|
||||||
region,
|
region,
|
||||||
var_store,
|
var_store,
|
||||||
&VecMap::default(),
|
&VecMap::default(),
|
||||||
annotation::AnnotationFor::Value,
|
annotation::AnnotationFor::Value,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
|
Output::default(),
|
||||||
),
|
),
|
||||||
Output::default(),
|
Err(e) => {
|
||||||
),
|
env.problems.push(Problem::FileProblem {
|
||||||
Err(e) => todo!("failed to load file emit can error: {}", e),
|
filename: file_path.to_path_buf(),
|
||||||
|
error: e.kind(),
|
||||||
|
});
|
||||||
|
|
||||||
|
// This will not manifest as a real runtime error and is just returned to have a value here.
|
||||||
|
// The pushed FileProblem will be fatal to compilation.
|
||||||
|
(
|
||||||
|
Expr::RuntimeError(roc_problem::can::RuntimeError::NoImplementation),
|
||||||
|
Output::default(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
Err(e) => {
|
||||||
|
env.problems.push(Problem::FileProblem {
|
||||||
|
filename: file_path.to_path_buf(),
|
||||||
|
error: e.kind(),
|
||||||
|
});
|
||||||
|
|
||||||
|
// This will not manifest as a real runtime error and is just returned to have a value here.
|
||||||
|
// The pushed FileProblem will be fatal to compilation.
|
||||||
|
(
|
||||||
|
Expr::RuntimeError(roc_problem::can::RuntimeError::NoImplementation),
|
||||||
|
Output::default(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
ast::Expr::SingleQuote(string) => {
|
ast::Expr::SingleQuote(string) => {
|
||||||
let mut it = string.chars().peekable();
|
let mut it = string.chars().peekable();
|
||||||
|
|
|
@ -51,7 +51,7 @@ use roc_parse::module::module_defs;
|
||||||
use roc_parse::parser::{FileError, Parser, SourceError, SyntaxError};
|
use roc_parse::parser::{FileError, Parser, SourceError, SyntaxError};
|
||||||
use roc_problem::Severity;
|
use roc_problem::Severity;
|
||||||
use roc_region::all::{LineInfo, Loc, Region};
|
use roc_region::all::{LineInfo, Loc, Region};
|
||||||
use roc_reporting::report::{Annotation, Palette, RenderTarget};
|
use roc_reporting::report::{to_file_problem_report_string, Palette, RenderTarget};
|
||||||
use roc_solve::module::{extract_module_owned_implementations, Solved, SolvedModule};
|
use roc_solve::module::{extract_module_owned_implementations, Solved, SolvedModule};
|
||||||
use roc_solve_problem::TypeError;
|
use roc_solve_problem::TypeError;
|
||||||
use roc_target::TargetInfo;
|
use roc_target::TargetInfo;
|
||||||
|
@ -1791,7 +1791,7 @@ fn state_thread_step<'a>(
|
||||||
Ok(ControlFlow::Break(LoadResult::Monomorphized(monomorphized)))
|
Ok(ControlFlow::Break(LoadResult::Monomorphized(monomorphized)))
|
||||||
}
|
}
|
||||||
Msg::FailedToReadFile { filename, error } => {
|
Msg::FailedToReadFile { filename, error } => {
|
||||||
let buf = to_file_problem_report(&filename, error);
|
let buf = to_file_problem_report_string(&filename, error);
|
||||||
Err(LoadingProblem::FormattedReport(buf))
|
Err(LoadingProblem::FormattedReport(buf))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1939,7 +1939,9 @@ pub fn report_loading_problem(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
LoadingProblem::FormattedReport(report) => report,
|
LoadingProblem::FormattedReport(report) => report,
|
||||||
LoadingProblem::FileProblem { filename, error } => to_file_problem_report(&filename, error),
|
LoadingProblem::FileProblem { filename, error } => {
|
||||||
|
to_file_problem_report_string(&filename, error)
|
||||||
|
}
|
||||||
err => todo!("Loading error: {:?}", err),
|
err => todo!("Loading error: {:?}", err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5688,15 +5690,19 @@ fn value_def_from_imports<'a>(
|
||||||
let value = match entry.value {
|
let value = match entry.value {
|
||||||
Module(_, _) => None,
|
Module(_, _) => None,
|
||||||
Package(_, _, _) => None,
|
Package(_, _, _) => None,
|
||||||
IngestedFile(file_name, typed_ident) => {
|
IngestedFile(ingested_path, typed_ident) => {
|
||||||
let file_path = if let StrLiteral::PlainLine(filename) = file_name {
|
let file_path = if let StrLiteral::PlainLine(ingested_path) = ingested_path {
|
||||||
let file_path = header_path.to_path_buf().with_file_name(filename);
|
let mut file_path = header_path.to_path_buf();
|
||||||
|
// Remove the header file name and push the new path.
|
||||||
|
file_path.pop();
|
||||||
|
file_path.push(ingested_path);
|
||||||
|
|
||||||
match fs::metadata(&file_path) {
|
match fs::metadata(&file_path) {
|
||||||
Ok(md) => {
|
Ok(md) => {
|
||||||
if !md.is_file() {
|
if md.is_dir() {
|
||||||
// TODO: is there a better loading problem to return when not a file.
|
|
||||||
return Err(LoadingProblem::FileProblem {
|
return Err(LoadingProblem::FileProblem {
|
||||||
filename: file_path,
|
filename: file_path,
|
||||||
|
// TODO: change to IsADirectory once that is stable.
|
||||||
error: io::ErrorKind::InvalidInput,
|
error: io::ErrorKind::InvalidInput,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -6551,87 +6557,6 @@ fn run_task<'a>(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_file_problem_report(filename: &Path, error: io::ErrorKind) -> String {
|
|
||||||
use roc_reporting::report::{Report, RocDocAllocator, DEFAULT_PALETTE};
|
|
||||||
use ven_pretty::DocAllocator;
|
|
||||||
|
|
||||||
let src_lines: Vec<&str> = Vec::new();
|
|
||||||
|
|
||||||
let mut module_ids = ModuleIds::default();
|
|
||||||
|
|
||||||
let module_id = module_ids.get_or_insert(&"find module name somehow?".into());
|
|
||||||
|
|
||||||
let interns = Interns::default();
|
|
||||||
|
|
||||||
// Report parsing and canonicalization problems
|
|
||||||
let alloc = RocDocAllocator::new(&src_lines, module_id, &interns);
|
|
||||||
|
|
||||||
let report = match error {
|
|
||||||
io::ErrorKind::NotFound => {
|
|
||||||
let doc = alloc.stack([
|
|
||||||
alloc.reflow(r"I am looking for this file, but it's not there:"),
|
|
||||||
alloc
|
|
||||||
.parser_suggestion(filename.to_str().unwrap())
|
|
||||||
.indent(4),
|
|
||||||
alloc.concat([
|
|
||||||
alloc.reflow(r"Is the file supposed to be there? "),
|
|
||||||
alloc.reflow("Maybe there is a typo in the file name?"),
|
|
||||||
]),
|
|
||||||
]);
|
|
||||||
|
|
||||||
Report {
|
|
||||||
filename: "UNKNOWN.roc".into(),
|
|
||||||
doc,
|
|
||||||
title: "FILE NOT FOUND".to_string(),
|
|
||||||
severity: Severity::RuntimeError,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
io::ErrorKind::PermissionDenied => {
|
|
||||||
let doc = alloc.stack([
|
|
||||||
alloc.reflow(r"I don't have the required permissions to read this file:"),
|
|
||||||
alloc
|
|
||||||
.parser_suggestion(filename.to_str().unwrap())
|
|
||||||
.indent(4),
|
|
||||||
alloc
|
|
||||||
.concat([alloc.reflow(r"Is it the right file? Maybe change its permissions?")]),
|
|
||||||
]);
|
|
||||||
|
|
||||||
Report {
|
|
||||||
filename: "UNKNOWN.roc".into(),
|
|
||||||
doc,
|
|
||||||
title: "FILE PERMISSION DENIED".to_string(),
|
|
||||||
severity: Severity::RuntimeError,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
let error = std::io::Error::from(error);
|
|
||||||
let formatted = format!("{}", error);
|
|
||||||
let doc = alloc.stack([
|
|
||||||
alloc.reflow(r"I tried to read this file:"),
|
|
||||||
alloc
|
|
||||||
.text(filename.to_str().unwrap())
|
|
||||||
.annotate(Annotation::Error)
|
|
||||||
.indent(4),
|
|
||||||
alloc.reflow(r"But ran into:"),
|
|
||||||
alloc.text(formatted).annotate(Annotation::Error).indent(4),
|
|
||||||
]);
|
|
||||||
|
|
||||||
Report {
|
|
||||||
filename: "UNKNOWN.roc".into(),
|
|
||||||
doc,
|
|
||||||
title: "FILE PROBLEM".to_string(),
|
|
||||||
severity: Severity::RuntimeError,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut buf = String::new();
|
|
||||||
let palette = DEFAULT_PALETTE;
|
|
||||||
report.render_color_terminal(&mut buf, &alloc, &palette);
|
|
||||||
|
|
||||||
buf
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_import_cycle_report(
|
fn to_import_cycle_report(
|
||||||
module_ids: ModuleIds,
|
module_ids: ModuleIds,
|
||||||
all_ident_ids: IdentIdsByModule,
|
all_ident_ids: IdentIdsByModule,
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
use std::io;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use roc_collections::all::MutSet;
|
use roc_collections::all::MutSet;
|
||||||
use roc_module::called_via::BinOp;
|
use roc_module::called_via::BinOp;
|
||||||
use roc_module::ident::{Ident, Lowercase, ModuleName, TagName};
|
use roc_module::ident::{Ident, Lowercase, ModuleName, TagName};
|
||||||
|
@ -204,11 +207,15 @@ pub enum Problem {
|
||||||
OverAppliedCrash {
|
OverAppliedCrash {
|
||||||
region: Region,
|
region: Region,
|
||||||
},
|
},
|
||||||
|
FileProblem {
|
||||||
|
filename: PathBuf,
|
||||||
|
error: io::ErrorKind,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Problem {
|
impl Problem {
|
||||||
pub fn severity(&self) -> Severity {
|
pub fn severity(&self) -> Severity {
|
||||||
use Severity::{RuntimeError, Warning};
|
use Severity::{Fatal, RuntimeError, Warning};
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
Problem::UnusedDef(_, _) => Warning,
|
Problem::UnusedDef(_, _) => Warning,
|
||||||
|
@ -269,6 +276,7 @@ impl Problem {
|
||||||
Problem::UnappliedCrash { .. } => RuntimeError,
|
Problem::UnappliedCrash { .. } => RuntimeError,
|
||||||
Problem::OverAppliedCrash { .. } => RuntimeError,
|
Problem::OverAppliedCrash { .. } => RuntimeError,
|
||||||
Problem::DefsOnlyUsedInRecursion(_, _) => Warning,
|
Problem::DefsOnlyUsedInRecursion(_, _) => Warning,
|
||||||
|
Problem::FileProblem { .. } => Fatal,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -414,6 +422,7 @@ impl Problem {
|
||||||
| Problem::RuntimeError(RuntimeError::VoidValue)
|
| Problem::RuntimeError(RuntimeError::VoidValue)
|
||||||
| Problem::RuntimeError(RuntimeError::ExposedButNotDefined(_))
|
| Problem::RuntimeError(RuntimeError::ExposedButNotDefined(_))
|
||||||
| Problem::RuntimeError(RuntimeError::NoImplementationNamed { .. })
|
| Problem::RuntimeError(RuntimeError::NoImplementationNamed { .. })
|
||||||
|
| Problem::FileProblem { .. }
|
||||||
| Problem::ExposedButNotDefined(_) => None,
|
| Problem::ExposedButNotDefined(_) => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,10 @@ pub mod can;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum Severity {
|
pub enum Severity {
|
||||||
|
/// This should stop compilation in all cases.
|
||||||
|
/// Due to delayed loading of ingested files, this is wanted behaviour over a runtime error.
|
||||||
|
Fatal,
|
||||||
|
|
||||||
/// This will cause a runtime error if some code get srun
|
/// This will cause a runtime error if some code get srun
|
||||||
/// (e.g. type mismatch, naming error)
|
/// (e.g. type mismatch, naming error)
|
||||||
RuntimeError,
|
RuntimeError,
|
||||||
|
|
|
@ -136,7 +136,7 @@ pub fn compile_to_mono<'a, 'i, I: Iterator<Item = &'i str>>(
|
||||||
Severity::Warning => {
|
Severity::Warning => {
|
||||||
warnings.push(buf);
|
warnings.push(buf);
|
||||||
}
|
}
|
||||||
Severity::RuntimeError => {
|
Severity::Fatal | Severity::RuntimeError => {
|
||||||
errors.push(buf);
|
errors.push(buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -154,7 +154,7 @@ pub fn compile_to_mono<'a, 'i, I: Iterator<Item = &'i str>>(
|
||||||
Severity::Warning => {
|
Severity::Warning => {
|
||||||
warnings.push(buf);
|
warnings.push(buf);
|
||||||
}
|
}
|
||||||
Severity::RuntimeError => {
|
Severity::Fatal | Severity::RuntimeError => {
|
||||||
errors.push(buf);
|
errors.push(buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ use roc_solve_problem::TypeError;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
|
||||||
pub struct Problems {
|
pub struct Problems {
|
||||||
|
pub fatally_errored: bool,
|
||||||
pub errors: usize,
|
pub errors: usize,
|
||||||
pub warnings: usize,
|
pub warnings: usize,
|
||||||
}
|
}
|
||||||
|
@ -65,6 +66,7 @@ pub fn report_problems(
|
||||||
// never need to re-allocate either the warnings or the errors vec!
|
// never need to re-allocate either the warnings or the errors vec!
|
||||||
let mut warnings = Vec::with_capacity(total_problems);
|
let mut warnings = Vec::with_capacity(total_problems);
|
||||||
let mut errors = Vec::with_capacity(total_problems);
|
let mut errors = Vec::with_capacity(total_problems);
|
||||||
|
let mut fatally_errored = false;
|
||||||
|
|
||||||
for (home, (module_path, src)) in sources.iter() {
|
for (home, (module_path, src)) in sources.iter() {
|
||||||
let mut src_lines: Vec<&str> = Vec::new();
|
let mut src_lines: Vec<&str> = Vec::new();
|
||||||
|
@ -92,6 +94,10 @@ pub fn report_problems(
|
||||||
RuntimeError => {
|
RuntimeError => {
|
||||||
errors.push(buf);
|
errors.push(buf);
|
||||||
}
|
}
|
||||||
|
Fatal => {
|
||||||
|
fatally_errored = true;
|
||||||
|
errors.push(buf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,6 +117,10 @@ pub fn report_problems(
|
||||||
RuntimeError => {
|
RuntimeError => {
|
||||||
errors.push(buf);
|
errors.push(buf);
|
||||||
}
|
}
|
||||||
|
Fatal => {
|
||||||
|
fatally_errored = true;
|
||||||
|
errors.push(buf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -144,6 +154,7 @@ pub fn report_problems(
|
||||||
}
|
}
|
||||||
|
|
||||||
Problems {
|
Problems {
|
||||||
|
fatally_errored,
|
||||||
errors: errors.len(),
|
errors: errors.len(),
|
||||||
warnings: warnings.len(),
|
warnings: warnings.len(),
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ use roc_types::types::AliasKind;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use crate::error::r#type::suggest;
|
use crate::error::r#type::suggest;
|
||||||
use crate::report::{Annotation, Report, RocDocAllocator, RocDocBuilder};
|
use crate::report::{to_file_problem_report, Annotation, Report, RocDocAllocator, RocDocBuilder};
|
||||||
use ven_pretty::DocAllocator;
|
use ven_pretty::DocAllocator;
|
||||||
|
|
||||||
const SYNTAX_PROBLEM: &str = "SYNTAX PROBLEM";
|
const SYNTAX_PROBLEM: &str = "SYNTAX PROBLEM";
|
||||||
|
@ -1093,6 +1093,11 @@ pub fn can_problem<'b>(
|
||||||
]);
|
]);
|
||||||
title = "OVERAPPLIED CRASH".to_string();
|
title = "OVERAPPLIED CRASH".to_string();
|
||||||
}
|
}
|
||||||
|
Problem::FileProblem { filename, error } => {
|
||||||
|
let report = to_file_problem_report(&alloc, &filename, error);
|
||||||
|
doc = report.doc;
|
||||||
|
title = report.title;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Report {
|
Report {
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
use roc_module::ident::Ident;
|
use roc_module::ident::Ident;
|
||||||
use roc_module::ident::{Lowercase, ModuleName, TagName, Uppercase};
|
use roc_module::ident::{Lowercase, ModuleName, TagName, Uppercase};
|
||||||
use roc_module::symbol::{Interns, ModuleId, PQModuleName, PackageQualified, Symbol};
|
use roc_module::symbol::{Interns, ModuleId, ModuleIds, PQModuleName, PackageQualified, Symbol};
|
||||||
use roc_problem::Severity;
|
use roc_problem::Severity;
|
||||||
use roc_region::all::LineColumnRegion;
|
use roc_region::all::LineColumnRegion;
|
||||||
use std::fmt;
|
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
use std::{fmt, io};
|
||||||
use ven_pretty::{BoxAllocator, DocAllocator, DocBuilder, Render, RenderAnnotated};
|
use ven_pretty::{BoxAllocator, DocAllocator, DocBuilder, Render, RenderAnnotated};
|
||||||
|
|
||||||
pub use crate::error::canonicalize::can_problem;
|
pub use crate::error::canonicalize::can_problem;
|
||||||
|
@ -1077,3 +1077,88 @@ where
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn to_file_problem_report_string(filename: &Path, error: io::ErrorKind) -> String {
|
||||||
|
let src_lines: Vec<&str> = Vec::new();
|
||||||
|
|
||||||
|
let mut module_ids = ModuleIds::default();
|
||||||
|
|
||||||
|
let module_id = module_ids.get_or_insert(&"find module name somehow?".into());
|
||||||
|
|
||||||
|
let interns = Interns::default();
|
||||||
|
|
||||||
|
// Report parsing and canonicalization problems
|
||||||
|
let alloc = RocDocAllocator::new(&src_lines, module_id, &interns);
|
||||||
|
|
||||||
|
let mut buf = String::new();
|
||||||
|
let palette = DEFAULT_PALETTE;
|
||||||
|
let report = to_file_problem_report(&alloc, filename, error);
|
||||||
|
report.render_color_terminal(&mut buf, &alloc, &palette);
|
||||||
|
|
||||||
|
buf
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_file_problem_report<'b>(
|
||||||
|
alloc: &'b RocDocAllocator<'b>,
|
||||||
|
filename: &Path,
|
||||||
|
error: io::ErrorKind,
|
||||||
|
) -> Report<'b> {
|
||||||
|
let filename: String = filename.to_str().unwrap().to_string();
|
||||||
|
match error {
|
||||||
|
io::ErrorKind::NotFound => {
|
||||||
|
let doc = alloc.stack([
|
||||||
|
alloc.reflow(r"I am looking for this file, but it's not there:"),
|
||||||
|
alloc
|
||||||
|
.string(filename)
|
||||||
|
.annotate(Annotation::ParserSuggestion)
|
||||||
|
.indent(4),
|
||||||
|
alloc.concat([
|
||||||
|
alloc.reflow(r"Is the file supposed to be there? "),
|
||||||
|
alloc.reflow("Maybe there is a typo in the file name?"),
|
||||||
|
]),
|
||||||
|
]);
|
||||||
|
|
||||||
|
Report {
|
||||||
|
filename: "UNKNOWN.roc".into(),
|
||||||
|
doc,
|
||||||
|
title: "FILE NOT FOUND".to_string(),
|
||||||
|
severity: Severity::Fatal,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
io::ErrorKind::PermissionDenied => {
|
||||||
|
let doc = alloc.stack([
|
||||||
|
alloc.reflow(r"I don't have the required permissions to read this file:"),
|
||||||
|
alloc
|
||||||
|
.string(filename)
|
||||||
|
.annotate(Annotation::ParserSuggestion)
|
||||||
|
.indent(4),
|
||||||
|
alloc
|
||||||
|
.concat([alloc.reflow(r"Is it the right file? Maybe change its permissions?")]),
|
||||||
|
]);
|
||||||
|
|
||||||
|
Report {
|
||||||
|
filename: "UNKNOWN.roc".into(),
|
||||||
|
doc,
|
||||||
|
title: "FILE PERMISSION DENIED".to_string(),
|
||||||
|
severity: Severity::Fatal,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
let error = std::io::Error::from(error);
|
||||||
|
let formatted = format!("{}", error);
|
||||||
|
let doc = alloc.stack([
|
||||||
|
alloc.reflow(r"I tried to read this file:"),
|
||||||
|
alloc.string(filename).annotate(Annotation::Error).indent(4),
|
||||||
|
alloc.reflow(r"But ran into:"),
|
||||||
|
alloc.text(formatted).annotate(Annotation::Error).indent(4),
|
||||||
|
]);
|
||||||
|
|
||||||
|
Report {
|
||||||
|
filename: "UNKNOWN.roc".into(),
|
||||||
|
doc,
|
||||||
|
title: "FILE PROBLEM".to_string(),
|
||||||
|
severity: Severity::Fatal,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue