12#![cfg(test)]34use hi_doc::{Formatting, SnippetBuilder, Text};5use thiserror::Error;67use crate::{parse, AstNode};89fn process(text: &str) -> String {10 use std::fmt::Write;11 let mut out = String::new();12 let (node, errors) = parse(text);13 write!(out, "{:#?}", node.syntax()).unwrap();14 if !errors.is_empty() && !text.is_empty() {15 writeln!(out, "===").unwrap();16 for err in &errors {17 writeln!(out, "{:?}", err).unwrap();18 }19 let mut code = text.to_string();2021 22 if code.ends_with('\n') {23 code.truncate(code.len() - 1);24 code += " ";25 }26 code += " ";2728 let mut s = SnippetBuilder::new(code);2930 for error in errors {31 s.error(Text::fragment(32 format!("{}", error.error),33 Formatting::default(),34 ))35 .range(error.range.start().into()..=error.range.end().into())36 .build();37 }3839 writeln!(out, "===").unwrap();40 let ansi = hi_doc::source_to_ansi(&s.build());41 let text = strip_ansi_escapes::strip_str(&ansi);42 out.push_str(&text);43 }44 out.split('\n')45 .map(|s| s.trim_end().to_string())46 .collect::<Vec<String>>()47 .join("\n")48 .trim_end()49 .to_string()50}51macro_rules! mk_test {52 ($($name:ident => $test:expr)+) => {$(53 #[test]54 fn $name() {55 let src = indoc::indoc!($test);56 let result = process(&src);57 insta::assert_snapshot!(stringify!($name), result, src);58 }59 )+};60 }61mk_test!(62 empty => r#" "#63 function => r#"64 function(a, b = 1) a + b65 "#66 function_error_no_value => r#"67 function(a, b = ) a + b68 "#69 function_error_rparen => r#"70 function(a, b71 "#72 function_error_body => r#"73 function(a, b)74 "#75 local_novalue => r#"76 local a =77 "#78 local_no_value_recovery => r#"79 local a =80 local b = 3;81 182 "#838485 no_rhs => r#"86 a +87 "#88 no_lhs => r#"89 + 290 "#91 no_operator => "92 2 293 "9495 named_before_positional => "96 a(1, 2, b=4, 3, 5, k = 12, 6)97 "9899 wrong_field_end => "100 {101 a: 1;102 b: 2;103 }104 "105106107 plain_call => "108 std.substr(a, 0, std.length(b)) == b109 "110111 destruct => "112 local [a, b, c] = arr;113 local [a, ...] = arr_rest;114 local [..., a] = rest_arr;115 local [...] = rest_in_arr;116 local [a, ...n] = arr_rest_n;117 local [...n, a] = rest_arr_n;118 local [...n] = rest_in_arr_n;119120 local {a, b, c} = obj;121 local {a, b, c, ...} = obj_rest;122 local {a, b, c, ...n} = obj_rest_n;123124 null125 "126127 str_block_missing_indent => "128 |||129 "130 str_block_missing_termination => "131 |||132 hello133 "134 str_block_missing_newline => "135 |||hello136 "137 str_block_missing_indent_text => "138 |||139 hello140 "141142 unexpected_destruct => "143 local * = 1;144 a145 "146 arr_compspec => r#"147 [a for a in [1, 2, 3]]148 "#149 arr_compspec_comma => "150 [a, for a in [1, 2, 3]]151 "152 arr_compspec_no_elems => "153 [for a in [1, 2, 3]]154 "155 arr_compspec_incompatible_with_multiple_elems => r#"156 [a for a in [1, 2, 3], b]157 "#158 arr_compspec_incompatible_with_multiple_elems_w => r#"159 [a, b, for a in [1, 2, 3], c]160 "#161162 obj_compspec => r#"163 {a:1 for a in [1, 2, 3]}164 "#165 obj_compspec_comma => "166 {a:1, for a in [1, 2, 3]}167 "168 obj_compspec_no_elems => "169 {for a in [1, 2, 3]}170 "171 obj_compspec_incompatible_with_multiple_elems => r#"172 {a:1 for a in [1, 2, 3], b:1}173 "#174 obj_compspec_incompatible_with_multiple_elems_w => r#"175 {a:1, b:1, for a in [1, 2, 3], c:1}176 "#177178 obj_compspec_incompatible_with_asserts => r#"179 {assert 1, a: 1 for a in [1,2,3]}180 "#181182 local_method => r#"183 local184 a(x) = x,185 a = function(x) x,186 ; c187 "#188 obj_method => r#"189 {190 a(x): x,191 a: function(x) x,192 }193 "#194195 continue_after_total_failure => r#"196 local intr = $intrinsic(test);197198 local a = 1, b = 2, c = a + b;199200 [c]201 "#202203 super_nesting => r#"204 super.a + super.b205 "#206207 string_block_trim => r#"208 |||-209 Trimmed text block210 |||211 "#212);213214#[test]215fn eval_simple() {216 let src = "local a = 1, b = 2; a + local c = 1; c";217 let (node, _errors) = parse(src);218219 dbg!(node);220}