git.delta.rocks / jrsonnet / refs/commits / 6beafa85136f

difftreelog

source

crates/jrsonnet-rowan-parser/src/tests.rs3.5 KiBsourcehistory
1#![cfg(test)]23use miette::{4	Diagnostic, GraphicalReportHandler, GraphicalTheme, LabeledSpan, ThemeCharacters, ThemeStyles,5};6use thiserror::Error;78use crate::{parse, AstNode};910#[derive(Debug, Error)]11#[error("syntax error")]12struct MyDiagnostic {13	code: String,14	spans: Vec<LabeledSpan>,15}16impl Diagnostic for MyDiagnostic {17	fn code<'a>(&'a self) -> Option<Box<dyn std::fmt::Display + 'a>> {18		None19	}2021	fn severity(&self) -> Option<miette::Severity> {22		None23	}2425	fn help<'a>(&'a self) -> Option<Box<dyn std::fmt::Display + 'a>> {26		None27	}2829	fn url<'a>(&'a self) -> Option<Box<dyn std::fmt::Display + 'a>> {30		None31	}3233	fn source_code(&self) -> Option<&dyn miette::SourceCode> {34		Some(&self.code)35	}3637	fn labels(&self) -> Option<Box<dyn Iterator<Item = miette::LabeledSpan> + '_>> {38		Some(Box::new(self.spans.clone().into_iter()))39	}4041	fn related<'a>(&'a self) -> Option<Box<dyn Iterator<Item = &'a dyn Diagnostic> + 'a>> {42		None43	}44}4546fn process(text: &str) -> String {47	use std::fmt::Write;48	let mut out = String::new();49	let (node, errors) = parse(text);50	write!(out, "{:#?}", node.syntax()).unwrap();51	if !errors.is_empty() && !text.is_empty() {52		writeln!(out, "===").unwrap();53		for err in &errors {54			writeln!(out, "{:?}", err).unwrap();55		}56		let mut code = text.to_string();5758		// Prettier errors at EOF position59		if code.ends_with('\n') {60			code.truncate(code.len() - 1);61			code += " ";62		}63		code += " ";6465		let diag = MyDiagnostic {66			code,67			spans: errors.into_iter().map(|e| e.into()).collect(),68		};6970		let handler = GraphicalReportHandler::new_themed(GraphicalTheme {71			characters: ThemeCharacters::ascii(),72			styles: ThemeStyles::none(),73		});7475		write!(out, "===").unwrap();76		handler77			.render_report(&mut out, &diag)78			.expect("fmt error?..");79	}80	out.split('\n')81		.map(|s| s.trim_end().to_string())82		.collect::<Vec<String>>()83		.join("\n")84		.trim_end()85		.to_string()86}87macro_rules! mk_test {88		($($name:ident => $test:expr)+) => {$(89			#[test]90			fn $name() {91				let src = indoc::indoc!($test);92				let result = process(&src);93				insta::assert_snapshot!(stringify!($name), result, src);9495			}96		)+};97	}98mk_test!(99	empty => r#" "#100	function => r#"101		function(a, b = 1) a + b102	"#103	function_error_no_value => r#"104		function(a, b = ) a + b105	"#106	function_error_rparen => r#"107		function(a, b108	"#109	function_error_body => r#"110		function(a, b)111	"#112	local_novalue => r#"113		local a =114	"#115	local_no_value_recovery => r#"116		local a =117		local b = 3;118		1119	"#120121	array_comp => r#"122		[a for a in [1, 2, 3]]123	"#124	array_comp_incompatible_with_multiple_elems => r#"125		[a for a in [1, 2, 3], b]126	"#127128	no_rhs => r#"129		a +130	"#131	no_lhs => r#"132		+ 2133	"#134	no_operator => "135		2 2136	"137138	named_before_positional => "139		a(1, 2, b=4, 3, 5, k = 12, 6)140	"141142	wrong_field_end => "143		{144			a: 1;145			b: 2;146		}147	"148149150	plain_call => "151		std.substr(a, 0, std.length(b)) == b152	"153154	destruct => "155		local [a, b, c] = arr;156		local [a, ...] = arr_rest;157		local [..., a] = rest_arr;158		local [...] = rest_in_arr;159		local [a, ...n] = arr_rest_n;160		local [...n, a] = rest_arr_n;161		local [...n] = rest_in_arr_n;162163		local {a, b, c} = obj;164		local {a, b, c, ...} = obj_rest;165		local {a, b, c, ...n} = obj_rest_n;166167		null168	"169170	str_block_missing_indent => "171		|||172	"173	str_block_missing_termination => "174		|||175			hello176	"177	str_block_missing_newline => "178		|||hello179	"180	str_block_missing_indent_text => "181		|||182		hello183	"184185	unexpected_destruct => "186		local * = 1;187		a188	"189);190191#[test]192fn stdlib() {193	let src = include_str!("../../jrsonnet-stdlib/src/std.jsonnet");194	let result = process(src);195	insta::assert_snapshot!("stdlib", result, src);196}