mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-26 13:29:12 +00:00
Stub out the rest of uitest
This commit is contained in:
parent
3aaf771543
commit
54d6bf7747
3 changed files with 170 additions and 40 deletions
|
@ -9,7 +9,8 @@ use std::{
|
|||
use lazy_static::lazy_static;
|
||||
use libtest_mimic::{run, Arguments, Failed, Trial};
|
||||
use regex::Regex;
|
||||
use test_solve_helpers::InferOptions;
|
||||
use roc_region::all::LineColumn;
|
||||
use test_solve_helpers::{infer_queries, InferOptions, InferredQuery};
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
let args = Arguments::from_args();
|
||||
|
@ -77,7 +78,18 @@ fn run_test(path: PathBuf) -> Result<(), Failed> {
|
|||
source,
|
||||
} = TestCase::parse(data)?;
|
||||
|
||||
fs::write(&path, &source)?;
|
||||
let inferred_program = infer_queries(&source, infer_options)?;
|
||||
let inferred_queries = inferred_program.into_sorted_queries();
|
||||
|
||||
{
|
||||
let mut fd = fs::OpenOptions::new()
|
||||
.write(true)
|
||||
.truncate(true)
|
||||
.open(&path)?;
|
||||
|
||||
assemble_query_output(&mut fd, &source, inferred_queries)?;
|
||||
}
|
||||
|
||||
check_for_changes(&path)?;
|
||||
|
||||
Ok(())
|
||||
|
@ -150,3 +162,63 @@ fn check_for_changes(path: &Path) -> Result<(), Failed> {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Assemble the output for a test, with queries elaborated in-line.
|
||||
fn assemble_query_output(
|
||||
writer: &mut impl io::Write,
|
||||
source: &str,
|
||||
sorted_queries: Vec<InferredQuery>,
|
||||
) -> io::Result<()> {
|
||||
// Reverse the queries so that we can pop them off the end as we pass through the lines.
|
||||
let mut sorted_queries = sorted_queries;
|
||||
sorted_queries.reverse();
|
||||
|
||||
for (i, line) in source.lines().enumerate() {
|
||||
let mut is_query_line = false;
|
||||
|
||||
while matches!(
|
||||
sorted_queries.last(),
|
||||
Some(InferredQuery {
|
||||
source_line_column,
|
||||
..
|
||||
}) if source_line_column.line == i as _
|
||||
) {
|
||||
let InferredQuery {
|
||||
output,
|
||||
comment_column,
|
||||
source_line_column,
|
||||
source,
|
||||
} = sorted_queries.pop().unwrap();
|
||||
|
||||
reconstruct_comment_line(writer, &source, source_line_column, comment_column, output)?;
|
||||
|
||||
writeln!(writer)?;
|
||||
|
||||
is_query_line = true;
|
||||
}
|
||||
|
||||
if !is_query_line {
|
||||
write!(writer, "{line}\n")?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn reconstruct_comment_line(
|
||||
writer: &mut impl io::Write,
|
||||
source: &str,
|
||||
source_line_column: LineColumn,
|
||||
comment_column: u32,
|
||||
output: String,
|
||||
) -> io::Result<()> {
|
||||
for _ in 0..comment_column {
|
||||
write!(writer, " ")?;
|
||||
}
|
||||
write!(writer, "#")?;
|
||||
for _ in 0..(source_line_column.column - comment_column - 1) {
|
||||
write!(writer, " ")?;
|
||||
}
|
||||
write!(writer, "{source} {output}")?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
app "test" provides [main] to "./platform"
|
||||
|
||||
main = Bool.isEq Bool.true Bool.false
|
||||
# ^^^^^^^^^
|
||||
# ^^^^^^^^^ Eq#Bool.isEq(9) : Bool, Bool -[[Bool.structuralEq(11)]]-> Bool
|
||||
|
|
|
@ -134,8 +134,13 @@ lazy_static! {
|
|||
Regex::new(r#"(?P<where>\^+)(?:\{-(?P<sub>\d+)\})?"#).unwrap();
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct TypeQuery(Region);
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct TypeQuery {
|
||||
query_region: Region,
|
||||
source: String,
|
||||
comment_column: u32,
|
||||
source_line_column: LineColumn,
|
||||
}
|
||||
|
||||
/// Parse inference queries in a Roc program.
|
||||
/// See [RE_TYPE_QUERY].
|
||||
|
@ -144,6 +149,16 @@ fn parse_queries(src: &str) -> Vec<TypeQuery> {
|
|||
let mut queries = vec![];
|
||||
let mut consecutive_query_lines = 0;
|
||||
for (i, line) in src.lines().enumerate() {
|
||||
// If this is a query line, it should start with a comment somewhere before the query
|
||||
// lines.
|
||||
let comment_column = match line.find("#") {
|
||||
Some(i) => i as _,
|
||||
None => {
|
||||
consecutive_query_lines = 0;
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
let mut queries_on_line = RE_TYPE_QUERY.captures_iter(line).into_iter().peekable();
|
||||
|
||||
if queries_on_line.peek().is_none() {
|
||||
|
@ -154,28 +169,46 @@ fn parse_queries(src: &str) -> Vec<TypeQuery> {
|
|||
}
|
||||
|
||||
for capture in queries_on_line {
|
||||
let source = capture
|
||||
.get(0)
|
||||
.expect("full capture must always exist")
|
||||
.as_str()
|
||||
.to_string();
|
||||
|
||||
let wher = capture.name("where").unwrap();
|
||||
let subtract_col = capture
|
||||
.name("sub")
|
||||
.and_then(|m| str::parse(m.as_str()).ok())
|
||||
.unwrap_or(0);
|
||||
|
||||
let (start, end) = (wher.start() as u32, wher.end() as u32);
|
||||
let (start, end) = (start - subtract_col, end - subtract_col);
|
||||
let (source_start, source_end) = (wher.start() as u32, wher.end() as u32);
|
||||
let (query_start, query_end) = (source_start - subtract_col, source_end - subtract_col);
|
||||
|
||||
let source_line_column = LineColumn {
|
||||
line: i as u32,
|
||||
column: source_start,
|
||||
};
|
||||
|
||||
let query_region = {
|
||||
let last_line = i as u32 - consecutive_query_lines;
|
||||
let start_lc = LineColumn {
|
||||
let query_start_lc = LineColumn {
|
||||
line: last_line,
|
||||
column: start,
|
||||
column: query_start,
|
||||
};
|
||||
let end_lc = LineColumn {
|
||||
let query_end_lc = LineColumn {
|
||||
line: last_line,
|
||||
column: end,
|
||||
column: query_end,
|
||||
};
|
||||
let query_lc_region = LineColumnRegion::new(query_start_lc, query_end_lc);
|
||||
line_info.convert_line_column_region(query_lc_region)
|
||||
};
|
||||
let lc_region = LineColumnRegion::new(start_lc, end_lc);
|
||||
let region = line_info.convert_line_column_region(lc_region);
|
||||
|
||||
queries.push(TypeQuery(region));
|
||||
queries.push(TypeQuery {
|
||||
query_region,
|
||||
source,
|
||||
comment_column,
|
||||
source_line_column,
|
||||
});
|
||||
}
|
||||
}
|
||||
queries
|
||||
|
@ -189,8 +222,13 @@ pub struct InferOptions {
|
|||
}
|
||||
|
||||
pub struct InferredQuery {
|
||||
pub region: Region,
|
||||
pub output: String,
|
||||
/// Where the comment before the query string was written in the source.
|
||||
pub comment_column: u32,
|
||||
/// Where the query string "^^^" itself was written in the source.
|
||||
pub source_line_column: LineColumn,
|
||||
/// The content of the query string.
|
||||
pub source: String,
|
||||
}
|
||||
|
||||
pub struct InferredProgram {
|
||||
|
@ -200,6 +238,15 @@ pub struct InferredProgram {
|
|||
inferred_queries: Vec<InferredQuery>,
|
||||
}
|
||||
|
||||
impl InferredProgram {
|
||||
/// Returns all inferred queries, sorted by their source location.
|
||||
pub fn into_sorted_queries(self) -> Vec<InferredQuery> {
|
||||
let mut inferred = self.inferred_queries;
|
||||
inferred.sort_by_key(|iq| iq.source_line_column);
|
||||
inferred
|
||||
}
|
||||
}
|
||||
|
||||
pub fn infer_queries(src: &str, options: InferOptions) -> Result<InferredProgram, Box<dyn Error>> {
|
||||
let (
|
||||
LoadedModule {
|
||||
|
@ -239,12 +286,18 @@ pub fn infer_queries(src: &str, options: InferOptions) -> Result<InferredProgram
|
|||
}
|
||||
|
||||
let mut inferred_queries = Vec::with_capacity(queries.len());
|
||||
for TypeQuery(region) in queries.into_iter() {
|
||||
let start = region.start().offset;
|
||||
let end = region.end().offset;
|
||||
for TypeQuery {
|
||||
query_region,
|
||||
source,
|
||||
comment_column,
|
||||
source_line_column,
|
||||
} in queries.into_iter()
|
||||
{
|
||||
let start = query_region.start().offset;
|
||||
let end = query_region.end().offset;
|
||||
let text = &src[start as usize..end as usize];
|
||||
let var = find_type_at(region, &declarations)
|
||||
.ok_or_else(|| format!("No type for {:?} ({:?})!", &text, region))?;
|
||||
let var = find_type_at(query_region, &declarations)
|
||||
.ok_or_else(|| format!("No type for {:?} ({:?})!", &text, query_region))?;
|
||||
|
||||
let snapshot = subs.snapshot();
|
||||
let actual_str = name_and_print_var(
|
||||
|
@ -261,8 +314,11 @@ pub fn infer_queries(src: &str, options: InferOptions) -> Result<InferredProgram
|
|||
);
|
||||
subs.rollback_to(snapshot);
|
||||
|
||||
let elaborated =
|
||||
match find_ability_member_and_owning_type_at(region, &declarations, &abilities_store) {
|
||||
let elaborated = match find_ability_member_and_owning_type_at(
|
||||
query_region,
|
||||
&declarations,
|
||||
&abilities_store,
|
||||
) {
|
||||
Some((spec_type, spec_symbol)) => {
|
||||
format!(
|
||||
"{}#{}({}) : {}",
|
||||
|
@ -278,8 +334,10 @@ pub fn infer_queries(src: &str, options: InferOptions) -> Result<InferredProgram
|
|||
};
|
||||
|
||||
inferred_queries.push(InferredQuery {
|
||||
region,
|
||||
output: elaborated,
|
||||
comment_column,
|
||||
source_line_column,
|
||||
source,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue