[fine] Automatic rebase support for CST
This commit is contained in:
parent
1f6d7ec131
commit
26871aa9ae
6 changed files with 122 additions and 8 deletions
|
|
@ -33,8 +33,9 @@ fn generate_test_for_file(path: PathBuf) -> String {
|
|||
}
|
||||
|
||||
let concrete_comparison = if let Some(concrete) = concrete_stuff {
|
||||
let display_path = path.display().to_string();
|
||||
quote! {
|
||||
crate::assert_concrete(&_tree, #concrete)
|
||||
crate::assert_concrete(&_tree, #concrete, #display_path)
|
||||
}
|
||||
} else {
|
||||
quote! {}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,84 @@
|
|||
use fine::parser::concrete::Tree;
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
fn assert_concrete(tree: &Tree, expected: &str) {
|
||||
assert_eq!(tree.dump(), expected, "concrete syntax trees did not match");
|
||||
fn rebase_concrete(source_path: &str, dump: &str) {
|
||||
// RE-BASE
|
||||
let contents = std::fs::read_to_string(source_path)
|
||||
.expect(&format!("unable to read input file {}", source_path));
|
||||
|
||||
let mut result = String::new();
|
||||
let mut lines = contents.lines();
|
||||
|
||||
let mut found_concrete_section = false;
|
||||
while let Some(line) = lines.next() {
|
||||
result.push_str(line);
|
||||
result.push_str("\n");
|
||||
|
||||
if line == "// concrete:" {
|
||||
found_concrete_section = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if !found_concrete_section {
|
||||
panic!(
|
||||
"unable to locate the concrete section in {}. Is there a line that starts with '// concrete:'?",
|
||||
source_path
|
||||
);
|
||||
}
|
||||
|
||||
let mut replaced_output = false;
|
||||
while let Some(line) = lines.next() {
|
||||
if line.starts_with("// | ") {
|
||||
// Skip copying lines here, because we're skipping
|
||||
// the existing concrete syntax tree.
|
||||
} else {
|
||||
// OK we're out of concrete syntax tree; copy in the
|
||||
// new CST. (We do this inline so we don't lose
|
||||
// `line`.)
|
||||
for expected_line in dump.lines() {
|
||||
result.push_str("// | ");
|
||||
result.push_str(expected_line);
|
||||
result.push_str("\n");
|
||||
}
|
||||
|
||||
// (Make sure not to drop this line.)
|
||||
result.push_str(line);
|
||||
result.push_str("\n");
|
||||
|
||||
replaced_output = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if !replaced_output {
|
||||
panic!(
|
||||
"didn't actually replace the output section in {}",
|
||||
source_path
|
||||
);
|
||||
}
|
||||
|
||||
// Now just copy the rest of the lines.
|
||||
while let Some(line) = lines.next() {
|
||||
result.push_str(line);
|
||||
result.push_str("\n");
|
||||
}
|
||||
|
||||
// ... and re-write the file.
|
||||
std::fs::write(source_path, result).expect("unable to write the new file!");
|
||||
}
|
||||
|
||||
fn assert_concrete(tree: &Tree, expected: &str, source_path: &str) {
|
||||
let dump = tree.dump();
|
||||
let rebase = std::env::var("FINE_TEST_REBASE")
|
||||
.unwrap_or(String::new())
|
||||
.to_lowercase();
|
||||
match rebase.as_str() {
|
||||
"1" | "true" | "yes" | "y" => {
|
||||
if dump != expected {
|
||||
rebase_concrete(source_path, &dump)
|
||||
}
|
||||
}
|
||||
_ => assert_eq!(expected, dump, "concrete syntax trees did not match (set FINE_TEST_REBASE=1 to auto-rebase if the diff is expected)"),
|
||||
}
|
||||
}
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/generated_tests.rs"));
|
||||
|
|
|
|||
|
|
@ -1,10 +1,6 @@
|
|||
// concrete:
|
||||
// | File
|
||||
// | ExpressionStatement
|
||||
// | LiteralExpression
|
||||
// | Number:'"42"'
|
||||
// | Semicolon:'";"'
|
||||
// | ExpressionStatement
|
||||
// | BinaryExpression
|
||||
// | BinaryExpression
|
||||
// | LiteralExpression
|
||||
|
|
@ -23,5 +19,4 @@
|
|||
// | Number:'"4"'
|
||||
// | Semicolon:'";"'
|
||||
//
|
||||
42;
|
||||
1 * 2 + -3 * 4;
|
||||
22
fine/tests/expression/boolean.fine
Normal file
22
fine/tests/expression/boolean.fine
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
// concrete:
|
||||
// | File
|
||||
// | ExpressionStatement
|
||||
// | BinaryExpression
|
||||
// | BinaryExpression
|
||||
// | LiteralExpression
|
||||
// | True:'"true"'
|
||||
// | And:'"and"'
|
||||
// | LiteralExpression
|
||||
// | False:'"false"'
|
||||
// | Or:'"or"'
|
||||
// | BinaryExpression
|
||||
// | LiteralExpression
|
||||
// | False:'"false"'
|
||||
// | And:'"and"'
|
||||
// | UnaryExpression
|
||||
// | Bang:'"!"'
|
||||
// | LiteralExpression
|
||||
// | True:'"true"'
|
||||
// | Semicolon:'";"'
|
||||
//
|
||||
true and false or false and !true;
|
||||
8
fine/tests/expression/number.fine
Normal file
8
fine/tests/expression/number.fine
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
// concrete:
|
||||
// | File
|
||||
// | ExpressionStatement
|
||||
// | LiteralExpression
|
||||
// | Number:'"42"'
|
||||
// | Semicolon:'";"'
|
||||
//
|
||||
42;
|
||||
12
fine/tests/expression/strings.fine
Normal file
12
fine/tests/expression/strings.fine
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
// concrete:
|
||||
// | File
|
||||
// | ExpressionStatement
|
||||
// | BinaryExpression
|
||||
// | LiteralExpression
|
||||
// | String:'"\"Hello \""'
|
||||
// | Plus:'"+"'
|
||||
// | LiteralExpression
|
||||
// | String:'"'world!'"'
|
||||
// | Semicolon:'";"'
|
||||
//
|
||||
"Hello " + 'world!';
|
||||
Loading…
Add table
Add a link
Reference in a new issue