// Part of the Crubit project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

/// Like `token_stream_matchers::assert_cc_matches!`, but expects `IR` instance
/// as input. The macro converts the instance to its corresponding struct
/// expression and matches the pattern against that.  See the documentation of
/// `token_stream_matchers` for more information.
///
/// Example:
/// ```rust
///    let ir = ir_from_cc(..., "struct SomeStruct {};').unwrap();
///    assert_ir_matches!(
///        ir,
///        quote! {
///            Record {
///                rs_name: "SomeStruct" ...
///            }
///        }
///    );
/// ```
#[macro_export]
macro_rules! assert_ir_matches {
    ($ir:expr, $pattern:expr $(,)*) => {
        $crate::internal::match_ir(&$ir, &$pattern)
            .expect("input unexpectedly didn't match the pattern");
    };
}

/// Like `assert_ir_matches`, but asserts that the pattern does not match the
/// `IR`.
#[macro_export]
macro_rules! assert_ir_not_matches {
    ($ir:expr, $pattern:expr $(,)*) => {
        $crate::internal::mismatch_ir(&$ir, &$pattern).unwrap();
    };
}

/// Like `assert_ir_matches!`, but expects a list of Items and a list of
/// TokenStreams as input. The macro converts each Item to its struct expression
/// and matches the corresponding pattern against that.
/// The use case for this macro is to compare a list of Items to expected
/// patterns, e.g when we want to confirm that the children items of an item
/// appear in a certain order.
#[macro_export]
macro_rules! assert_items_match {
    ($items:expr, $patterns:expr $(,)*) => {
        assert_eq!($items.len(), $patterns.len());
        for (idx, (item, pattern)) in $items.into_iter().zip($patterns).enumerate() {
            $crate::internal::match_item(&item, &pattern).expect(&format!(
                "input at position {} unexpectedly didn't match the pattern",
                &idx
            ));
        }
    };
}

/// Only used to make stuff needed by exported macros available
pub mod internal {

    use anyhow::Result;
    use ir::{Item, IR};
    use itertools::Itertools;
    pub use proc_macro2::TokenStream;
    use quote::quote;
    pub use token_stream_printer::{
        rs_tokens_to_formatted_string, rs_tokens_to_formatted_string_for_tests,
    };

    pub fn match_ir(ir: &IR, pattern: &TokenStream) -> Result<()> {
        token_stream_matchers::internal::match_tokens(
            &ir_to_token_stream(ir)?,
            pattern,
            &ir_to_string,
        )
    }

    pub fn mismatch_ir(ir: &IR, pattern: &TokenStream) -> Result<()> {
        token_stream_matchers::internal::mismatch_tokens(
            &ir_to_token_stream(ir)?,
            pattern,
            &ir_to_string,
        )
    }

    fn ir_to_token_stream(ir: &IR) -> Result<TokenStream> {
        // derived debug impl doesn't emit commas after the last element of a group,
        // (for example `[a, b, c]`), but rustfmt automatically adds it (`[a, b,
        // c,]`). We use rustfmt to format the failure messages. So to make the
        // input token stream consistent with failure messages we format the
        // input token stream with rustfmt as well.
        Ok(ir_to_string(ir.flat_ir_debug_print().parse().unwrap())?.parse().unwrap())
    }

    fn ir_to_string(input: TokenStream) -> Result<String> {
        // Rustfmt refuses to format some kinds of invalid Rust code. Let's put our IR
        // struct expression into the body of a function, format it, and then remove
        // the function.
        let input_stream = quote! { fn make_rustfmt_happy() { #input } };
        let formatted = rs_tokens_to_formatted_string_for_tests(input_stream)?;
        let snippet = formatted
            .strip_prefix("fn make_rustfmt_happy() {\n")
            .unwrap()
            .strip_suffix("}\n")
            .unwrap()
            .lines()
            .map(|line| &line[4..])
            .join("\n");
        Ok(snippet)
    }

    pub fn match_item(item: &Item, pattern: &TokenStream) -> Result<()> {
        token_stream_matchers::internal::match_tokens(
            &item_to_token_stream(item)?,
            pattern,
            &ir_to_string,
        )
    }

    fn item_to_token_stream(item: &Item) -> Result<TokenStream> {
        // derived debug impl doesn't emit commas after the last element of a group,
        // (for example `[a, b, c]`), but rustfmt automatically adds it (`[a, b,
        // c,]`). We use rustfmt to format the failure messages. So to make the
        // input token stream consistent with failure messages we format the
        // input token stream with rustfmt as well.
        Ok(ir_to_string(format! {"{:?}", item}.parse().unwrap())?.parse().unwrap())
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use quote::quote;

    /// We aren't testing platform-specific details, just the matchers.
    fn ir_from_cc(header: &str) -> arc_anyhow::Result<ir::IR> {
        ir_testing::ir_from_cc(multiplatform_testing::Platform::X86Linux, header)
    }

    #[test]
    fn test_optional_trailing_comma() {
        assert_ir_matches!(ir_from_cc("").unwrap(), quote! { FlatIR { ... }});
        assert_ir_matches!(ir_from_cc("").unwrap(), quote! { FlatIR { ... }},);

        assert_ir_not_matches!(ir_from_cc("").unwrap(), quote! {this pattern is not in the ir});
        assert_ir_not_matches!(ir_from_cc("").unwrap(), quote! {this pattern is not in the ir},);
    }

    #[test]
    fn test_assert_ir_matches_assumes_trailing_commas_in_groups() {
        assert_ir_matches!(ir_from_cc("").unwrap(), quote! {{... , }});
    }

    #[test]
    fn test_assert_not_matches_accepts_not_matching_pattern() {
        assert_ir_not_matches!(ir_from_cc("").unwrap(), quote! {this pattern is not in the ir});
    }

    #[test]
    #[should_panic(expected = "input:\n\n```\nFlatIR {")]
    fn test_assert_ir_not_matches_panics_on_match() {
        assert_ir_not_matches!(ir_from_cc("").unwrap(), quote! {items});
    }

    #[test]
    #[should_panic]
    fn test_assert_ir_matches_panics_on_mismatch() {
        assert_ir_matches!(ir_from_cc("").unwrap(), quote! {this pattern is not in the ir});
    }
}
