1#![cfg(test)]23use miette::{Diagnostic, GraphicalReportHandler, LabeledSpan};4use thiserror::Error;56use crate::parser::parse;78#[derive(Debug, Error)]9#[error("syntax error")]10struct MyDiagnostic {11 code: String,12 spans: Vec<LabeledSpan>,13}14impl Diagnostic for MyDiagnostic {15 fn code<'a>(&'a self) -> Option<Box<dyn std::fmt::Display + 'a>> {16 None17 }1819 fn severity(&self) -> Option<miette::Severity> {20 None21 }2223 fn help<'a>(&'a self) -> Option<Box<dyn std::fmt::Display + 'a>> {24 None25 }2627 fn url<'a>(&'a self) -> Option<Box<dyn std::fmt::Display + 'a>> {28 None29 }3031 fn source_code(&self) -> Option<&dyn miette::SourceCode> {32 Some(&self.code)33 }3435 fn labels(&self) -> Option<Box<dyn Iterator<Item = miette::LabeledSpan> + '_>> {36 Some(Box::new(self.spans.clone().into_iter()))37 }3839 fn related<'a>(&'a self) -> Option<Box<dyn Iterator<Item = &'a dyn Diagnostic> + 'a>> {40 None41 }42}4344fn process(text: &str) -> String {45 use std::fmt::Write;46 let mut out = String::new();47 let node = parse(text);48 write!(out, "{:#?}", node.syntax()).unwrap();49 if !node.errors.is_empty() && !text.is_empty() {50 writeln!(out, "===").unwrap();51 for err in &node.errors {52 writeln!(out, "{:?}", err).unwrap();53 }54 let diag = MyDiagnostic {55 code: text.to_string(),56 spans: node.errors.into_iter().map(|e| e.into()).collect(),57 };5859 let handler = GraphicalReportHandler::new();6061 write!(out, "===").unwrap();62 handler.render_report(&mut out, &diag).unwrap();63 }64 out65}66macro_rules! mk_test {67 ($($name:ident => $test:expr)+) => {$(68 #[test]69 fn $name() {70 let src = indoc::indoc!($test);71 let result = process(&src);72 insta::assert_snapshot!(stringify!($name), result, src);7374 }75 )+};76 }77mk_test!(78 empty => r#" "#79 function => r#"80 function(a, b = 1) a + b81 "#82 function_error_no_value => r#"83 function(a, b = ) a + b84 "#85 function_error_rparen => r#"86 function(a, b87 "#88 function_error_body => r#"89 function(a, b)90 "#91 local_novalue => r#"92 local a =93 "#94 local_no_value_recovery => r#"95 local a =96 local b = 3;97 198 "#99100 array_comp => r#"101 [a for a in [1, 2, 3]]102 "#103 array_comp_incompatible_with_multiple_elems => r#"104 [a for a in [1, 2, 3], b]105 "#106107 no_rhs => r#"108 a +109 "#110 no_lhs => r#"111 + 2112 "#113 no_operator => "114 2 2115 "116117 named_before_positional => "118 a(1, 2, b=4, 3, 5, k = 12, 6)119 "120121 wrong_field_end => "122 {123 a: 1;124 b: 2;125 }126 "127);