// Copyright Two Neutron Stars Incorporated and contributors
// SPDX-License-Identifier: BlueOak-1.0.0

/// Create a test case for the AST Macro
///
/// ```
/// ast_test_case! {
///   ident_discard(
///     #[laburnum_syntax(AST)]
///     pub struct Callable {
///       path: NodeId<crate::ty::Path, crate::symbol::Ident>,
///       args: Vec<NodeId<crate::callable::Argument>>,
///       expr: Option<NodeId<crate::expression::Inline>>,
///     }
///   )
/// }
/// ```
#[macro_export]
macro_rules! ast_test_case {
( $( $(#[$meta:meta])* $name:ident( $($input:tt)* ) $(,)? )+ ) => {
    $(
      #[test_log::test]
      fn $name() {
        let mut snapshot = ferrotype::Ferrotype::new();

        let expect_errs = attr_error!{$($meta)?};
        snapshot.set_expect_errors(
          expect_errs,
        );

        let src = quote!($( $input )* );

        snapshot.add_token_stream("Source", &src);

        match process(
          quote!(#src),
          $crate::Args::ast(),
        ) {
          | Ok(ts) => {
            snapshot.add_token_stream("Output", &ts);

            if expect_errs {
              snapshot.print();
              panic!("Expected error, but got: {:#?}", ts);
            }
          },
          | Err(e) => {
            snapshot.add_debug("Error", &e);
            if !expect_errs {
              snapshot.print();
              panic!("Unexpected error: {:#?}", e);
            }
          },
        }

        assert!(snapshot);
      }
    )+
  };
}

// -- attr_error ---------------------------------------------------------------
/// Usage
/// ```
/// assert_eq!(mylang_error::attr_error! {error}, true);
/// assert_eq!(mylang_error::attr_error! {}, false);
/// ```
#[macro_export]
macro_rules! attr_error {
  // Quick rule to convert #[error] into a boolean
  () => {
    false
  };

  (error) => {
    true
  };
}
