//! `hir_expand` deals with macro expansion.
//!
//! Specifically, it implements a concept of `MacroFile` -- a file whose syntax
//! tree originates not from the text of some `FileId`, but from some macro
//! expansion.
#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))]

pub use intern;

pub mod attrs;
pub mod builtin;
pub mod change;
pub mod db;
pub mod declarative;
pub mod eager;
pub mod files;
pub mod hygiene;
pub mod inert_attr_macro;
pub mod mod_path;
pub mod name;
pub mod proc_macro;
pub mod span_map;

mod cfg_process;
mod fixup;
mod prettify_macro_expansion_;

use attrs::collect_attrs;
use rustc_hash::FxHashMap;
use salsa::plumbing::{AsId, FromId};
use stdx::TupleExt;
use triomphe::Arc;

use core::fmt;
use std::hash::Hash;

use base_db::Crate;
use either::Either;
use span::{Edition, ErasedFileAstId, FileAstId, Span, SpanAnchor, SyntaxContext};
use syntax::{
    SyntaxNode, SyntaxToken, TextRange, TextSize,
    ast::{self, AstNode},
};

use crate::{
    attrs::AttrId,
    builtin::{
        BuiltinAttrExpander, BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerExpander,
        include_input_to_file_id,
    },
    db::ExpandDatabase,
    mod_path::ModPath,
    proc_macro::{CustomProcMacroExpander, ProcMacroKind},
    span_map::{ExpansionSpanMap, SpanMap},
};

pub use crate::{
    cfg_process::check_cfg_attr_value,
    files::{AstId, ErasedAstId, FileRange, InFile, InMacroFile, InRealFile},
    prettify_macro_expansion_::prettify_macro_expansion,
};

pub use base_db::EditionedFileId;
pub use mbe::{DeclarativeMacro, ValueResult};

pub mod tt {
    pub use span::Span;
    pub use tt::{DelimiterKind, IdentIsRaw, LitKind, Spacing, token_to_literal};

    pub type Delimiter = ::tt::Delimiter<Span>;
    pub type DelimSpan = ::tt::DelimSpan<Span>;
    pub type Subtree = ::tt::Subtree<Span>;
    pub type Leaf = ::tt::Leaf<Span>;
    pub type Literal = ::tt::Literal<Span>;
    pub type Punct = ::tt::Punct<Span>;
    pub type Ident = ::tt::Ident<Span>;
    pub type TokenTree = ::tt::TokenTree<Span>;
    pub type TopSubtree = ::tt::TopSubtree<Span>;
    pub type TopSubtreeBuilder = ::tt::TopSubtreeBuilder<Span>;
    pub type TokenTreesView<'a> = ::tt::TokenTreesView<'a, Span>;
    pub type SubtreeView<'a> = ::tt::SubtreeView<'a, Span>;
    pub type TtElement<'a> = ::tt::iter::TtElement<'a, Span>;
    pub type TtIter<'a> = ::tt::iter::TtIter<'a, Span>;
}

#[macro_export]
macro_rules! impl_intern_lookup {
    ($db:ident, $id:ident, $loc:ident, $intern:ident, $lookup:ident) => {
        impl $crate::Intern for $loc {
            type Database = dyn $db;
            type ID = $id;
            fn intern(self, db: &Self::Database) -> Self::ID {
                db.$intern(self)
            }
        }

        impl $crate::Lookup for $id {
            type Database = dyn $db;
            type Data = $loc;
            fn lookup(&self, db: &Self::Database) -> Self::Data {
                db.$lookup(*self)
            }
        }
    };
}

// ideally these would be defined in base-db, but the orphan rule doesn't let us
pub trait Intern {
    type Database: ?Sized;
    type ID;
    fn intern(self, db: &Self::Database) -> Self::ID;
}

pub trait Lookup {
    type Database: ?Sized;
    type Data;
    fn lookup(&self, db: &Self::Database) -> Self::Data;
}

impl_intern_lookup!(
    ExpandDatabase,
    MacroCallId,
    MacroCallLoc,
    intern_macro_call,
    lookup_intern_macro_call
);

pub type ExpandResult<T> = ValueResult<T, ExpandError>;

#[derive(Debug, PartialEq, Eq, Clone, Hash)]
pub struct ExpandError {
    inner: Arc<(ExpandErrorKind, Span)>,
}

impl ExpandError {
    pub fn new(span: Span, kind: ExpandErrorKind) -> Self {
        ExpandError { inner: Arc::new((kind, span)) }
    }
    pub fn other(span: Span, msg: impl Into<Box<str>>) -> Self {
        ExpandError { inner: Arc::new((ExpandErrorKind::Other(msg.into()), span)) }
    }
    pub fn kind(&self) -> &ExpandErrorKind {
        &self.inner.0
    }
    pub fn span(&self) -> Span {
        self.inner.1
    }

    pub fn render_to_string(&self, db: &dyn ExpandDatabase) -> RenderedExpandError {
        self.inner.0.render_to_string(db)
    }
}

#[derive(Debug, PartialEq, Eq, Clone, Hash)]
pub enum ExpandErrorKind {
    /// Attribute macro expansion is disabled.
    ProcMacroAttrExpansionDisabled,
    MissingProcMacroExpander(Crate),
    /// The macro for this call is disabled.
    MacroDisabled,
    /// The macro definition has errors.
    MacroDefinition,
    Mbe(mbe::ExpandErrorKind),
    RecursionOverflow,
    Other(Box<str>),
    ProcMacroPanic(Box<str>),
}

pub struct RenderedExpandError {
    pub message: String,
    pub error: bool,
    pub kind: &'static str,
}

impl fmt::Display for RenderedExpandError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.message)
    }
}

impl RenderedExpandError {
    const GENERAL_KIND: &str = "macro-error";
    const DISABLED: &str = "proc-macro-disabled";
    const ATTR_EXP_DISABLED: &str = "attribute-expansion-disabled";
}

impl ExpandErrorKind {
    pub fn render_to_string(&self, db: &dyn ExpandDatabase) -> RenderedExpandError {
        match self {
            ExpandErrorKind::ProcMacroAttrExpansionDisabled => RenderedExpandError {
                message: "procedural attribute macro expansion is disabled".to_owned(),
                error: false,
                kind: RenderedExpandError::ATTR_EXP_DISABLED,
            },
            ExpandErrorKind::MacroDisabled => RenderedExpandError {
                message: "proc-macro is explicitly disabled".to_owned(),
                error: false,
                kind: RenderedExpandError::DISABLED,
            },
            &ExpandErrorKind::MissingProcMacroExpander(def_crate) => {
                match db.proc_macros_for_crate(def_crate).as_ref().and_then(|it| it.get_error()) {
                    Some(e) => RenderedExpandError {
                        message: e.to_string(),
                        error: e.is_hard_error(),
                        kind: RenderedExpandError::GENERAL_KIND,
                    },
                    None => RenderedExpandError {
                        message: format!(
                            "internal error: proc-macro map is missing error entry for crate {def_crate:?}"
                        ),
                        error: true,
                        kind: RenderedExpandError::GENERAL_KIND,
                    },
                }
            }
            ExpandErrorKind::MacroDefinition => RenderedExpandError {
                message: "macro definition has parse errors".to_owned(),
                error: true,
                kind: RenderedExpandError::GENERAL_KIND,
            },
            ExpandErrorKind::Mbe(e) => RenderedExpandError {
                message: e.to_string(),
                error: true,
                kind: RenderedExpandError::GENERAL_KIND,
            },
            ExpandErrorKind::RecursionOverflow => RenderedExpandError {
                message: "overflow expanding the original macro".to_owned(),
                error: true,
                kind: RenderedExpandError::GENERAL_KIND,
            },
            ExpandErrorKind::Other(e) => RenderedExpandError {
                message: (**e).to_owned(),
                error: true,
                kind: RenderedExpandError::GENERAL_KIND,
            },
            ExpandErrorKind::ProcMacroPanic(e) => RenderedExpandError {
                message: format!("proc-macro panicked: {e}"),
                error: true,
                kind: RenderedExpandError::GENERAL_KIND,
            },
        }
    }
}

impl From<mbe::ExpandError> for ExpandError {
    fn from(mbe: mbe::ExpandError) -> Self {
        ExpandError { inner: Arc::new((ExpandErrorKind::Mbe(mbe.inner.1.clone()), mbe.inner.0)) }
    }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct MacroCallLoc {
    pub def: MacroDefId,
    pub krate: Crate,
    pub kind: MacroCallKind,
    pub ctxt: SyntaxContext,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct MacroDefId {
    pub krate: Crate,
    pub edition: Edition,
    pub kind: MacroDefKind,
    pub local_inner: bool,
    pub allow_internal_unsafe: bool,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum MacroDefKind {
    Declarative(AstId<ast::Macro>),
    BuiltIn(AstId<ast::Macro>, BuiltinFnLikeExpander),
    BuiltInAttr(AstId<ast::Macro>, BuiltinAttrExpander),
    BuiltInDerive(AstId<ast::Macro>, BuiltinDeriveExpander),
    BuiltInEager(AstId<ast::Macro>, EagerExpander),
    ProcMacro(AstId<ast::Fn>, CustomProcMacroExpander, ProcMacroKind),
}

impl MacroDefKind {
    #[inline]
    pub fn is_declarative(&self) -> bool {
        matches!(self, MacroDefKind::Declarative(..))
    }

    pub fn erased_ast_id(&self) -> ErasedAstId {
        match *self {
            MacroDefKind::ProcMacro(id, ..) => id.erase(),
            MacroDefKind::BuiltIn(id, _)
            | MacroDefKind::BuiltInAttr(id, _)
            | MacroDefKind::BuiltInDerive(id, _)
            | MacroDefKind::BuiltInEager(id, _)
            | MacroDefKind::Declarative(id, ..) => id.erase(),
        }
    }
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct EagerCallInfo {
    /// The expanded argument of the eager macro.
    arg: Arc<tt::TopSubtree>,
    /// Call id of the eager macro's input file (this is the macro file for its fully expanded input).
    arg_id: MacroCallId,
    error: Option<ExpandError>,
    /// The call site span of the eager macro
    span: Span,
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum MacroCallKind {
    FnLike {
        ast_id: AstId<ast::MacroCall>,
        expand_to: ExpandTo,
        /// Some if this is a macro call for an eager macro. Note that this is `None`
        /// for the eager input macro file.
        // FIXME: This is being interned, subtrees can vary quickly differing just slightly causing
        // leakage problems here
        eager: Option<Arc<EagerCallInfo>>,
    },
    Derive {
        ast_id: AstId<ast::Adt>,
        /// Syntactical index of the invoking `#[derive]` attribute.
        ///
        /// Outer attributes are counted first, then inner attributes. This does not support
        /// out-of-line modules, which may have attributes spread across 2 files!
        derive_attr_index: AttrId,
        /// Index of the derive macro in the derive attribute
        derive_index: u32,
        /// The "parent" macro call.
        /// We will resolve the same token tree for all derive macros in the same derive attribute.
        derive_macro_id: MacroCallId,
    },
    Attr {
        ast_id: AstId<ast::Item>,
        // FIXME: This shouldn't be here, we can derive this from `invoc_attr_index`
        // but we need to fix the `cfg_attr` handling first.
        attr_args: Option<Arc<tt::TopSubtree>>,
        /// Syntactical index of the invoking `#[attribute]`.
        ///
        /// Outer attributes are counted first, then inner attributes. This does not support
        /// out-of-line modules, which may have attributes spread across 2 files!
        invoc_attr_index: AttrId,
    },
}

impl HirFileId {
    pub fn edition(self, db: &dyn ExpandDatabase) -> Edition {
        match self {
            HirFileId::FileId(file_id) => file_id.editioned_file_id(db).edition(),
            HirFileId::MacroFile(m) => db.lookup_intern_macro_call(m).def.edition,
        }
    }
    pub fn original_file(self, db: &dyn ExpandDatabase) -> EditionedFileId {
        let mut file_id = self;
        loop {
            match file_id {
                HirFileId::FileId(id) => break id,
                HirFileId::MacroFile(macro_call_id) => {
                    file_id = db.lookup_intern_macro_call(macro_call_id).kind.file_id()
                }
            }
        }
    }

    pub fn original_file_respecting_includes(mut self, db: &dyn ExpandDatabase) -> EditionedFileId {
        loop {
            match self {
                HirFileId::FileId(id) => break id,
                HirFileId::MacroFile(file) => {
                    let loc = db.lookup_intern_macro_call(file);
                    if loc.def.is_include() {
                        if let MacroCallKind::FnLike { eager: Some(eager), .. } = &loc.kind {
                            if let Ok(it) = include_input_to_file_id(db, file, &eager.arg) {
                                break it;
                            }
                        }
                    }
                    self = loc.kind.file_id();
                }
            }
        }
    }

    pub fn original_call_node(self, db: &dyn ExpandDatabase) -> Option<InRealFile<SyntaxNode>> {
        let mut call = db.lookup_intern_macro_call(self.macro_file()?).to_node(db);
        loop {
            match call.file_id {
                HirFileId::FileId(file_id) => {
                    break Some(InRealFile { file_id, value: call.value });
                }
                HirFileId::MacroFile(macro_call_id) => {
                    call = db.lookup_intern_macro_call(macro_call_id).to_node(db);
                }
            }
        }
    }

    pub fn call_node(self, db: &dyn ExpandDatabase) -> Option<InFile<SyntaxNode>> {
        Some(db.lookup_intern_macro_call(self.macro_file()?).to_node(db))
    }

    pub fn as_builtin_derive_attr_node(
        &self,
        db: &dyn ExpandDatabase,
    ) -> Option<InFile<ast::Attr>> {
        let macro_file = self.macro_file()?;
        let loc = db.lookup_intern_macro_call(macro_file);
        let attr = match loc.def.kind {
            MacroDefKind::BuiltInDerive(..) => loc.to_node(db),
            _ => return None,
        };
        Some(attr.with_value(ast::Attr::cast(attr.value.clone())?))
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum MacroKind {
    /// `macro_rules!` or Macros 2.0 macro.
    Declarative,
    /// A built-in function-like macro.
    DeclarativeBuiltIn,
    /// A custom derive.
    Derive,
    /// A builtin-in derive.
    DeriveBuiltIn,
    /// A procedural attribute macro.
    Attr,
    /// A built-in attribute macro.
    AttrBuiltIn,
    /// A function-like procedural macro.
    ProcMacro,
}

impl MacroCallId {
    pub fn call_node(self, db: &dyn ExpandDatabase) -> InFile<SyntaxNode> {
        db.lookup_intern_macro_call(self).to_node(db)
    }
    pub fn expansion_level(self, db: &dyn ExpandDatabase) -> u32 {
        let mut level = 0;
        let mut macro_file = self;
        loop {
            let loc = db.lookup_intern_macro_call(macro_file);

            level += 1;
            macro_file = match loc.kind.file_id() {
                HirFileId::FileId(_) => break level,
                HirFileId::MacroFile(it) => it,
            };
        }
    }
    pub fn parent(self, db: &dyn ExpandDatabase) -> HirFileId {
        db.lookup_intern_macro_call(self).kind.file_id()
    }

    /// Return expansion information if it is a macro-expansion file
    pub fn expansion_info(self, db: &dyn ExpandDatabase) -> ExpansionInfo {
        ExpansionInfo::new(db, self)
    }

    pub fn kind(self, db: &dyn ExpandDatabase) -> MacroKind {
        match db.lookup_intern_macro_call(self).def.kind {
            MacroDefKind::Declarative(..) => MacroKind::Declarative,
            MacroDefKind::BuiltIn(..) | MacroDefKind::BuiltInEager(..) => {
                MacroKind::DeclarativeBuiltIn
            }
            MacroDefKind::BuiltInDerive(..) => MacroKind::DeriveBuiltIn,
            MacroDefKind::ProcMacro(_, _, ProcMacroKind::CustomDerive) => MacroKind::Derive,
            MacroDefKind::ProcMacro(_, _, ProcMacroKind::Attr) => MacroKind::Attr,
            MacroDefKind::ProcMacro(_, _, ProcMacroKind::Bang) => MacroKind::ProcMacro,
            MacroDefKind::BuiltInAttr(..) => MacroKind::AttrBuiltIn,
        }
    }

    pub fn is_include_macro(self, db: &dyn ExpandDatabase) -> bool {
        db.lookup_intern_macro_call(self).def.is_include()
    }

    pub fn is_include_like_macro(self, db: &dyn ExpandDatabase) -> bool {
        db.lookup_intern_macro_call(self).def.is_include_like()
    }

    pub fn is_env_or_option_env(self, db: &dyn ExpandDatabase) -> bool {
        db.lookup_intern_macro_call(self).def.is_env_or_option_env()
    }

    pub fn is_eager(self, db: &dyn ExpandDatabase) -> bool {
        let loc = db.lookup_intern_macro_call(self);
        matches!(loc.def.kind, MacroDefKind::BuiltInEager(..))
    }

    pub fn eager_arg(self, db: &dyn ExpandDatabase) -> Option<MacroCallId> {
        let loc = db.lookup_intern_macro_call(self);
        match &loc.kind {
            MacroCallKind::FnLike { eager, .. } => eager.as_ref().map(|it| it.arg_id),
            _ => None,
        }
    }

    pub fn is_derive_attr_pseudo_expansion(self, db: &dyn ExpandDatabase) -> bool {
        let loc = db.lookup_intern_macro_call(self);
        loc.def.is_attribute_derive()
    }
}

impl MacroDefId {
    pub fn make_call(
        self,
        db: &dyn ExpandDatabase,
        krate: Crate,
        kind: MacroCallKind,
        ctxt: SyntaxContext,
    ) -> MacroCallId {
        db.intern_macro_call(MacroCallLoc { def: self, krate, kind, ctxt })
    }

    pub fn definition_range(&self, db: &dyn ExpandDatabase) -> InFile<TextRange> {
        match self.kind {
            MacroDefKind::Declarative(id)
            | MacroDefKind::BuiltIn(id, _)
            | MacroDefKind::BuiltInAttr(id, _)
            | MacroDefKind::BuiltInDerive(id, _)
            | MacroDefKind::BuiltInEager(id, _) => {
                id.with_value(db.ast_id_map(id.file_id).get(id.value).text_range())
            }
            MacroDefKind::ProcMacro(id, _, _) => {
                id.with_value(db.ast_id_map(id.file_id).get(id.value).text_range())
            }
        }
    }

    pub fn ast_id(&self) -> Either<AstId<ast::Macro>, AstId<ast::Fn>> {
        match self.kind {
            MacroDefKind::ProcMacro(id, ..) => Either::Right(id),
            MacroDefKind::Declarative(id)
            | MacroDefKind::BuiltIn(id, _)
            | MacroDefKind::BuiltInAttr(id, _)
            | MacroDefKind::BuiltInDerive(id, _)
            | MacroDefKind::BuiltInEager(id, _) => Either::Left(id),
        }
    }

    pub fn is_proc_macro(&self) -> bool {
        matches!(self.kind, MacroDefKind::ProcMacro(..))
    }

    pub fn is_attribute(&self) -> bool {
        matches!(
            self.kind,
            MacroDefKind::BuiltInAttr(..) | MacroDefKind::ProcMacro(_, _, ProcMacroKind::Attr)
        )
    }

    pub fn is_derive(&self) -> bool {
        matches!(
            self.kind,
            MacroDefKind::BuiltInDerive(..)
                | MacroDefKind::ProcMacro(_, _, ProcMacroKind::CustomDerive)
        )
    }

    pub fn is_fn_like(&self) -> bool {
        matches!(
            self.kind,
            MacroDefKind::BuiltIn(..)
                | MacroDefKind::ProcMacro(_, _, ProcMacroKind::Bang)
                | MacroDefKind::BuiltInEager(..)
                | MacroDefKind::Declarative(..)
        )
    }

    pub fn is_attribute_derive(&self) -> bool {
        matches!(self.kind, MacroDefKind::BuiltInAttr(_, expander) if expander.is_derive())
    }

    pub fn is_include(&self) -> bool {
        matches!(self.kind, MacroDefKind::BuiltInEager(_, expander) if expander.is_include())
    }

    pub fn is_include_like(&self) -> bool {
        matches!(self.kind, MacroDefKind::BuiltInEager(_, expander) if expander.is_include_like())
    }

    pub fn is_env_or_option_env(&self) -> bool {
        matches!(self.kind, MacroDefKind::BuiltInEager(_, expander) if expander.is_env_or_option_env())
    }
}

impl MacroCallLoc {
    pub fn to_node(&self, db: &dyn ExpandDatabase) -> InFile<SyntaxNode> {
        match self.kind {
            MacroCallKind::FnLike { ast_id, .. } => {
                ast_id.with_value(ast_id.to_node(db).syntax().clone())
            }
            MacroCallKind::Derive { ast_id, derive_attr_index, .. } => {
                // FIXME: handle `cfg_attr`
                ast_id.with_value(ast_id.to_node(db)).map(|it| {
                    collect_attrs(&it)
                        .nth(derive_attr_index.ast_index())
                        .and_then(|it| match it.1 {
                            Either::Left(attr) => Some(attr.syntax().clone()),
                            Either::Right(_) => None,
                        })
                        .unwrap_or_else(|| it.syntax().clone())
                })
            }
            MacroCallKind::Attr { ast_id, invoc_attr_index, .. } => {
                if self.def.is_attribute_derive() {
                    // FIXME: handle `cfg_attr`
                    ast_id.with_value(ast_id.to_node(db)).map(|it| {
                        collect_attrs(&it)
                            .nth(invoc_attr_index.ast_index())
                            .and_then(|it| match it.1 {
                                Either::Left(attr) => Some(attr.syntax().clone()),
                                Either::Right(_) => None,
                            })
                            .unwrap_or_else(|| it.syntax().clone())
                    })
                } else {
                    ast_id.with_value(ast_id.to_node(db).syntax().clone())
                }
            }
        }
    }

    pub fn to_node_item(&self, db: &dyn ExpandDatabase) -> InFile<ast::Item> {
        match self.kind {
            MacroCallKind::FnLike { ast_id, .. } => {
                InFile::new(ast_id.file_id, ast_id.map(FileAstId::upcast).to_node(db))
            }
            MacroCallKind::Derive { ast_id, .. } => {
                InFile::new(ast_id.file_id, ast_id.map(FileAstId::upcast).to_node(db))
            }
            MacroCallKind::Attr { ast_id, .. } => InFile::new(ast_id.file_id, ast_id.to_node(db)),
        }
    }

    fn expand_to(&self) -> ExpandTo {
        match self.kind {
            MacroCallKind::FnLike { expand_to, .. } => expand_to,
            MacroCallKind::Derive { .. } => ExpandTo::Items,
            MacroCallKind::Attr { .. } if self.def.is_attribute_derive() => ExpandTo::Items,
            MacroCallKind::Attr { .. } => {
                // FIXME(stmt_expr_attributes)
                ExpandTo::Items
            }
        }
    }

    pub fn include_file_id(
        &self,
        db: &dyn ExpandDatabase,
        macro_call_id: MacroCallId,
    ) -> Option<EditionedFileId> {
        if self.def.is_include() {
            if let MacroCallKind::FnLike { eager: Some(eager), .. } = &self.kind {
                if let Ok(it) = include_input_to_file_id(db, macro_call_id, &eager.arg) {
                    return Some(it);
                }
            }
        }

        None
    }
}

impl MacroCallKind {
    pub fn descr(&self) -> &'static str {
        match self {
            MacroCallKind::FnLike { .. } => "macro call",
            MacroCallKind::Derive { .. } => "derive macro",
            MacroCallKind::Attr { .. } => "attribute macro",
        }
    }

    /// Returns the file containing the macro invocation.
    pub fn file_id(&self) -> HirFileId {
        match *self {
            MacroCallKind::FnLike { ast_id: InFile { file_id, .. }, .. }
            | MacroCallKind::Derive { ast_id: InFile { file_id, .. }, .. }
            | MacroCallKind::Attr { ast_id: InFile { file_id, .. }, .. } => file_id,
        }
    }

    pub fn erased_ast_id(&self) -> ErasedFileAstId {
        match *self {
            MacroCallKind::FnLike { ast_id: InFile { value, .. }, .. } => value.erase(),
            MacroCallKind::Derive { ast_id: InFile { value, .. }, .. } => value.erase(),
            MacroCallKind::Attr { ast_id: InFile { value, .. }, .. } => value.erase(),
        }
    }

    /// Returns the original file range that best describes the location of this macro call.
    ///
    /// This spans the entire macro call, including its input. That is for
    /// - fn_like! {}, it spans the path and token tree
    /// - #\[derive], it spans the `#[derive(...)]` attribute and the annotated item
    /// - #\[attr], it spans the `#[attr(...)]` attribute and the annotated item
    pub fn original_call_range_with_input(self, db: &dyn ExpandDatabase) -> FileRange {
        let mut kind = self;
        let file_id = loop {
            match kind.file_id() {
                HirFileId::MacroFile(file) => {
                    kind = db.lookup_intern_macro_call(file).kind;
                }
                HirFileId::FileId(file_id) => break file_id,
            }
        };

        let range = match kind {
            MacroCallKind::FnLike { ast_id, .. } => ast_id.to_ptr(db).text_range(),
            MacroCallKind::Derive { ast_id, .. } => ast_id.to_ptr(db).text_range(),
            MacroCallKind::Attr { ast_id, .. } => ast_id.to_ptr(db).text_range(),
        };

        FileRange { range, file_id }
    }

    /// Returns the original file range that best describes the location of this macro call.
    ///
    /// Here we try to roughly match what rustc does to improve diagnostics: fn-like macros
    /// get the macro path (rustc shows the whole `ast::MacroCall`), attribute macros get the
    /// attribute's range, and derives get only the specific derive that is being referred to.
    pub fn original_call_range(self, db: &dyn ExpandDatabase) -> FileRange {
        let mut kind = self;
        let file_id = loop {
            match kind.file_id() {
                HirFileId::MacroFile(file) => {
                    kind = db.lookup_intern_macro_call(file).kind;
                }
                HirFileId::FileId(file_id) => break file_id,
            }
        };

        let range = match kind {
            MacroCallKind::FnLike { ast_id, .. } => {
                let node = ast_id.to_node(db);
                node.path()
                    .unwrap()
                    .syntax()
                    .text_range()
                    .cover(node.excl_token().unwrap().text_range())
            }
            MacroCallKind::Derive { ast_id, derive_attr_index, .. } => {
                // FIXME: should be the range of the macro name, not the whole derive
                // FIXME: handle `cfg_attr`
                collect_attrs(&ast_id.to_node(db))
                    .nth(derive_attr_index.ast_index())
                    .expect("missing derive")
                    .1
                    .expect_left("derive is a doc comment?")
                    .syntax()
                    .text_range()
            }
            // FIXME: handle `cfg_attr`
            MacroCallKind::Attr { ast_id, invoc_attr_index, .. } => {
                collect_attrs(&ast_id.to_node(db))
                    .nth(invoc_attr_index.ast_index())
                    .expect("missing attribute")
                    .1
                    .expect_left("attribute macro is a doc comment?")
                    .syntax()
                    .text_range()
            }
        };

        FileRange { range, file_id }
    }

    fn arg(&self, db: &dyn ExpandDatabase) -> InFile<Option<SyntaxNode>> {
        match self {
            MacroCallKind::FnLike { ast_id, .. } => {
                ast_id.to_in_file_node(db).map(|it| Some(it.token_tree()?.syntax().clone()))
            }
            MacroCallKind::Derive { ast_id, .. } => {
                ast_id.to_in_file_node(db).syntax().cloned().map(Some)
            }
            MacroCallKind::Attr { ast_id, .. } => {
                ast_id.to_in_file_node(db).syntax().cloned().map(Some)
            }
        }
    }
}

/// ExpansionInfo mainly describes how to map text range between src and expanded macro
// FIXME: can be expensive to create, we should check the use sites and maybe replace them with
// simpler function calls if the map is only used once
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ExpansionInfo {
    expanded: InMacroFile<SyntaxNode>,
    /// The argument TokenTree or item for attributes
    arg: InFile<Option<SyntaxNode>>,
    exp_map: Arc<ExpansionSpanMap>,
    arg_map: SpanMap,
    loc: MacroCallLoc,
}

impl ExpansionInfo {
    pub fn expanded(&self) -> InMacroFile<SyntaxNode> {
        self.expanded.clone()
    }

    pub fn arg(&self) -> InFile<Option<&SyntaxNode>> {
        self.arg.as_ref().map(|it| it.as_ref())
    }

    pub fn call_file(&self) -> HirFileId {
        self.arg.file_id
    }

    pub fn is_attr(&self) -> bool {
        matches!(
            self.loc.def.kind,
            MacroDefKind::BuiltInAttr(..) | MacroDefKind::ProcMacro(_, _, ProcMacroKind::Attr)
        )
    }

    /// Maps the passed in file range down into a macro expansion if it is the input to a macro call.
    ///
    /// Note this does a linear search through the entire backing vector of the spanmap.
    // FIXME: Consider adding a reverse map to ExpansionInfo to get rid of the linear search which
    // potentially results in quadratic look ups (notably this might improve semantic highlighting perf)
    pub fn map_range_down_exact(
        &self,
        span: Span,
    ) -> Option<InMacroFile<impl Iterator<Item = (SyntaxToken, SyntaxContext)> + '_>> {
        let tokens = self.exp_map.ranges_with_span_exact(span).flat_map(move |(range, ctx)| {
            self.expanded.value.covering_element(range).into_token().zip(Some(ctx))
        });

        Some(InMacroFile::new(self.expanded.file_id, tokens))
    }

    /// Maps the passed in file range down into a macro expansion if it is the input to a macro call.
    /// Unlike [`map_range_down_exact`], this will consider spans that contain the given span.
    ///
    /// Note this does a linear search through the entire backing vector of the spanmap.
    pub fn map_range_down(
        &self,
        span: Span,
    ) -> Option<InMacroFile<impl Iterator<Item = (SyntaxToken, SyntaxContext)> + '_>> {
        let tokens = self.exp_map.ranges_with_span(span).flat_map(move |(range, ctx)| {
            self.expanded.value.covering_element(range).into_token().zip(Some(ctx))
        });

        Some(InMacroFile::new(self.expanded.file_id, tokens))
    }

    /// Looks up the span at the given offset.
    pub fn span_for_offset(
        &self,
        db: &dyn ExpandDatabase,
        offset: TextSize,
    ) -> (FileRange, SyntaxContext) {
        debug_assert!(self.expanded.value.text_range().contains(offset));
        span_for_offset(db, &self.exp_map, offset)
    }

    /// Maps up the text range out of the expansion hierarchy back into the original file its from.
    pub fn map_node_range_up(
        &self,
        db: &dyn ExpandDatabase,
        range: TextRange,
    ) -> Option<(FileRange, SyntaxContext)> {
        debug_assert!(self.expanded.value.text_range().contains_range(range));
        map_node_range_up(db, &self.exp_map, range)
    }

    /// Maps up the text range out of the expansion into its macro call.
    ///
    /// Note that this may return multiple ranges as we lose the precise association between input to output
    /// and as such we may consider inputs that are unrelated.
    pub fn map_range_up_once(
        &self,
        db: &dyn ExpandDatabase,
        token: TextRange,
    ) -> InFile<smallvec::SmallVec<[TextRange; 1]>> {
        debug_assert!(self.expanded.value.text_range().contains_range(token));
        let span = self.exp_map.span_at(token.start());
        match &self.arg_map {
            SpanMap::RealSpanMap(_) => {
                let file_id = EditionedFileId::from_span(db, span.anchor.file_id).into();
                let anchor_offset =
                    db.ast_id_map(file_id).get_erased(span.anchor.ast_id).text_range().start();
                InFile { file_id, value: smallvec::smallvec![span.range + anchor_offset] }
            }
            SpanMap::ExpansionSpanMap(arg_map) => {
                let Some(arg_node) = &self.arg.value else {
                    return InFile::new(self.arg.file_id, smallvec::smallvec![]);
                };
                let arg_range = arg_node.text_range();
                InFile::new(
                    self.arg.file_id,
                    arg_map
                        .ranges_with_span_exact(span)
                        .filter(|(range, _)| range.intersect(arg_range).is_some())
                        .map(TupleExt::head)
                        .collect(),
                )
            }
        }
    }

    pub fn new(db: &dyn ExpandDatabase, macro_file: MacroCallId) -> ExpansionInfo {
        let _p = tracing::info_span!("ExpansionInfo::new").entered();
        let loc = db.lookup_intern_macro_call(macro_file);

        let arg_tt = loc.kind.arg(db);
        let arg_map = db.span_map(arg_tt.file_id);

        let (parse, exp_map) = db.parse_macro_expansion(macro_file).value;
        let expanded = InMacroFile { file_id: macro_file, value: parse.syntax_node() };

        ExpansionInfo { expanded, loc, arg: arg_tt, exp_map, arg_map }
    }
}

/// Maps up the text range out of the expansion hierarchy back into the original file its from only
/// considering the root spans contained.
/// Unlike [`map_node_range_up`], this will not return `None` if any anchors or syntax contexts differ.
pub fn map_node_range_up_rooted(
    db: &dyn ExpandDatabase,
    exp_map: &ExpansionSpanMap,
    range: TextRange,
) -> Option<FileRange> {
    let mut spans = exp_map.spans_for_range(range).filter(|span| span.ctx.is_root());
    let Span { range, anchor, ctx: _ } = spans.next()?;
    let mut start = range.start();
    let mut end = range.end();

    for span in spans {
        if span.anchor != anchor {
            return None;
        }
        start = start.min(span.range.start());
        end = end.max(span.range.end());
    }
    let file_id = EditionedFileId::from_span(db, anchor.file_id);
    let anchor_offset =
        db.ast_id_map(file_id.into()).get_erased(anchor.ast_id).text_range().start();
    Some(FileRange { file_id, range: TextRange::new(start, end) + anchor_offset })
}

/// Maps up the text range out of the expansion hierarchy back into the original file its from.
///
/// this will return `None` if any anchors or syntax contexts differ.
pub fn map_node_range_up(
    db: &dyn ExpandDatabase,
    exp_map: &ExpansionSpanMap,
    range: TextRange,
) -> Option<(FileRange, SyntaxContext)> {
    let mut spans = exp_map.spans_for_range(range);
    let Span { range, anchor, ctx } = spans.next()?;
    let mut start = range.start();
    let mut end = range.end();

    for span in spans {
        if span.anchor != anchor || span.ctx != ctx {
            return None;
        }
        start = start.min(span.range.start());
        end = end.max(span.range.end());
    }
    let file_id = EditionedFileId::from_span(db, anchor.file_id);
    let anchor_offset =
        db.ast_id_map(file_id.into()).get_erased(anchor.ast_id).text_range().start();
    Some((FileRange { file_id, range: TextRange::new(start, end) + anchor_offset }, ctx))
}

/// Maps up the text range out of the expansion hierarchy back into the original file its from.
/// This version will aggregate the ranges of all spans with the same anchor and syntax context.
pub fn map_node_range_up_aggregated(
    db: &dyn ExpandDatabase,
    exp_map: &ExpansionSpanMap,
    range: TextRange,
) -> FxHashMap<(SpanAnchor, SyntaxContext), TextRange> {
    let mut map = FxHashMap::default();
    for span in exp_map.spans_for_range(range) {
        let range = map.entry((span.anchor, span.ctx)).or_insert_with(|| span.range);
        *range = TextRange::new(
            range.start().min(span.range.start()),
            range.end().max(span.range.end()),
        );
    }
    for ((anchor, _), range) in &mut map {
        let file_id = EditionedFileId::from_span(db, anchor.file_id);
        let anchor_offset =
            db.ast_id_map(file_id.into()).get_erased(anchor.ast_id).text_range().start();
        *range += anchor_offset;
    }
    map
}

/// Looks up the span at the given offset.
pub fn span_for_offset(
    db: &dyn ExpandDatabase,
    exp_map: &ExpansionSpanMap,
    offset: TextSize,
) -> (FileRange, SyntaxContext) {
    let span = exp_map.span_at(offset);
    let file_id = EditionedFileId::from_span(db, span.anchor.file_id);
    let anchor_offset =
        db.ast_id_map(file_id.into()).get_erased(span.anchor.ast_id).text_range().start();
    (FileRange { file_id, range: span.range + anchor_offset }, span.ctx)
}

/// In Rust, macros expand token trees to token trees. When we want to turn a
/// token tree into an AST node, we need to figure out what kind of AST node we
/// want: something like `foo` can be a type, an expression, or a pattern.
///
/// Naively, one would think that "what this expands to" is a property of a
/// particular macro: macro `m1` returns an item, while macro `m2` returns an
/// expression, etc. That's not the case -- macros are polymorphic in the
/// result, and can expand to any type of the AST node.
///
/// What defines the actual AST node is the syntactic context of the macro
/// invocation. As a contrived example, in `let T![*] = T![*];` the first `T`
/// expands to a pattern, while the second one expands to an expression.
///
/// `ExpandTo` captures this bit of information about a particular macro call
/// site.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ExpandTo {
    Statements,
    Items,
    Pattern,
    Type,
    Expr,
}

impl ExpandTo {
    pub fn from_call_site(call: &ast::MacroCall) -> ExpandTo {
        use syntax::SyntaxKind::*;

        let syn = call.syntax();

        let parent = match syn.parent() {
            Some(it) => it,
            None => return ExpandTo::Statements,
        };

        // FIXME: macros in statement position are treated as expression statements, they should
        // probably be their own statement kind. The *grand*parent indicates what's valid.
        if parent.kind() == MACRO_EXPR
            && parent
                .parent()
                .is_some_and(|p| matches!(p.kind(), EXPR_STMT | STMT_LIST | MACRO_STMTS))
        {
            return ExpandTo::Statements;
        }

        match parent.kind() {
            MACRO_ITEMS | SOURCE_FILE | ITEM_LIST => ExpandTo::Items,
            MACRO_STMTS | EXPR_STMT | STMT_LIST => ExpandTo::Statements,
            MACRO_PAT => ExpandTo::Pattern,
            MACRO_TYPE => ExpandTo::Type,

            ARG_LIST | ARRAY_EXPR | AWAIT_EXPR | BIN_EXPR | BREAK_EXPR | CALL_EXPR | CAST_EXPR
            | CLOSURE_EXPR | FIELD_EXPR | FOR_EXPR | IF_EXPR | INDEX_EXPR | LET_EXPR
            | MATCH_ARM | MATCH_EXPR | MATCH_GUARD | METHOD_CALL_EXPR | PAREN_EXPR | PATH_EXPR
            | PREFIX_EXPR | RANGE_EXPR | RECORD_EXPR_FIELD | REF_EXPR | RETURN_EXPR | TRY_EXPR
            | TUPLE_EXPR | WHILE_EXPR | MACRO_EXPR => ExpandTo::Expr,
            _ => {
                // Unknown , Just guess it is `Items`
                ExpandTo::Items
            }
        }
    }
}

intern::impl_internable!(ModPath, attrs::AttrInput);

#[salsa_macros::interned(no_lifetime, debug, revisions = usize::MAX)]
#[doc(alias = "MacroFileId")]
pub struct MacroCallId {
    pub loc: MacroCallLoc,
}

impl From<span::MacroCallId> for MacroCallId {
    #[inline]
    fn from(value: span::MacroCallId) -> Self {
        MacroCallId::from_id(value.0)
    }
}

impl From<MacroCallId> for span::MacroCallId {
    #[inline]
    fn from(value: MacroCallId) -> span::MacroCallId {
        span::MacroCallId(value.as_id())
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, salsa_macros::Supertype)]
pub enum HirFileId {
    FileId(EditionedFileId),
    MacroFile(MacroCallId),
}

impl From<EditionedFileId> for HirFileId {
    #[inline]
    fn from(file_id: EditionedFileId) -> Self {
        HirFileId::FileId(file_id)
    }
}

impl From<MacroCallId> for HirFileId {
    #[inline]
    fn from(file_id: MacroCallId) -> Self {
        HirFileId::MacroFile(file_id)
    }
}

impl HirFileId {
    #[inline]
    pub fn macro_file(self) -> Option<MacroCallId> {
        match self {
            HirFileId::FileId(_) => None,
            HirFileId::MacroFile(it) => Some(it),
        }
    }

    #[inline]
    pub fn is_macro(self) -> bool {
        matches!(self, HirFileId::MacroFile(_))
    }

    #[inline]
    pub fn file_id(self) -> Option<EditionedFileId> {
        match self {
            HirFileId::FileId(it) => Some(it),
            HirFileId::MacroFile(_) => None,
        }
    }
}

impl PartialEq<EditionedFileId> for HirFileId {
    fn eq(&self, &other: &EditionedFileId) -> bool {
        *self == HirFileId::from(other)
    }
}
impl PartialEq<HirFileId> for EditionedFileId {
    fn eq(&self, &other: &HirFileId) -> bool {
        other == HirFileId::from(*self)
    }
}
