#![allow(dead_code)]
use slicec::ast::Ast;
use slicec::compilation_state::CompilationState;
use slicec::compile_from_strings;
use slicec::diagnostics::Diagnostic;
use slicec::slice_options::SliceOptions;
#[must_use]
pub fn parse(slice: impl Into<String>, options: Option<&SliceOptions>) -> CompilationState {
compile_from_strings(&[&slice.into()], options)
}
#[must_use]
pub fn parse_for_ast(slice: impl Into<String>) -> Ast {
let compilation_state = parse(slice, None);
if compilation_state.diagnostics.has_errors() {
panic!("{:?}", compilation_state.diagnostics);
}
compilation_state.ast
}
#[must_use]
pub fn parse_multiple_for_ast(slice: &[&str]) -> Ast {
let compilation_state = compile_from_strings(slice, None);
if !compilation_state.diagnostics.is_empty() {
panic!("{:?}", compilation_state.diagnostics);
}
compilation_state.ast
}
#[must_use]
pub fn parse_for_diagnostics(slice: impl Into<String>) -> Vec<Diagnostic> {
parse_multiple_for_diagnostics(&[&slice.into()])
}
#[must_use]
pub fn parse_multiple_for_diagnostics(slice: &[&str]) -> Vec<Diagnostic> {
compile_from_strings(slice, None).diagnostics.into_inner()
}
pub fn assert_parses(slice: impl Into<String>) {
let diagnostics = parse_for_diagnostics(slice);
let expected: [Diagnostic; 0] = []; check_diagnostics(diagnostics, expected);
}
pub fn check_diagnostics<const L: usize>(diagnostics: Vec<Diagnostic>, expected: [impl Into<Diagnostic>; L]) {
if expected.len() != diagnostics.len() {
eprintln!(
"Expected {} diagnostics, but got {}.",
expected.len(),
diagnostics.len()
);
eprintln!("The emitted diagnostics were:");
for diagnostic in diagnostics {
eprintln!("\t{diagnostic:?}");
}
eprintln!();
panic!("test failure");
}
for (expect, diagnostic) in expected.into_iter().zip(diagnostics) {
let expect: Diagnostic = expect.into();
let mut failed = false;
if expect.code() != diagnostic.code() {
eprintln!("diagnostic codes didn't match:");
eprintln!("\texpected '{:?}', but got '{:?}'", expect.code(), diagnostic.code());
failed = true;
}
if expect.message() != diagnostic.message() {
eprintln!("diagnostic messages didn't match:");
eprintln!("\texpected: \"{}\"", expect.message());
eprintln!("\t but got: \"{}\"", diagnostic.message());
failed = true;
}
if expect.span.is_some() && expect.span != diagnostic.span {
eprintln!("diagnostic spans didn't match:");
eprintln!("\texpected: \"{:?}\"", expect.span);
eprintln!("\t but got: \"{:?}\"", diagnostic.span);
failed = true;
}
if expect.scope.is_some() && expect.scope != diagnostic.scope {
eprintln!("diagnostic scopes didn't match:");
eprintln!("\texpected: \"{:?}\"", expect.scope);
eprintln!("\t but got: \"{:?}\"", diagnostic.scope);
failed = true;
}
if !expect.notes.is_empty() {
let expected_notes = expect.notes;
let emitted_notes = diagnostic.notes;
if expected_notes.len() != emitted_notes.len() {
eprintln!(
"Expected {} notes, but got {}.",
expected_notes.len(),
emitted_notes.len()
);
eprintln!("The emitted notes were:");
for note in emitted_notes {
eprintln!("\t{note:?}");
}
failed = true;
} else {
for (expected_note, emitted_note) in expected_notes.iter().zip(emitted_notes) {
if expected_note.message != emitted_note.message {
eprintln!("note messages didn't match:");
eprintln!("\texpected: \"{}\"", expected_note.message);
eprintln!("\t but got: \"{}\"", emitted_note.message);
failed = true;
}
if expected_note.span.is_some() && expected_note.span != emitted_note.span {
eprintln!("note spans didn't match:");
eprintln!("\texpected: \"{:?}\"", expected_note.span);
eprintln!("\t but got: \"{:?}\"", emitted_note.span);
failed = true;
}
}
}
}
if failed {
eprintln!();
panic!("test failure");
}
}
}