basic working

compiling, but still missing positions from expression errors
This commit is contained in:
faldor20 2024-12-11 22:36:14 +10:00
parent 146710a129
commit 81f2095e61
No known key found for this signature in database
GPG key ID: F2216079B890CD57
14 changed files with 192 additions and 49 deletions

View file

@ -254,7 +254,7 @@ fn main() -> io::Result<()> {
exit_code = problems.exit_code();
}
Err(LoadingProblem::FormattedReport(report)) => {
Err(LoadingProblem::FormattedReport(report, _)) => {
print!("{report}");
exit_code = 1;
@ -285,7 +285,7 @@ fn main() -> io::Result<()> {
Ok(problems.exit_code())
}
Err(LoadingProblem::FormattedReport(report)) => {
Err(LoadingProblem::FormattedReport(report, _)) => {
print!("{report}");
Ok(1)

View file

@ -702,7 +702,7 @@ pub fn handle_error_module(
pub fn handle_loading_problem(problem: LoadingProblem) -> std::io::Result<i32> {
match problem {
LoadingProblem::FormattedReport(report) => {
LoadingProblem::FormattedReport(report,_) => {
print!("{report}");
Ok(1)
}

View file

@ -88,7 +88,7 @@ fn write_types_for_module_real(module_id: ModuleId, filename: &str, output_path:
let mut module = match res_module {
Ok(v) => v,
Err(LoadingProblem::FormattedReport(report)) => {
Err(LoadingProblem::FormattedReport(report,None)) => {
internal_error!("{}", report);
}
Err(other) => {

View file

@ -187,7 +187,7 @@ mod test_reporting {
let mut buf = String::new();
match infer_expr_help_new(subdir, arena, src) {
Err(LoadingProblem::FormattedReport(fail)) => fail,
Err(LoadingProblem::FormattedReport(fail,_)) => fail,
Ok((module_src, type_problems, can_problems, home, interns)) => {
let lines = LineInfo::new(&module_src);
let src_lines: Vec<&str> = module_src.split('\n').collect();

View file

@ -998,13 +998,49 @@ pub enum LoadingProblem<'a> {
TriedToImportAppModule,
/// a formatted report
FormattedReport(String),
FormattedReport(String, Option<Region>),
ImportCycle(PathBuf, Vec<ModuleId>),
IncorrectModuleName(FileError<'a, IncorrectModuleName<'a>>),
CouldNotFindCacheDir,
ChannelProblem(ChannelProblem),
}
impl<'a> LoadingProblem<'a> {
pub fn get_region(&self) -> Option<Region> {
match self {
LoadingProblem::ParsingFailed(err) => err.problem.problem.get_region(),
LoadingProblem::MultiplePlatformPackages {
filename,
module_id,
source,
region,
} => Some(*region),
LoadingProblem::NoPlatformPackage {
filename,
module_id,
source,
region,
} => Some(*region),
LoadingProblem::UnrecognizedPackageShorthand {
filename,
module_id,
source,
region,
shorthand,
available,
} => Some(*region),
LoadingProblem::FileProblem { filename, error } => None,
LoadingProblem::UnexpectedHeader(_) => None,
LoadingProblem::ErrJoiningWorkerThreads => None,
LoadingProblem::TriedToImportAppModule => None,
LoadingProblem::FormattedReport(_, region) => *region,
LoadingProblem::ImportCycle(_, _) => None,
LoadingProblem::IncorrectModuleName(_) => None,
LoadingProblem::CouldNotFindCacheDir => None,
LoadingProblem::ChannelProblem(_) => None,
}
}
}
#[derive(Debug)]
pub enum AvailableShorthands<'a> {
@ -1179,12 +1215,12 @@ impl<'a> LoadStart<'a> {
})
.into_inner()
.into_module_ids();
let region=problem.get_region();
let report = report_loading_problem(problem, module_ids, render, palette);
// TODO try to gracefully recover and continue
// instead of changing the control flow to exit.
return Err(LoadingProblem::FormattedReport(report));
return Err(LoadingProblem::FormattedReport(report, region));
}
};
@ -1609,6 +1645,7 @@ fn state_thread_step<'a>(
msg_tx: &crossbeam::channel::Sender<Msg<'a>>,
msg_rx: &crossbeam::channel::Receiver<Msg<'a>>,
) -> Result<ControlFlow<LoadResult<'a>, State<'a>>, LoadingProblem<'a>> {
match msg_rx.try_recv() {
Ok(msg) => {
match msg {
@ -1672,10 +1709,11 @@ fn state_thread_step<'a>(
}
Msg::FailedToReadFile { filename, error } => {
let buf = to_file_problem_report_string(filename, error, true);
Err(LoadingProblem::FormattedReport(buf))
Err(LoadingProblem::FormattedReport(buf,None))
}
Msg::FailedToParse(problem) => {
let region=problem.problem.problem.get_region();
let module_ids = (*state.arc_modules).lock().clone().into_module_ids();
let buf = to_parse_problem_report(
problem,
@ -1684,14 +1722,14 @@ fn state_thread_step<'a>(
state.render,
state.palette,
);
Err(LoadingProblem::FormattedReport(buf))
Err(LoadingProblem::FormattedReport(buf,region))
}
Msg::IncorrectModuleName(FileError {
problem: SourceError { problem, bytes },
filename,
}) => {
let module_ids = (*state.arc_modules).lock().clone().into_module_ids();
let buf = to_incorrect_module_name_report(
let (buf, region) = to_incorrect_module_name_report(
module_ids,
state.constrained_ident_ids,
problem,
@ -1699,7 +1737,7 @@ fn state_thread_step<'a>(
bytes,
state.render,
);
Err(LoadingProblem::FormattedReport(buf))
Err(LoadingProblem::FormattedReport(buf,Some(region)))
}
msg => {
// This is where most of the main thread's work gets done.
@ -1716,6 +1754,7 @@ fn state_thread_step<'a>(
match res_state {
Ok(new_state) => Ok(ControlFlow::Continue(new_state)),
Err(LoadingProblem::ParsingFailed(problem)) => {
let region=problem.problem.problem.get_region();
let module_ids = Arc::try_unwrap(arc_modules)
.unwrap_or_else(|_| {
panic!(
@ -1734,7 +1773,7 @@ fn state_thread_step<'a>(
render,
palette,
);
Err(LoadingProblem::FormattedReport(buf))
Err(LoadingProblem::FormattedReport(buf, region))
}
Err(LoadingProblem::ImportCycle(filename, cycle)) => {
let module_ids = arc_modules.lock().clone().into_module_ids();
@ -1747,7 +1786,7 @@ fn state_thread_step<'a>(
filename,
render,
);
return Err(LoadingProblem::FormattedReport(buf));
return Err(LoadingProblem::FormattedReport(buf,None));
}
Err(LoadingProblem::IncorrectModuleName(FileError {
problem: SourceError { problem, bytes },
@ -1756,7 +1795,7 @@ fn state_thread_step<'a>(
let module_ids = arc_modules.lock().clone().into_module_ids();
let root_exposed_ident_ids = IdentIds::exposed_builtins(0);
let buf = to_incorrect_module_name_report(
let (buf, region) = to_incorrect_module_name_report(
module_ids,
root_exposed_ident_ids,
problem,
@ -1764,7 +1803,7 @@ fn state_thread_step<'a>(
bytes,
render,
);
return Err(LoadingProblem::FormattedReport(buf));
return Err(LoadingProblem::FormattedReport(buf,Some(region)));
}
Err(LoadingProblem::UnrecognizedPackageShorthand {
filename,
@ -1788,7 +1827,7 @@ fn state_thread_step<'a>(
available,
render,
);
return Err(LoadingProblem::FormattedReport(buf));
return Err(LoadingProblem::FormattedReport(buf,Some(region)));
}
Err(e) => Err(e),
}
@ -1835,9 +1874,9 @@ pub fn report_loading_problem(
filename,
bytes,
render,
)
).0
}
LoadingProblem::FormattedReport(report) => report,
LoadingProblem::FormattedReport(report,region) => report,
LoadingProblem::FileProblem { filename, error } => {
to_file_problem_report_string(filename, error, true)
}
@ -2085,7 +2124,7 @@ fn load_multi_threaded<'a>(
"command can sometimes give a more helpful error report than other commands.\n\n"
)
.to_string(),
))
None))
})
}
}
@ -3046,7 +3085,7 @@ fn register_package_shorthands<'a>(
Problem::InvalidUrl(url_err),
module_path.to_path_buf(),
);
return Err(LoadingProblem::FormattedReport(buf));
return Err(LoadingProblem::FormattedReport(buf,None));
}
}
}
@ -3164,7 +3203,7 @@ fn finish_specialization<'a>(
Valid(To::NewPackage(p_or_p)) => PathBuf::from(p_or_p.as_str()),
other => {
let buf = report_cannot_run(state.root_id, state.root_path, other);
return Err(LoadingProblem::FormattedReport(buf));
return Err(LoadingProblem::FormattedReport(buf,None));
}
};
@ -4129,7 +4168,7 @@ fn load_packages<'a>(
Err(problem) => {
let buf = to_https_problem_report_string(src, problem, filename);
load_messages.push(Msg::FailedToLoad(LoadingProblem::FormattedReport(buf)));
load_messages.push(Msg::FailedToLoad(LoadingProblem::FormattedReport(buf,None)));
return;
}
}
@ -6447,7 +6486,7 @@ fn to_incorrect_module_name_report<'a>(
filename: PathBuf,
src: &'a [u8],
render: RenderTarget,
) -> String {
) -> (String,Region) {
use roc_reporting::report::{Report, RocDocAllocator, DEFAULT_PALETTE};
use ven_pretty::DocAllocator;
@ -6488,7 +6527,7 @@ fn to_incorrect_module_name_report<'a>(
let mut buf = String::new();
let palette = DEFAULT_PALETTE;
report.render(render, &mut buf, &alloc, &palette);
buf
(buf, found.region)
}
fn to_no_platform_package_report(

View file

@ -141,7 +141,7 @@ fn multiple_modules(subdir: &str, files: Vec<(&str, &str)>) -> Result<LoadedModu
match multiple_modules_help(subdir, arena, files) {
Err(io_error) => panic!("IO trouble: {io_error:?}"),
Ok(Err(LoadingProblem::FormattedReport(buf))) => Err(buf),
Ok(Err(LoadingProblem::FormattedReport(buf, None))) => Err(buf),
Ok(Err(loading_problem)) => Err(format!("{loading_problem:?}")),
Ok(Ok(mut loaded_module)) => {
let home = loaded_module.module_id;
@ -247,7 +247,7 @@ fn load_fixture(
);
let mut loaded_module = match loaded {
Ok(x) => x,
Err(roc_load_internal::file::LoadingProblem::FormattedReport(report)) => {
Err(roc_load_internal::file::LoadingProblem::FormattedReport(report,None)) => {
println!("{report}");
panic!("{}", report);
}

View file

@ -63,6 +63,28 @@ pub enum SyntaxError<'a> {
Space(BadInputError),
NotEndOfFile(Position),
}
impl<'a> SyntaxError<'a> {
pub fn get_region(&self) -> Option<Region> {
let region = match self {
SyntaxError::Unexpected(r) => Some(*r),
SyntaxError::Eof(r) => Some(*r),
SyntaxError::ReservedKeyword(r) => Some(*r),
SyntaxError::ArgumentsBeforeEquals(r) => Some(*r),
SyntaxError::Type(e_type) => Some(e_type.get_region()),
SyntaxError::Pattern(e_pattern) => Some(e_pattern.get_region()),
SyntaxError::NotEndOfFile(pos) => Some(Region::from_pos(*pos)),
SyntaxError::Expr(e_expr, pos) => Some(Region::from_pos(*pos)),
SyntaxError::Header(e_header) => Some(e_header.get_region()),
SyntaxError::NotYetImplemented(_) => None,
SyntaxError::OutdentedTooFar => None,
SyntaxError::Todo => None,
SyntaxError::InvalidPattern => None,
SyntaxError::BadUtf8 => None,
SyntaxError::Space(bad_input) => None,
};
region
}
}
pub trait SpaceProblem: std::fmt::Debug {
fn space_problem(e: BadInputError, pos: Position) -> Self;
}
@ -133,6 +155,27 @@ pub enum EHeader<'a> {
InconsistentModuleName(Region),
}
impl<'a> EHeader<'a> {
pub fn get_region(&self) -> Region {
match self {
EHeader::Provides(_, pos)
| EHeader::Params(_, pos)
| EHeader::Exposes(_, pos)
| EHeader::Imports(_, pos)
| EHeader::Requires(_, pos)
| EHeader::Packages(_, pos)
| EHeader::Space(_, pos)
| EHeader::Start(pos)
| EHeader::ModuleName(pos)
| EHeader::AppName(_, pos)
| EHeader::PackageName(_, pos)
| EHeader::PlatformName(_, pos)
| EHeader::IndentStart(pos) => Region::from_pos(*pos),
EHeader::InconsistentModuleName(region) => *region,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum EProvides<'a> {
Provides(Position),
@ -587,6 +630,30 @@ pub enum EPattern<'a> {
RecordUpdaterFunction(Position),
}
impl<'a> EPattern<'a> {
pub fn get_region(&self) -> Region {
let pos = match self {
EPattern::Record(_, position)
| EPattern::List(_, position)
| EPattern::AsKeyword(position)
| EPattern::AsIdentifier(position)
| EPattern::Underscore(position)
| EPattern::NotAPattern(position)
| EPattern::Start(position)
| EPattern::End(position)
| EPattern::Space(_, position)
| EPattern::PInParens(_, position)
| EPattern::NumLiteral(_, position)
| EPattern::IndentStart(position)
| EPattern::IndentEnd(position)
| EPattern::AsIndentStart(position)
| EPattern::AccessorFunction(position)
| EPattern::RecordUpdaterFunction(position) => position,
};
Region::from_pos(*pos)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum PRecord<'a> {
End(Position),
@ -649,6 +716,33 @@ pub enum EType<'a> {
TAsIndentStart(Position),
}
impl<'a> EType<'a> {
pub fn get_region(&self) -> Region {
let pos = match self {
EType::Space(_, position)
| EType::UnderscoreSpacing(position)
| EType::TRecord(_, position)
| EType::TTagUnion(_, position)
| EType::TInParens(_, position)
| EType::TApply(_, position)
| EType::TInlineAlias(_, position)
| EType::TBadTypeVariable(position)
| EType::TWildcard(position)
| EType::TInferred(position)
| EType::TStart(position)
| EType::TEnd(position)
| EType::TFunctionArgument(position)
| EType::TWhereBar(position)
| EType::TImplementsClause(position)
| EType::TAbilityImpl(_, position)
| EType::TIndentStart(position)
| EType::TIndentEnd(position)
| EType::TAsIndentStart(position) => position,
};
Region::from_pos(*pos)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ETypeRecord<'a> {
End(Position),

View file

@ -172,7 +172,7 @@ fn compiles_to_ir(test_name: &str, src: &str, mode: &str, allow_type_errors: boo
let mut loaded = match loaded {
Ok(x) => x,
Err(LoadMonomorphizedError::LoadingProblem(roc_load::LoadingProblem::FormattedReport(
report,
report,_
))) => {
println!("{report}");
panic!();

View file

@ -63,7 +63,7 @@ pub(crate) fn write_compiled_ir<'a>(
let loaded = match loaded {
Ok(x) => x,
Err(LoadMonomorphizedError::LoadingProblem(roc_load::LoadingProblem::FormattedReport(
report,
report,_
))) => {
println!("{report}");
panic!();

View file

@ -674,7 +674,7 @@ pub fn load_module_for_docs(filename: PathBuf) -> LoadedModule {
load_config,
) {
Ok(loaded) => loaded,
Err(LoadingProblem::FormattedReport(report)) => {
Err(LoadingProblem::FormattedReport(report,_)) => {
eprintln!("{report}");
std::process::exit(1);
}

View file

@ -437,7 +437,7 @@ pub fn load_types(
},
)
.unwrap_or_else(|problem| match problem {
LoadingProblem::FormattedReport(report) => {
LoadingProblem::FormattedReport(report, _) => {
eprintln!("{report}");
process::exit(1);

View file

@ -122,7 +122,7 @@ pub(crate) fn global_analysis(doc_info: DocInfo) -> Vec<AnalyzedDocument> {
Ok(module) => module,
Err(problem) => {
let all_problems = problem
.into_lsp_diagnostic(&())
.into_lsp_diagnostic(&doc_info.line_info)
.into_iter()
.collect::<Vec<_>>();

View file

@ -1,3 +1,7 @@
use std::any::Any;
use roc_load::LoadingProblem;
use roc_parse::parser::{EHeader, EPattern, EType, SourceError, SyntaxError};
use roc_region::all::{LineColumn, LineColumnRegion, LineInfo, Region};
use tower_lsp::lsp_types::{Position, Range};
@ -69,7 +73,7 @@ impl ToRocPosition for tower_lsp::lsp_types::Position {
}
pub(crate) mod diag {
use std::path::Path;
use std::{fmt::Debug, path::Path};
use roc_load::LoadingProblem;
use roc_region::all::{LineInfo, Region};
@ -102,19 +106,16 @@ pub(crate) mod diag {
}
impl IntoLspDiagnostic<'_> for &LoadingProblem<'_> {
type Feed = ();
type Feed = LineInfo;
fn into_lsp_diagnostic(self, _feed: &()) -> Option<Diagnostic> {
let range = Range {
start: Position {
line: 0,
character: 0,
},
end: Position {
line: 0,
character: 1,
},
};
fn into_lsp_diagnostic(self, line_info: &LineInfo) -> Option<Diagnostic> {
let mut range = self
.get_region()
.unwrap_or(Region::new(
roc_region::all::Position::new(0),
roc_region::all::Position::new(10000000),
))
.to_range(line_info);
let msg = match self {
LoadingProblem::FileProblem { filename, error } => {
@ -152,7 +153,10 @@ pub(crate) mod diag {
LoadingProblem::TriedToImportAppModule => {
"Attempted to import app module".to_string()
}
LoadingProblem::FormattedReport(report) => report.clone(),
LoadingProblem::FormattedReport(report, region) => {
range = region.unwrap_or(Region::zero()).to_range(line_info);
report.clone()
}
LoadingProblem::ImportCycle(_, _) => {
"Circular dependency between modules".to_string()
}
@ -194,7 +198,10 @@ pub(crate) mod diag {
fn into_lsp_diagnostic(self, fmt: &'a ProblemFmt<'a>) -> Option<Diagnostic> {
let range = self
.region()
.unwrap_or_else(Region::zero)
.unwrap_or(Region::new(
roc_region::all::Position::new(0),
roc_region::all::Position::new(10000000),
))
.to_range(fmt.line_info);
let report = roc_reporting::report::can_problem(
@ -228,7 +235,10 @@ pub(crate) mod diag {
fn into_lsp_diagnostic(self, fmt: &'a ProblemFmt<'a>) -> Option<Diagnostic> {
let range = self
.region()
.unwrap_or_else(Region::zero)
.unwrap_or(Region::new(
roc_region::all::Position::new(0),
roc_region::all::Position::new(10000000),
))
.to_range(fmt.line_info);
let report = roc_reporting::report::type_problem(

View file

@ -80,7 +80,7 @@ pub fn compile_to_mono<'a, 'i, I: Iterator<Item = &'i str>>(
(m.can_problems, m.type_problems)
);
}
Err(LoadMonomorphizedError::LoadingProblem(LoadingProblem::FormattedReport(report))) => {
Err(LoadMonomorphizedError::LoadingProblem(LoadingProblem::FormattedReport(report,_))) => {
return (
None,
Problems {