bring parse errors into the reporting tests

This commit is contained in:
Folkert 2020-04-15 19:49:05 +02:00
parent 5e500f55ae
commit e21cdfc689
4 changed files with 91 additions and 138 deletions

View file

@ -1247,7 +1247,11 @@ pub fn ident_etc<'a>(min_indent: u16) -> impl Parser<'a, Expr<'a>> {
(Some(_loc_args), Some((_spaces_before_equals, Either::First(_equals_indent)))) => {
// We got args with an '=' after them, e.g. `foo a b = ...`
// This is a syntax error!
panic!("TODO gracefully handle parse error for defs like `foo a b = ...`");
let fail = Fail {
attempting: state.attempting,
reason: FailReason::ArgumentsBeforeEquals,
};
Err((fail, state))
}
(None, Some((spaces_before_equals, Either::First(equals_indent)))) => {
// We got '=' with no args before it

View file

@ -190,6 +190,7 @@ pub enum FailReason {
Eof(Region),
InvalidPattern,
ReservedKeyword(Region),
ArgumentsBeforeEquals,
}
#[derive(Debug, Clone, PartialEq, Eq)]

View file

@ -103,96 +103,10 @@ pub fn parse_loc_with<'a>(arena: &'a Bump, input: &'a str) -> Result<Located<ast
}
#[allow(dead_code)]
pub fn can_expr(expr_str: &str) -> CanExprOut {
pub fn can_expr(expr_str: &str) -> Result<CanExprOut, Fail> {
can_expr_with(&Bump::new(), test_home(), expr_str)
}
#[allow(dead_code)]
pub fn uniq_expr(
expr_str: &str,
) -> (
Located<Expr>,
Output,
Vec<Problem>,
Subs,
Variable,
Constraint,
ModuleId,
Interns,
) {
let declared_idents: &ImMap<Ident, (Symbol, Region)> = &ImMap::default();
uniq_expr_with(&Bump::new(), expr_str, declared_idents)
}
#[allow(dead_code)]
pub fn uniq_expr_with(
arena: &Bump,
expr_str: &str,
declared_idents: &ImMap<Ident, (Symbol, Region)>,
) -> (
Located<Expr>,
Output,
Vec<Problem>,
Subs,
Variable,
Constraint,
ModuleId,
Interns,
) {
let home = test_home();
let CanExprOut {
loc_expr,
output,
problems,
var_store: old_var_store,
var,
interns,
..
} = can_expr_with(arena, home, expr_str);
// double check
let var_store = VarStore::new(old_var_store.fresh());
let expected2 = Expected::NoExpectation(Type::Variable(var));
let constraint = roc_constrain::uniq::constrain_declaration(
home,
&var_store,
Region::zero(),
&loc_expr,
declared_idents,
expected2,
);
let stdlib = uniq_stdlib();
let types = stdlib.types;
let imports: Vec<_> = types
.iter()
.map(|(symbol, (solved_type, region))| Import {
loc_symbol: Located::at(*region, *symbol),
solved_type: solved_type,
})
.collect();
// load builtin values
// TODO what to do with those rigids?
let (_introduced_rigids, constraint) =
constrain_imported_values(imports, constraint, &var_store);
// load builtin types
let mut constraint = load_builtin_aliases(&stdlib.aliases, constraint, &var_store);
constraint.instantiate_aliases(&var_store);
let subs2 = Subs::new(var_store.into());
(
loc_expr, output, problems, subs2, var, constraint, home, interns,
)
}
pub struct CanExprOut {
pub loc_expr: Located<Expr>,
pub output: Output,
@ -205,13 +119,13 @@ pub struct CanExprOut {
}
#[allow(dead_code)]
pub fn can_expr_with(arena: &Bump, home: ModuleId, expr_str: &str) -> CanExprOut {
let loc_expr = parse_loc_with(&arena, expr_str).unwrap_or_else(|e| {
panic!(
"can_expr_with() got a parse error when attempting to canonicalize:\n\n{:?} {:?}",
expr_str, e
)
});
pub fn can_expr_with(arena: &Bump, home: ModuleId, expr_str: &str) -> Result<CanExprOut, Fail> {
let loc_expr = match parse_loc_with(&arena, expr_str) {
Ok(e) => e,
Err(fail) => {
return Err(fail);
}
};
let var_store = VarStore::default();
let var = var_store.fresh();
@ -283,7 +197,7 @@ pub fn can_expr_with(arena: &Bump, home: ModuleId, expr_str: &str) -> CanExprOut
all_ident_ids,
};
CanExprOut {
Ok(CanExprOut {
loc_expr,
output,
problems: env.problems,
@ -292,7 +206,7 @@ pub fn can_expr_with(arena: &Bump, home: ModuleId, expr_str: &str) -> CanExprOut
interns,
var,
constraint,
}
})
}
#[allow(dead_code)]

View file

@ -23,6 +23,7 @@ mod test_reporting {
use std::path::PathBuf;
// use roc_region::all;
use crate::helpers::{can_expr, infer_expr, CanExprOut};
use roc_parse::parser::Fail;
use roc_reporting::report::{RocDocAllocator, RocDocBuilder};
use roc_solve::solve;
@ -43,13 +44,16 @@ mod test_reporting {
fn infer_expr_help(
expr_src: &str,
) -> (
) -> Result<
(
Vec<solve::TypeError>,
Vec<roc_problem::can::Problem>,
Vec<roc_mono::expr::MonoProblem>,
ModuleId,
Interns,
) {
),
Fail,
> {
let CanExprOut {
loc_expr,
output,
@ -60,7 +64,7 @@ mod test_reporting {
mut interns,
problems: can_problems,
..
} = can_expr(expr_src);
} = can_expr(expr_src)?;
let mut subs = Subs::new(var_store.into());
for (var, name) in output.introduced_variables.name_by_var {
@ -99,7 +103,7 @@ mod test_reporting {
);
}
(unify_problems, can_problems, mono_problems, home, interns)
Ok((unify_problems, can_problems, mono_problems, home, interns))
}
fn list_reports<F>(src: &str, buf: &mut String, callback: F)
@ -108,8 +112,9 @@ mod test_reporting {
{
use ven_pretty::DocAllocator;
let (type_problems, can_problems, mono_problems, home, interns) = infer_expr_help(src);
match infer_expr_help(src) {
Err(fail) => todo!(),
Ok((type_problems, can_problems, mono_problems, home, interns)) => {
let src_lines: Vec<&str> = src.split('\n').collect();
let alloc = RocDocAllocator::new(&src_lines, home, &interns);
@ -143,6 +148,8 @@ mod test_reporting {
callback(doc, buf)
}
}
}
fn report_problem_as(src: &str, expected_rendering: &str) {
let mut buf: String = String::new();
@ -491,7 +498,8 @@ mod test_reporting {
"#
);
let (_type_problems, _can_problems, _mono_problems, home, interns) = infer_expr_help(src);
let (_type_problems, _can_problems, _mono_problems, home, interns) =
infer_expr_help(src).expect("parse error");
let mut buf = String::new();
let src_lines: Vec<&str> = src.split('\n').collect();
@ -521,7 +529,7 @@ mod test_reporting {
);
let (_type_problems, _can_problems, _mono_problems, home, mut interns) =
infer_expr_help(src);
infer_expr_help(src).expect("parse error");
let mut buf = String::new();
let src_lines: Vec<&str> = src.split('\n').collect();
@ -2671,4 +2679,30 @@ mod test_reporting {
),
)
}
#[test]
fn elm_function_syntax() {
report_problem_as(
indoc!(
r#"
f x y = x
"#
),
indoc!(
r#"
-- SYNTAX PROBLEM --------------------------------------------------------------
The `a` type variable is not used in the `Foo` alias definition:
1 Foo a : [ Foo ]
^
Roc does not allow unused type parameters!
Hint: If you want an unused type parameter (a so-called "phantom
type"), read the guide section on phantom data.
"#
),
)
}
}