// 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

//! Support for retrieving Crubit control attributes. These attributes override
//! how Crubit handles a given AST entry.
//!
//! These should never be written directly by users, but rather generated by
//! Crubit itself. (Potentially in a procedural macro.)
#![feature(rustc_private)]
#![deny(rustc::internal)]

extern crate rustc_ast;
extern crate rustc_middle;
extern crate rustc_span;

use anyhow::{bail, ensure, Result};

use rustc_ast::ast::LitKind;
use rustc_ast::ast::{MetaItemKind, NestedMetaItem};
use rustc_middle::ty::TyCtxt;
use rustc_span::def_id::DefId;
use rustc_span::symbol::Symbol;

/// A `#[__crubit::annotate(...)]` attribute.
#[derive(Debug, Default, Clone, PartialEq)]
pub struct CrubitAttr {
    /// The C++ type of this is spelled as so.
    /// For instance,
    /// `#[__crubit::annotate(internal_cpp_type="std::basic_string<char>")]`
    pub cpp_type: Option<Symbol>,
    // The C++ name of the item. This allows us to rename Rust function names that are
    // not C++-compatible like `new`.
    //
    // For instance,
    //
    // ```
    // #[__crubit::annotate(cpp_name="Create")]
    // pub fn new() -> i32 {...}
    // ```
    //
    // will rename `new` in Rust to `Create` in C++.
    pub cpp_name: Option<Symbol>,
}

/// Gets the `#[__crubit::annotate(...)]` attribute(s) applied to a definition.
///
/// If the definition has no crubit attributes, then an empty (default)
/// `CrubitAttr` is returned.
pub fn get(tcx: TyCtxt, did: impl Into<DefId>) -> Result<CrubitAttr> {
    // NB: do not make these lazy globals, symbols are per-session and sessions are
    // reset in tests. The resulting test failures are very difficult.
    let crubit_annotate = &[Symbol::intern("__crubit"), Symbol::intern("annotate")];
    let cpp_type = Symbol::intern("cpp_type");
    let cpp_name = Symbol::intern("cpp_name");

    let mut crubit_attr = CrubitAttr::default();
    // A quick note: the parsing logic is unfortunate, but such is life. We don't
    // put extra special effort into making the error messages maximally
    // helpful, because they "should never happen": `__crubit::annotate` calls
    // are introduced automatically by Crubit itself, so these errors are only
    // going to be read by Crubit developers when we mess up, not Crubit
    // _users_.
    for attr in tcx.get_attrs_by_path(did.into(), crubit_annotate) {
        let Some(meta) = attr.meta() else {
            bail!("Invalid #[__crubit::annotate(...)] attribute (not a rustc_ast::ast::MetaItem)");
        };
        let MetaItemKind::List(args) = &meta.kind else {
            bail!("Invalid #[__crubit::annotate(...)] attribute (expected __crubit::annotate())");
        };
        for arg in args {
            let NestedMetaItem::MetaItem(arg) = arg else {
                bail!(
                    "Invalid #[__crubit::annotate(...)] attribute (expected nested meta item, not a literal)"
                );
            };
            if arg.path == cpp_type {
                let MetaItemKind::NameValue(value) = &arg.kind else {
                    bail!("Invalid #[__crubit::annotate(cpp_type=...)] attribute (expected =...)");
                };
                let LitKind::Str(s, _raw) = value.kind else {
                    bail!(
                        "Invalid #[__crubit::annotate(cpp_type=...)] attribute (expected =\"...\")"
                    );
                };
                ensure!(
                    crubit_attr.cpp_type.is_none(),
                    "Unexpected duplicate #[__crubit::annotate(cpp_type=...)]"
                );
                crubit_attr.cpp_type = Some(s)
            } else if arg.path == cpp_name {
                let MetaItemKind::NameValue(value) = &arg.kind else {
                    bail!("Invalid #[__crubit::annotate(cpp_name=...)] attribute (expected =...)");
                };
                let LitKind::Str(s, _raw) = value.kind else {
                    bail!(
                        "Invalid #[__crubit::annotate(cpp_name=...)] attribute (expected =\"...\")"
                    );
                };
                ensure!(
                    crubit_attr.cpp_name.is_none(),
                    "Unexpected duplicate #[__crubit::annotate(cpp_name=...)]"
                );
                crubit_attr.cpp_name = Some(s);
            }
        }
    }
    Ok(crubit_attr)
}

#[cfg(test)]
pub mod tests {
    use super::*;
    use run_compiler_test_support::{find_def_id_by_name, run_compiler_for_testing};

    #[test]
    fn test_missing() {
        let test_src = r#"
                pub struct SomeStruct;
            "#;
        run_compiler_for_testing(test_src, |tcx| {
            let attr = get(tcx, find_def_id_by_name(tcx, "SomeStruct")).unwrap();
            assert_eq!(attr, CrubitAttr::default());
        });
    }

    #[test]
    fn test_empty() {
        let test_src = r#"
                #![feature(register_tool)]
                #![register_tool(__crubit)]
                #[__crubit::annotate()]
                pub struct SomeStruct;
            "#;
        run_compiler_for_testing(test_src, |tcx| {
            let attr = get(tcx, find_def_id_by_name(tcx, "SomeStruct")).unwrap();
            assert_eq!(attr, CrubitAttr::default());
        });
    }

    #[test]
    fn test_cpp_type() {
        let test_src = r#"
                #![feature(register_tool)]
                #![register_tool(__crubit)]
                #[__crubit::annotate(cpp_type = "A C++ Type")]
                pub struct SomeStruct;
            "#;
        run_compiler_for_testing(test_src, |tcx| {
            let attr = get(tcx, find_def_id_by_name(tcx, "SomeStruct")).unwrap();
            assert_eq!(attr.cpp_type.unwrap(), Symbol::intern("A C++ Type"));
        });
    }

    #[test]
    fn test_cpp_name() {
        let test_src = r#"
                #![feature(register_tool)]
                #![register_tool(__crubit)]
                #[__crubit::annotate(cpp_name = "Create")]
                pub fn new() -> i32 { 0 }
            "#;
        run_compiler_for_testing(test_src, |tcx| {
            let attr = get(tcx, find_def_id_by_name(tcx, "new")).unwrap();
            assert_eq!(attr.cpp_name.unwrap(), Symbol::intern("Create"));
        });
    }

    #[test]
    fn test_cpp_name_duplicated() {
        let test_src = r#"
                #![feature(register_tool)]
                #![register_tool(__crubit)]
                #[__crubit::annotate(cpp_name = "Create", cpp_name = "Create2")]
                pub fn new() -> i32 { 0 }
            "#;
        run_compiler_for_testing(test_src, |tcx| {
            let attr = get(tcx, find_def_id_by_name(tcx, "new"));
            assert!(attr.is_err());
        });
    }

    #[test]
    fn test_cpp_type_multi() {
        let test_src = r#"
                #![feature(register_tool)]
                #![register_tool(__crubit)]
                #[__crubit::annotate(cpp_type = "X", cpp_type = "X")]
                pub struct SomeStruct;
            "#;
        run_compiler_for_testing(test_src, |tcx| {
            let attr = get(tcx, find_def_id_by_name(tcx, "SomeStruct"));
            assert!(attr.is_err());
        });
    }
}
