Two shadowing report tests

This commit is contained in:
Chad Stearns 2020-04-05 15:19:43 -04:00
parent 671eb0f32e
commit d8511e3285
3 changed files with 109 additions and 25 deletions

View file

@ -1326,7 +1326,14 @@ fn to_pending_def<'a>(
} }
} }
Err(err) => panic!("TODO gracefully handle shadowing of type alias {:?}", err), Err((original_region, shadow)) => {
env.problem(Problem::ShadowingInAnnotation {
original_region,
shadow,
});
panic!("TODO gracefully handle shadowing of type alias {:?}", err)
}
} }
} }

View file

@ -1,12 +1,14 @@
use crate::report::ReportText::{BinOp, Concat, Module, Region, Value}; use crate::report::ReportText::{BinOp, Concat, Module, Region, Value};
use roc_module::symbol::{Interns, ModuleId, Symbol}; use roc_module::symbol::{Interns, ModuleId, Symbol};
use roc_problem::can::PrecedenceProblem::BothNonAssociative; use roc_problem::can::PrecedenceProblem::BothNonAssociative;
use roc_problem::can::Problem; use roc_problem::can::{Problem, RuntimeError};
use roc_types::pretty_print::content_to_string; use roc_types::pretty_print::content_to_string;
use roc_types::subs::{Content, Subs}; use roc_types::subs::{Content, Subs};
use roc_types::types::{write_error_type, ErrorType}; use roc_types::types::{write_error_type, ErrorType};
use std::path::PathBuf; use std::path::PathBuf;
use roc_module::ident::Ident;
use roc_region::all::Located;
use std::fmt; use std::fmt;
use ven_pretty::{BoxAllocator, DocAllocator, DocBuilder, Render, RenderAnnotated}; use ven_pretty::{BoxAllocator, DocAllocator, DocBuilder, Render, RenderAnnotated};
@ -110,14 +112,21 @@ pub fn can_problem(filename: PathBuf, problem: Problem) -> Report {
original_region, original_region,
shadow, shadow,
} => { } => {
// v-- just to satisfy clippy shadowing_report(&mut texts, original_region, shadow);
let _a = original_region;
let _b = shadow;
panic!("TODO implement shadow report");
} }
Problem::RuntimeError(_runtime_error) => { Problem::RuntimeError(runtime_error) => match runtime_error {
panic!("TODO implement run time error report"); RuntimeError::Shadowing {
original_region,
shadow,
} => {
shadowing_report(&mut texts, original_region, shadow);
} }
_ => {
dbg!(runtime_error);
panic!("TODO implement run time error reporting");
}
},
}; };
Report { Report {
@ -126,11 +135,27 @@ pub fn can_problem(filename: PathBuf, problem: Problem) -> Report {
} }
} }
fn shadowing_report(
texts: &mut Vec<ReportText>,
original_region: roc_region::all::Region,
shadow: Located<Ident>,
) {
texts.push(name(shadow.value));
texts.push(plain_text(" is first defined here:"));
texts.push(Region(original_region));
texts.push(plain_text("But then it's defined a second time here:"));
texts.push(Region(shadow.region));
texts.push(plain_text("Since these variables have the same name, it's easy to use the wrong one on accident. Give one of them a new name."));
}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum ReportText { pub enum ReportText {
/// A value. Render it qualified unless it was defined in the current module. /// A value. Render it qualified unless it was defined in the current module.
Value(Symbol), Value(Symbol),
/// An identifier, should probably be rendered the same way as a symbol.
Name(Ident),
/// A module, /// A module,
Module(ModuleId), Module(ModuleId),
@ -181,6 +206,10 @@ pub fn plain_text(str: &str) -> ReportText {
ReportText::Plain(Box::from(str)) ReportText::Plain(Box::from(str))
} }
pub fn name(ident: Ident) -> ReportText {
ReportText::Name(ident)
}
pub fn em_text(str: &str) -> ReportText { pub fn em_text(str: &str) -> ReportText {
ReportText::EmText(Box::from(str)) ReportText::EmText(Box::from(str))
} }
@ -658,6 +687,9 @@ impl ReportText {
.append(alloc.line()) .append(alloc.line())
.append(alloc.line()) .append(alloc.line())
} }
Name(ident) => alloc
.text(format!("{}", ident.as_inline_str()))
.annotate(Annotation::Symbol),
} }
} }
} }

View file

@ -305,22 +305,67 @@ mod test_reporting {
) )
} }
// #[test] #[test]
// fn report_shadow() { fn report_shadowing() {
// report_problem_as( report_problem_as(
// indoc!( indoc!(
// r#" r#"
// i = 1 i = 1
//
// s = \i -> s = \i ->
// i + 1 i + 1
//
// s i s i
// "# "#
// ), ),
// indoc!(r#" "#), indoc!(
// ) r#"
// } i is first defined here:
1 i = 1
^
But then it's defined a second time here:
3 s = \i ->
^
Since these variables have the same name, it's easy to use the wrong one on accident. Give one of them a new name."#
),
)
}
#[test]
fn report_shadowing_in_annotation() {
report_problem_as(
indoc!(
r#"
Booly : [ Yes, No ]
Booly : [ Yes, No, Maybe ]
x =
No
x
"#
),
indoc!(
r#"
Booly is first defined here:
1 Booly : [ Yes, No ]
^^^^^
But then it's defined a second time here:
3 Booly : [ Yes, No, Maybe ]
^^^^^
Since these variables have the same name, it's easy to use the wrong one on accident. Give one of them a new name."#
),
)
}
// #[test] // #[test]
// fn report_unsupported_top_level_def() { // fn report_unsupported_top_level_def() {