use crate::base::*;
use crate::config::StripUnconfigured;
use crate::configure;
use crate::hygiene::{ExpnData, ExpnId, ExpnKind, SyntaxContext};
use crate::mbe::macro_rules::annotate_err_with_kind;
use crate::module::{parse_external_mod, push_directory, Directory, DirectoryOwnership};
use crate::placeholders::{placeholder, PlaceholderExpander};
use crate::proc_macro::collect_derives;

use rustc_ast::ast::{self, AttrItem, Block, LitKind, NodeId, PatKind, Path};
use rustc_ast::ast::{ItemKind, MacArgs, MacStmtStyle, StmtKind};
use rustc_ast::mut_visit::*;
use rustc_ast::ptr::P;
use rustc_ast::token;
use rustc_ast::tokenstream::TokenStream;
use rustc_ast::visit::{self, AssocCtxt, Visitor};
use rustc_ast_pretty::pprust;
use rustc_attr::{self as attr, is_builtin_attr, HasAttrs};
use rustc_data_structures::map_in_place::MapInPlace;
use rustc_errors::{Applicability, PResult};
use rustc_feature::Features;
use rustc_parse::parser::Parser;
use rustc_parse::validate_attr;
use rustc_session::lint::builtin::UNUSED_DOC_COMMENTS;
use rustc_session::lint::BuiltinLintDiagnostics;
use rustc_session::parse::{feature_err, ParseSess};
use rustc_session::Limit;
use rustc_span::source_map::respan;
use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::{FileName, Span, DUMMY_SP};

use smallvec::{smallvec, SmallVec};
use std::io::ErrorKind;
use std::ops::DerefMut;
use std::path::PathBuf;
use std::rc::Rc;
use std::{iter, mem, slice};

macro_rules! ast_fragments {
    (
        $($Kind:ident($AstTy:ty) {
            $kind_name:expr;
            $(one fn $mut_visit_ast:ident; fn $visit_ast:ident;)?
            $(many fn $flat_map_ast_elt:ident; fn $visit_ast_elt:ident($($args:tt)*);)?
            fn $make_ast:ident;
        })*
    ) => {
        /// A fragment of AST that can be produced by a single macro expansion.
        /// Can also serve as an input and intermediate result for macro expansion operations.
        pub enum AstFragment {
            OptExpr(Option<P<ast::Expr>>),
            $($Kind($AstTy),)*
        }

        /// "Discriminant" of an AST fragment.
        #[derive(Copy, Clone, PartialEq, Eq)]
        pub enum AstFragmentKind {
            OptExpr,
            $($Kind,)*
        }

        impl AstFragmentKind {
            pub fn name(self) -> &'static str {
                match self {
                    AstFragmentKind::OptExpr => "expression",
                    $(AstFragmentKind::$Kind => $kind_name,)*
                }
            }

            fn make_from<'a>(self, result: Box<dyn MacResult + 'a>) -> Option<AstFragment> {
                match self {
                    AstFragmentKind::OptExpr =>
                        result.make_expr().map(Some).map(AstFragment::OptExpr),
                    $(AstFragmentKind::$Kind => result.$make_ast().map(AstFragment::$Kind),)*
                }
            }
        }

        impl AstFragment {
            pub fn add_placeholders(&mut self, placeholders: &[NodeId]) {
                if placeholders.is_empty() {
                    return;
                }
                match self {
                    $($(AstFragment::$Kind(ast) => ast.extend(placeholders.iter().flat_map(|id| {
                        // We are repeating through arguments with `many`, to do that we have to
                        // mention some macro variable from those arguments even if it's not used.
                        macro _repeating($flat_map_ast_elt) {}
                        placeholder(AstFragmentKind::$Kind, *id, None).$make_ast()
                    })),)?)*
                    _ => panic!("unexpected AST fragment kind")
                }
            }

            pub fn make_opt_expr(self) -> Option<P<ast::Expr>> {
                match self {
                    AstFragment::OptExpr(expr) => expr,
                    _ => panic!("AstFragment::make_* called on the wrong kind of fragment"),
                }
            }

            $(pub fn $make_ast(self) -> $AstTy {
                match self {
                    AstFragment::$Kind(ast) => ast,
                    _ => panic!("AstFragment::make_* called on the wrong kind of fragment"),
                }
            })*

            pub fn mut_visit_with<F: MutVisitor>(&mut self, vis: &mut F) {
                match self {
                    AstFragment::OptExpr(opt_expr) => {
                        visit_clobber(opt_expr, |opt_expr| {
                            if let Some(expr) = opt_expr {
                                vis.filter_map_expr(expr)
                            } else {
                                None
                            }
                        });
                    }
                    $($(AstFragment::$Kind(ast) => vis.$mut_visit_ast(ast),)?)*
                    $($(AstFragment::$Kind(ast) =>
                        ast.flat_map_in_place(|ast| vis.$flat_map_ast_elt(ast)),)?)*
                }
            }

            pub fn visit_with<'a, V: Visitor<'a>>(&'a self, visitor: &mut V) {
                match *self {
                    AstFragment::OptExpr(Some(ref expr)) => visitor.visit_expr(expr),
                    AstFragment::OptExpr(None) => {}
                    $($(AstFragment::$Kind(ref ast) => visitor.$visit_ast(ast),)?)*
                    $($(AstFragment::$Kind(ref ast) => for ast_elt in &ast[..] {
                        visitor.$visit_ast_elt(ast_elt, $($args)*);
                    })?)*
                }
            }
        }

        impl<'a> MacResult for crate::mbe::macro_rules::ParserAnyMacro<'a> {
            $(fn $make_ast(self: Box<crate::mbe::macro_rules::ParserAnyMacro<'a>>)
                           -> Option<$AstTy> {
                Some(self.make(AstFragmentKind::$Kind).$make_ast())
            })*
        }
    }
}

ast_fragments! {
    Expr(P<ast::Expr>) { "expression"; one fn visit_expr; fn visit_expr; fn make_expr; }
    Pat(P<ast::Pat>) { "pattern"; one fn visit_pat; fn visit_pat; fn make_pat; }
    Ty(P<ast::Ty>) { "type"; one fn visit_ty; fn visit_ty; fn make_ty; }
    Stmts(SmallVec<[ast::Stmt; 1]>) {
        "statement"; many fn flat_map_stmt; fn visit_stmt(); fn make_stmts;
    }
    Items(SmallVec<[P<ast::Item>; 1]>) {
        "item"; many fn flat_map_item; fn visit_item(); fn make_items;
    }
    TraitItems(SmallVec<[P<ast::AssocItem>; 1]>) {
        "trait item";
        many fn flat_map_trait_item;
        fn visit_assoc_item(AssocCtxt::Trait);
        fn make_trait_items;
    }
    ImplItems(SmallVec<[P<ast::AssocItem>; 1]>) {
        "impl item";
        many fn flat_map_impl_item;
        fn visit_assoc_item(AssocCtxt::Impl);
        fn make_impl_items;
    }
    ForeignItems(SmallVec<[P<ast::ForeignItem>; 1]>) {
        "foreign item";
        many fn flat_map_foreign_item;
        fn visit_foreign_item();
        fn make_foreign_items;
    }
    Arms(SmallVec<[ast::Arm; 1]>) {
        "match arm"; many fn flat_map_arm; fn visit_arm(); fn make_arms;
    }
    Fields(SmallVec<[ast::Field; 1]>) {
        "field expression"; many fn flat_map_field; fn visit_field(); fn make_fields;
    }
    FieldPats(SmallVec<[ast::FieldPat; 1]>) {
        "field pattern";
        many fn flat_map_field_pattern;
        fn visit_field_pattern();
        fn make_field_patterns;
    }
    GenericParams(SmallVec<[ast::GenericParam; 1]>) {
        "generic parameter";
        many fn flat_map_generic_param;
        fn visit_generic_param();
        fn make_generic_params;
    }
    Params(SmallVec<[ast::Param; 1]>) {
        "function parameter"; many fn flat_map_param; fn visit_param(); fn make_params;
    }
    StructFields(SmallVec<[ast::StructField; 1]>) {
        "field";
        many fn flat_map_struct_field;
        fn visit_struct_field();
        fn make_struct_fields;
    }
    Variants(SmallVec<[ast::Variant; 1]>) {
        "variant"; many fn flat_map_variant; fn visit_variant(); fn make_variants;
    }
}

impl AstFragmentKind {
    crate fn dummy(self, span: Span) -> AstFragment {
        self.make_from(DummyResult::any(span)).expect("couldn't create a dummy AST fragment")
    }

    fn expect_from_annotatables<I: IntoIterator<Item = Annotatable>>(
        self,
        items: I,
    ) -> AstFragment {
        let mut items = items.into_iter();
        match self {
            AstFragmentKind::Arms => {
                AstFragment::Arms(items.map(Annotatable::expect_arm).collect())
            }
            AstFragmentKind::Fields => {
                AstFragment::Fields(items.map(Annotatable::expect_field).collect())
            }
            AstFragmentKind::FieldPats => {
                AstFragment::FieldPats(items.map(Annotatable::expect_field_pattern).collect())
            }
            AstFragmentKind::GenericParams => {
                AstFragment::GenericParams(items.map(Annotatable::expect_generic_param).collect())
            }
            AstFragmentKind::Params => {
                AstFragment::Params(items.map(Annotatable::expect_param).collect())
            }
            AstFragmentKind::StructFields => {
                AstFragment::StructFields(items.map(Annotatable::expect_struct_field).collect())
            }
            AstFragmentKind::Variants => {
                AstFragment::Variants(items.map(Annotatable::expect_variant).collect())
            }
            AstFragmentKind::Items => {
                AstFragment::Items(items.map(Annotatable::expect_item).collect())
            }
            AstFragmentKind::ImplItems => {
                AstFragment::ImplItems(items.map(Annotatable::expect_impl_item).collect())
            }
            AstFragmentKind::TraitItems => {
                AstFragment::TraitItems(items.map(Annotatable::expect_trait_item).collect())
            }
            AstFragmentKind::ForeignItems => {
                AstFragment::ForeignItems(items.map(Annotatable::expect_foreign_item).collect())
            }
            AstFragmentKind::Stmts => {
                AstFragment::Stmts(items.map(Annotatable::expect_stmt).collect())
            }
            AstFragmentKind::Expr => AstFragment::Expr(
                items.next().expect("expected exactly one expression").expect_expr(),
            ),
            AstFragmentKind::OptExpr => {
                AstFragment::OptExpr(items.next().map(Annotatable::expect_expr))
            }
            AstFragmentKind::Pat | AstFragmentKind::Ty => {
                panic!("patterns and types aren't annotatable")
            }
        }
    }
}

pub struct Invocation {
    pub kind: InvocationKind,
    pub fragment_kind: AstFragmentKind,
    pub expansion_data: ExpansionData,
}

pub enum InvocationKind {
    Bang {
        mac: ast::MacCall,
        span: Span,
    },
    Attr {
        attr: ast::Attribute,
        item: Annotatable,
        // Required for resolving derive helper attributes.
        derives: Vec<Path>,
        // We temporarily report errors for attribute macros placed after derives
        after_derive: bool,
    },
    Derive {
        path: Path,
        item: Annotatable,
    },
    /// "Invocation" that contains all derives from an item,
    /// broken into multiple `Derive` invocations when expanded.
    /// FIXME: Find a way to remove it.
    DeriveContainer {
        derives: Vec<Path>,
        item: Annotatable,
    },
}

impl InvocationKind {
    fn placeholder_visibility(&self) -> Option<ast::Visibility> {
        // HACK: For unnamed fields placeholders should have the same visibility as the actual
        // fields because for tuple structs/variants resolve determines visibilities of their
        // constructor using these field visibilities before attributes on them are are expanded.
        // The assumption is that the attribute expansion cannot change field visibilities,
        // and it holds because only inert attributes are supported in this position.
        match self {
            InvocationKind::Attr { item: Annotatable::StructField(field), .. }
            | InvocationKind::Derive { item: Annotatable::StructField(field), .. }
            | InvocationKind::DeriveContainer { item: Annotatable::StructField(field), .. }
                if field.ident.is_none() =>
            {
                Some(field.vis.clone())
            }
            _ => None,
        }
    }
}

impl Invocation {
    pub fn span(&self) -> Span {
        match &self.kind {
            InvocationKind::Bang { span, .. } => *span,
            InvocationKind::Attr { attr, .. } => attr.span,
            InvocationKind::Derive { path, .. } => path.span,
            InvocationKind::DeriveContainer { item, .. } => item.span(),
        }
    }
}

pub struct MacroExpander<'a, 'b> {
    pub cx: &'a mut ExtCtxt<'b>,
    monotonic: bool, // cf. `cx.monotonic_expander()`
}

impl<'a, 'b> MacroExpander<'a, 'b> {
    pub fn new(cx: &'a mut ExtCtxt<'b>, monotonic: bool) -> Self {
        MacroExpander { cx, monotonic }
    }

    pub fn expand_crate(&mut self, mut krate: ast::Crate) -> ast::Crate {
        let mut module = ModuleData {
            mod_path: vec![Ident::from_str(&self.cx.ecfg.crate_name)],
            directory: match self.cx.source_map().span_to_unmapped_path(krate.span) {
                FileName::Real(name) => name.into_local_path(),
                other => PathBuf::from(other.to_string()),
            },
        };
        module.directory.pop();
        self.cx.root_path = module.directory.clone();
        self.cx.current_expansion.module = Rc::new(module);

        let orig_mod_span = krate.module.inner;

        let krate_item = AstFragment::Items(smallvec![P(ast::Item {
            attrs: krate.attrs,
            span: krate.span,
            kind: ast::ItemKind::Mod(krate.module),
            ident: Ident::invalid(),
            id: ast::DUMMY_NODE_ID,
            vis: respan(krate.span.shrink_to_lo(), ast::VisibilityKind::Public),
            tokens: None,
        })]);

        match self.fully_expand_fragment(krate_item).make_items().pop().map(P::into_inner) {
            Some(ast::Item { attrs, kind: ast::ItemKind::Mod(module), .. }) => {
                krate.attrs = attrs;
                krate.module = module;
            }
            None => {
                // Resolution failed so we return an empty expansion
                krate.attrs = vec![];
                krate.module = ast::Mod { inner: orig_mod_span, items: vec![], inline: true };
            }
            Some(ast::Item { span, kind, .. }) => {
                krate.attrs = vec![];
                krate.module = ast::Mod { inner: orig_mod_span, items: vec![], inline: true };
                self.cx.span_err(
                    span,
                    &format!(
                        "expected crate top-level item to be a module after macro expansion, found {} {}",
                        kind.article(), kind.descr()
                    ),
                );
            }
        };
        self.cx.trace_macros_diag();
        krate
    }

    // Recursively expand all macro invocations in this AST fragment.
    pub fn fully_expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragment {
        let orig_expansion_data = self.cx.current_expansion.clone();
        self.cx.current_expansion.depth = 0;

        // Collect all macro invocations and replace them with placeholders.
        let (mut fragment_with_placeholders, mut invocations) =
            self.collect_invocations(input_fragment, &[]);

        // Optimization: if we resolve all imports now,
        // we'll be able to immediately resolve most of imported macros.
        self.resolve_imports();

        // Resolve paths in all invocations and produce output expanded fragments for them, but
        // do not insert them into our input AST fragment yet, only store in `expanded_fragments`.
        // The output fragments also go through expansion recursively until no invocations are left.
        // Unresolved macros produce dummy outputs as a recovery measure.
        invocations.reverse();
        let mut expanded_fragments = Vec::new();
        let mut undetermined_invocations = Vec::new();
        let (mut progress, mut force) = (false, !self.monotonic);
        loop {
            let (invoc, res) = if let Some(invoc) = invocations.pop() {
                invoc
            } else {
                self.resolve_imports();
                if undetermined_invocations.is_empty() {
                    break;
                }
                invocations = mem::take(&mut undetermined_invocations);
                force = !mem::replace(&mut progress, false);
                continue;
            };

            let res = match res {
                Some(res) => res,
                None => {
                    let eager_expansion_root = if self.monotonic {
                        invoc.expansion_data.id
                    } else {
                        orig_expansion_data.id
                    };
                    match self.cx.resolver.resolve_macro_invocation(
                        &invoc,
                        eager_expansion_root,
                        force,
                    ) {
                        Ok(res) => res,
                        Err(Indeterminate) => {
                            // Cannot resolve, will retry this invocation later.
                            undetermined_invocations.push((invoc, None));
                            continue;
                        }
                    }
                }
            };

            let ExpansionData { depth, id: expn_id, .. } = invoc.expansion_data;
            self.cx.current_expansion = invoc.expansion_data.clone();

            // FIXME(jseyfried): Refactor out the following logic
            let (expanded_fragment, new_invocations) = match res {
                InvocationRes::Single(ext) => match self.expand_invoc(invoc, &ext.kind) {
                    ExpandResult::Ready(fragment) => self.collect_invocations(fragment, &[]),
                    ExpandResult::Retry(invoc, explanation) => {
                        if force {
                            // We are stuck, stop retrying and produce a dummy fragment.
                            let span = invoc.span();
                            self.cx.span_err(span, &explanation);
                            let fragment = invoc.fragment_kind.dummy(span);
                            self.collect_invocations(fragment, &[])
                        } else {
                            // Cannot expand, will retry this invocation later.
                            undetermined_invocations
                                .push((invoc, Some(InvocationRes::Single(ext))));
                            continue;
                        }
                    }
                },
                InvocationRes::DeriveContainer(_exts) => {
                    // FIXME: Consider using the derive resolutions (`_exts`) immediately,
                    // instead of enqueuing the derives to be resolved again later.
                    let (derives, item) = match invoc.kind {
                        InvocationKind::DeriveContainer { derives, item } => (derives, item),
                        _ => unreachable!(),
                    };
                    if !item.derive_allowed() {
                        self.error_derive_forbidden_on_non_adt(&derives, &item);
                    }

                    let mut item = self.fully_configure(item);
                    item.visit_attrs(|attrs| attrs.retain(|a| !a.has_name(sym::derive)));

                    let mut derive_placeholders = Vec::with_capacity(derives.len());
                    invocations.reserve(derives.len());
                    for path in derives {
                        let expn_id = ExpnId::fresh(None);
                        derive_placeholders.push(NodeId::placeholder_from_expn_id(expn_id));
                        invocations.push((
                            Invocation {
                                kind: InvocationKind::Derive { path, item: item.clone() },
                                fragment_kind: invoc.fragment_kind,
                                expansion_data: ExpansionData {
                                    id: expn_id,
                                    ..invoc.expansion_data.clone()
                                },
                            },
                            None,
                        ));
                    }
                    let fragment =
                        invoc.fragment_kind.expect_from_annotatables(::std::iter::once(item));
                    self.collect_invocations(fragment, &derive_placeholders)
                }
            };

            progress = true;
            if expanded_fragments.len() < depth {
                expanded_fragments.push(Vec::new());
            }
            expanded_fragments[depth - 1].push((expn_id, expanded_fragment));
            invocations.extend(new_invocations.into_iter().rev());
        }

        self.cx.current_expansion = orig_expansion_data;

        // Finally incorporate all the expanded macros into the input AST fragment.
        let mut placeholder_expander = PlaceholderExpander::new(self.cx, self.monotonic);
        while let Some(expanded_fragments) = expanded_fragments.pop() {
            for (expn_id, expanded_fragment) in expanded_fragments.into_iter().rev() {
                placeholder_expander
                    .add(NodeId::placeholder_from_expn_id(expn_id), expanded_fragment);
            }
        }
        fragment_with_placeholders.mut_visit_with(&mut placeholder_expander);
        fragment_with_placeholders
    }

    fn error_derive_forbidden_on_non_adt(&self, derives: &[Path], item: &Annotatable) {
        let attr = attr::find_by_name(item.attrs(), sym::derive);
        let span = attr.map_or(item.span(), |attr| attr.span);
        let mut err = self
            .cx
            .struct_span_err(span, "`derive` may only be applied to structs, enums and unions");
        if let Some(ast::Attribute { style: ast::AttrStyle::Inner, .. }) = attr {
            let trait_list = derives.iter().map(|t| pprust::path_to_string(t)).collect::<Vec<_>>();
            let suggestion = format!("#[derive({})]", trait_list.join(", "));
            err.span_suggestion(
                span,
                "try an outer attribute",
                suggestion,
                // We don't 𝑘𝑛𝑜𝑤 that the following item is an ADT
                Applicability::MaybeIncorrect,
            );
        }
        err.emit();
    }

    fn resolve_imports(&mut self) {
        if self.monotonic {
            self.cx.resolver.resolve_imports();
        }
    }

    /// Collects all macro invocations reachable at this time in this AST fragment, and replace
    /// them with "placeholders" - dummy macro invocations with specially crafted `NodeId`s.
    /// Then call into resolver that builds a skeleton ("reduced graph") of the fragment and
    /// prepares data for resolving paths of macro invocations.
    fn collect_invocations(
        &mut self,
        mut fragment: AstFragment,
        extra_placeholders: &[NodeId],
    ) -> (AstFragment, Vec<(Invocation, Option<InvocationRes>)>) {
        // Resolve `$crate`s in the fragment for pretty-printing.
        self.cx.resolver.resolve_dollar_crates();

        let invocations = {
            let mut collector = InvocationCollector {
                cfg: StripUnconfigured {
                    sess: self.cx.parse_sess,
                    features: self.cx.ecfg.features,
                },
                cx: self.cx,
                invocations: Vec::new(),
                monotonic: self.monotonic,
            };
            fragment.mut_visit_with(&mut collector);
            fragment.add_placeholders(extra_placeholders);
            collector.invocations
        };

        if self.monotonic {
            self.cx
                .resolver
                .visit_ast_fragment_with_placeholders(self.cx.current_expansion.id, &fragment);
        }

        (fragment, invocations)
    }

    fn fully_configure(&mut self, item: Annotatable) -> Annotatable {
        let mut cfg =
            StripUnconfigured { sess: self.cx.parse_sess, features: self.cx.ecfg.features };
        // Since the item itself has already been configured by the InvocationCollector,
        // we know that fold result vector will contain exactly one element
        match item {
            Annotatable::Item(item) => Annotatable::Item(cfg.flat_map_item(item).pop().unwrap()),
            Annotatable::TraitItem(item) => {
                Annotatable::TraitItem(cfg.flat_map_trait_item(item).pop().unwrap())
            }
            Annotatable::ImplItem(item) => {
                Annotatable::ImplItem(cfg.flat_map_impl_item(item).pop().unwrap())
            }
            Annotatable::ForeignItem(item) => {
                Annotatable::ForeignItem(cfg.flat_map_foreign_item(item).pop().unwrap())
            }
            Annotatable::Stmt(stmt) => {
                Annotatable::Stmt(stmt.map(|stmt| cfg.flat_map_stmt(stmt).pop().unwrap()))
            }
            Annotatable::Expr(mut expr) => Annotatable::Expr({
                cfg.visit_expr(&mut expr);
                expr
            }),
            Annotatable::Arm(arm) => Annotatable::Arm(cfg.flat_map_arm(arm).pop().unwrap()),
            Annotatable::Field(field) => {
                Annotatable::Field(cfg.flat_map_field(field).pop().unwrap())
            }
            Annotatable::FieldPat(fp) => {
                Annotatable::FieldPat(cfg.flat_map_field_pattern(fp).pop().unwrap())
            }
            Annotatable::GenericParam(param) => {
                Annotatable::GenericParam(cfg.flat_map_generic_param(param).pop().unwrap())
            }
            Annotatable::Param(param) => {
                Annotatable::Param(cfg.flat_map_param(param).pop().unwrap())
            }
            Annotatable::StructField(sf) => {
                Annotatable::StructField(cfg.flat_map_struct_field(sf).pop().unwrap())
            }
            Annotatable::Variant(v) => Annotatable::Variant(cfg.flat_map_variant(v).pop().unwrap()),
        }
    }

    fn error_recursion_limit_reached(&mut self) {
        let expn_data = self.cx.current_expansion.id.expn_data();
        let suggested_limit = self.cx.ecfg.recursion_limit * 2;
        self.cx
            .struct_span_err(
                expn_data.call_site,
                &format!("recursion limit reached while expanding `{}`", expn_data.kind.descr()),
            )
            .help(&format!(
                "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate (`{}`)",
                suggested_limit, self.cx.ecfg.crate_name,
            ))
            .emit();
        self.cx.trace_macros_diag();
    }

    /// A macro's expansion does not fit in this fragment kind.
    /// For example, a non-type macro in a type position.
    fn error_wrong_fragment_kind(&mut self, kind: AstFragmentKind, mac: &ast::MacCall, span: Span) {
        let msg = format!(
            "non-{kind} macro in {kind} position: {path}",
            kind = kind.name(),
            path = pprust::path_to_string(&mac.path),
        );
        self.cx.span_err(span, &msg);
        self.cx.trace_macros_diag();
    }

    fn expand_invoc(
        &mut self,
        invoc: Invocation,
        ext: &SyntaxExtensionKind,
    ) -> ExpandResult<AstFragment, Invocation> {
        let recursion_limit =
            self.cx.reduced_recursion_limit.unwrap_or(self.cx.ecfg.recursion_limit);
        if !recursion_limit.value_within_limit(self.cx.current_expansion.depth) {
            if self.cx.reduced_recursion_limit.is_none() {
                self.error_recursion_limit_reached();
            }

            // Reduce the recursion limit by half each time it triggers.
            self.cx.reduced_recursion_limit = Some(recursion_limit / 2);

            return ExpandResult::Ready(invoc.fragment_kind.dummy(invoc.span()));
        }

        let (fragment_kind, span) = (invoc.fragment_kind, invoc.span());
        ExpandResult::Ready(match invoc.kind {
            InvocationKind::Bang { mac, .. } => match ext {
                SyntaxExtensionKind::Bang(expander) => {
                    let tok_result = match expander.expand(self.cx, span, mac.args.inner_tokens()) {
                        Err(_) => return ExpandResult::Ready(fragment_kind.dummy(span)),
                        Ok(ts) => ts,
                    };
                    self.parse_ast_fragment(tok_result, fragment_kind, &mac.path, span)
                }
                SyntaxExtensionKind::LegacyBang(expander) => {
                    let prev = self.cx.current_expansion.prior_type_ascription;
                    self.cx.current_expansion.prior_type_ascription = mac.prior_type_ascription;
                    let tok_result = expander.expand(self.cx, span, mac.args.inner_tokens());
                    let result = if let Some(result) = fragment_kind.make_from(tok_result) {
                        result
                    } else {
                        self.error_wrong_fragment_kind(fragment_kind, &mac, span);
                        fragment_kind.dummy(span)
                    };
                    self.cx.current_expansion.prior_type_ascription = prev;
                    result
                }
                _ => unreachable!(),
            },
            InvocationKind::Attr { attr, mut item, derives, after_derive } => match ext {
                SyntaxExtensionKind::Attr(expander) => {
                    self.gate_proc_macro_input(&item);
                    self.gate_proc_macro_attr_item(span, &item);
                    let tokens = item.into_tokens(self.cx.parse_sess);
                    let attr_item = attr.unwrap_normal_item();
                    if let MacArgs::Eq(..) = attr_item.args {
                        self.cx.span_err(span, "key-value macro attributes are not supported");
                    }
                    let inner_tokens = attr_item.args.inner_tokens();
                    let tok_result = match expander.expand(self.cx, span, inner_tokens, tokens) {
                        Err(_) => return ExpandResult::Ready(fragment_kind.dummy(span)),
                        Ok(ts) => ts,
                    };
                    self.parse_ast_fragment(tok_result, fragment_kind, &attr_item.path, span)
                }
                SyntaxExtensionKind::LegacyAttr(expander) => {
                    match validate_attr::parse_meta(self.cx.parse_sess, &attr) {
                        Ok(meta) => {
                            let items = match expander.expand(self.cx, span, &meta, item) {
                                ExpandResult::Ready(items) => items,
                                ExpandResult::Retry(item, explanation) => {
                                    // Reassemble the original invocation for retrying.
                                    return ExpandResult::Retry(
                                        Invocation {
                                            kind: InvocationKind::Attr {
                                                attr,
                                                item,
                                                derives,
                                                after_derive,
                                            },
                                            ..invoc
                                        },
                                        explanation,
                                    );
                                }
                            };
                            fragment_kind.expect_from_annotatables(items)
                        }
                        Err(mut err) => {
                            err.emit();
                            fragment_kind.dummy(span)
                        }
                    }
                }
                SyntaxExtensionKind::NonMacroAttr { mark_used } => {
                    attr::mark_known(&attr);
                    if *mark_used {
                        attr::mark_used(&attr);
                    }
                    item.visit_attrs(|attrs| attrs.push(attr));
                    fragment_kind.expect_from_annotatables(iter::once(item))
                }
                _ => unreachable!(),
            },
            InvocationKind::Derive { path, item } => match ext {
                SyntaxExtensionKind::Derive(expander)
                | SyntaxExtensionKind::LegacyDerive(expander) => {
                    if !item.derive_allowed() {
                        return ExpandResult::Ready(fragment_kind.dummy(span));
                    }
                    if let SyntaxExtensionKind::Derive(..) = ext {
                        self.gate_proc_macro_input(&item);
                    }
                    let meta = ast::MetaItem { kind: ast::MetaItemKind::Word, span, path };
                    let items = match expander.expand(self.cx, span, &meta, item) {
                        ExpandResult::Ready(items) => items,
                        ExpandResult::Retry(item, explanation) => {
                            // Reassemble the original invocation for retrying.
                            return ExpandResult::Retry(
                                Invocation {
                                    kind: InvocationKind::Derive { path: meta.path, item },
                                    ..invoc
                                },
                                explanation,
                            );
                        }
                    };
                    fragment_kind.expect_from_annotatables(items)
                }
                _ => unreachable!(),
            },
            InvocationKind::DeriveContainer { .. } => unreachable!(),
        })
    }

    fn gate_proc_macro_attr_item(&self, span: Span, item: &Annotatable) {
        let kind = match item {
            Annotatable::Item(_)
            | Annotatable::TraitItem(_)
            | Annotatable::ImplItem(_)
            | Annotatable::ForeignItem(_) => return,
            Annotatable::Stmt(_) => "statements",
            Annotatable::Expr(_) => "expressions",
            Annotatable::Arm(..)
            | Annotatable::Field(..)
            | Annotatable::FieldPat(..)
            | Annotatable::GenericParam(..)
            | Annotatable::Param(..)
            | Annotatable::StructField(..)
            | Annotatable::Variant(..) => panic!("unexpected annotatable"),
        };
        if self.cx.ecfg.proc_macro_hygiene() {
            return;
        }
        feature_err(
            self.cx.parse_sess,
            sym::proc_macro_hygiene,
            span,
            &format!("custom attributes cannot be applied to {}", kind),
        )
        .emit();
    }

    fn gate_proc_macro_input(&self, annotatable: &Annotatable) {
        struct GateProcMacroInput<'a> {
            parse_sess: &'a ParseSess,
        }

        impl<'ast, 'a> Visitor<'ast> for GateProcMacroInput<'a> {
            fn visit_item(&mut self, item: &'ast ast::Item) {
                match &item.kind {
                    ast::ItemKind::Mod(module) if !module.inline => {
                        feature_err(
                            self.parse_sess,
                            sym::proc_macro_hygiene,
                            item.span,
                            "non-inline modules in proc macro input are unstable",
                        )
                        .emit();
                    }
                    _ => {}
                }

                visit::walk_item(self, item);
            }

            fn visit_mac(&mut self, _: &'ast ast::MacCall) {}
        }

        if !self.cx.ecfg.proc_macro_hygiene() {
            annotatable.visit_with(&mut GateProcMacroInput { parse_sess: self.cx.parse_sess });
        }
    }

    fn parse_ast_fragment(
        &mut self,
        toks: TokenStream,
        kind: AstFragmentKind,
        path: &Path,
        span: Span,
    ) -> AstFragment {
        let mut parser = self.cx.new_parser_from_tts(toks);
        match parse_ast_fragment(&mut parser, kind) {
            Ok(fragment) => {
                ensure_complete_parse(&mut parser, path, kind.name(), span);
                fragment
            }
            Err(mut err) => {
                err.set_span(span);
                annotate_err_with_kind(&mut err, kind, span);
                err.emit();
                self.cx.trace_macros_diag();
                kind.dummy(span)
            }
        }
    }
}

pub fn parse_ast_fragment<'a>(
    this: &mut Parser<'a>,
    kind: AstFragmentKind,
) -> PResult<'a, AstFragment> {
    Ok(match kind {
        AstFragmentKind::Items => {
            let mut items = SmallVec::new();
            while let Some(item) = this.parse_item()? {
                items.push(item);
            }
            AstFragment::Items(items)
        }
        AstFragmentKind::TraitItems => {
            let mut items = SmallVec::new();
            while let Some(item) = this.parse_trait_item()? {
                items.extend(item);
            }
            AstFragment::TraitItems(items)
        }
        AstFragmentKind::ImplItems => {
            let mut items = SmallVec::new();
            while let Some(item) = this.parse_impl_item()? {
                items.extend(item);
            }
            AstFragment::ImplItems(items)
        }
        AstFragmentKind::ForeignItems => {
            let mut items = SmallVec::new();
            while let Some(item) = this.parse_foreign_item()? {
                items.extend(item);
            }
            AstFragment::ForeignItems(items)
        }
        AstFragmentKind::Stmts => {
            let mut stmts = SmallVec::new();
            // Won't make progress on a `}`.
            while this.token != token::Eof && this.token != token::CloseDelim(token::Brace) {
                if let Some(stmt) = this.parse_full_stmt()? {
                    stmts.push(stmt);
                }
            }
            AstFragment::Stmts(stmts)
        }
        AstFragmentKind::Expr => AstFragment::Expr(this.parse_expr()?),
        AstFragmentKind::OptExpr => {
            if this.token != token::Eof {
                AstFragment::OptExpr(Some(this.parse_expr()?))
            } else {
                AstFragment::OptExpr(None)
            }
        }
        AstFragmentKind::Ty => AstFragment::Ty(this.parse_ty()?),
        AstFragmentKind::Pat => AstFragment::Pat(this.parse_pat(None)?),
        AstFragmentKind::Arms
        | AstFragmentKind::Fields
        | AstFragmentKind::FieldPats
        | AstFragmentKind::GenericParams
        | AstFragmentKind::Params
        | AstFragmentKind::StructFields
        | AstFragmentKind::Variants => panic!("unexpected AST fragment kind"),
    })
}

pub fn ensure_complete_parse<'a>(
    this: &mut Parser<'a>,
    macro_path: &Path,
    kind_name: &str,
    span: Span,
) {
    if this.token != token::Eof {
        let token = pprust::token_to_string(&this.token);
        let msg = format!("macro expansion ignores token `{}` and any following", token);
        // Avoid emitting backtrace info twice.
        let def_site_span = this.token.span.with_ctxt(SyntaxContext::root());
        let mut err = this.struct_span_err(def_site_span, &msg);
        err.span_label(span, "caused by the macro expansion here");
        let msg = format!(
            "the usage of `{}!` is likely invalid in {} context",
            pprust::path_to_string(macro_path),
            kind_name,
        );
        err.note(&msg);
        let semi_span = this.sess.source_map().next_point(span);

        let semi_full_span = semi_span.to(this.sess.source_map().next_point(semi_span));
        match this.sess.source_map().span_to_snippet(semi_full_span) {
            Ok(ref snippet) if &snippet[..] != ";" && kind_name == "expression" => {
                err.span_suggestion(
                    semi_span,
                    "you might be missing a semicolon here",
                    ";".to_owned(),
                    Applicability::MaybeIncorrect,
                );
            }
            _ => {}
        }
        err.emit();
    }
}

struct InvocationCollector<'a, 'b> {
    cx: &'a mut ExtCtxt<'b>,
    cfg: StripUnconfigured<'a>,
    invocations: Vec<(Invocation, Option<InvocationRes>)>,
    monotonic: bool,
}

impl<'a, 'b> InvocationCollector<'a, 'b> {
    fn collect(&mut self, fragment_kind: AstFragmentKind, kind: InvocationKind) -> AstFragment {
        // Expansion data for all the collected invocations is set upon their resolution,
        // with exception of the derive container case which is not resolved and can get
        // its expansion data immediately.
        let expn_data = match &kind {
            InvocationKind::DeriveContainer { item, .. } => Some(ExpnData {
                parent: self.cx.current_expansion.id,
                ..ExpnData::default(
                    ExpnKind::Macro(MacroKind::Attr, sym::derive),
                    item.span(),
                    self.cx.parse_sess.edition,
                    None,
                )
            }),
            _ => None,
        };
        let expn_id = ExpnId::fresh(expn_data);
        let vis = kind.placeholder_visibility();
        self.invocations.push((
            Invocation {
                kind,
                fragment_kind,
                expansion_data: ExpansionData {
                    id: expn_id,
                    depth: self.cx.current_expansion.depth + 1,
                    ..self.cx.current_expansion.clone()
                },
            },
            None,
        ));
        placeholder(fragment_kind, NodeId::placeholder_from_expn_id(expn_id), vis)
    }

    fn collect_bang(
        &mut self,
        mac: ast::MacCall,
        span: Span,
        kind: AstFragmentKind,
    ) -> AstFragment {
        self.collect(kind, InvocationKind::Bang { mac, span })
    }

    fn collect_attr(
        &mut self,
        attr: Option<ast::Attribute>,
        derives: Vec<Path>,
        item: Annotatable,
        kind: AstFragmentKind,
        after_derive: bool,
    ) -> AstFragment {
        self.collect(
            kind,
            match attr {
                Some(attr) => InvocationKind::Attr { attr, item, derives, after_derive },
                None => InvocationKind::DeriveContainer { derives, item },
            },
        )
    }

    fn find_attr_invoc(
        &self,
        attrs: &mut Vec<ast::Attribute>,
        after_derive: &mut bool,
    ) -> Option<ast::Attribute> {
        let attr = attrs
            .iter()
            .position(|a| {
                if a.has_name(sym::derive) {
                    *after_derive = true;
                }
                !attr::is_known(a) && !is_builtin_attr(a)
            })
            .map(|i| attrs.remove(i));
        if let Some(attr) = &attr {
            if !self.cx.ecfg.custom_inner_attributes()
                && attr.style == ast::AttrStyle::Inner
                && !attr.has_name(sym::test)
            {
                feature_err(
                    &self.cx.parse_sess,
                    sym::custom_inner_attributes,
                    attr.span,
                    "non-builtin inner attributes are unstable",
                )
                .emit();
            }
        }
        attr
    }

    /// If `item` is an attr invocation, remove and return the macro attribute and derive traits.
    fn classify_item(
        &mut self,
        item: &mut impl HasAttrs,
    ) -> (Option<ast::Attribute>, Vec<Path>, /* after_derive */ bool) {
        let (mut attr, mut traits, mut after_derive) = (None, Vec::new(), false);

        item.visit_attrs(|mut attrs| {
            attr = self.find_attr_invoc(&mut attrs, &mut after_derive);
            traits = collect_derives(&mut self.cx, &mut attrs);
        });

        (attr, traits, after_derive)
    }

    /// Alternative to `classify_item()` that ignores `#[derive]` so invocations fallthrough
    /// to the unused-attributes lint (making it an error on statements and expressions
    /// is a breaking change)
    fn classify_nonitem(
        &mut self,
        nonitem: &mut impl HasAttrs,
    ) -> (Option<ast::Attribute>, /* after_derive */ bool) {
        let (mut attr, mut after_derive) = (None, false);

        nonitem.visit_attrs(|mut attrs| {
            attr = self.find_attr_invoc(&mut attrs, &mut after_derive);
        });

        (attr, after_derive)
    }

    fn configure<T: HasAttrs>(&mut self, node: T) -> Option<T> {
        self.cfg.configure(node)
    }

    // Detect use of feature-gated or invalid attributes on macro invocations
    // since they will not be detected after macro expansion.
    fn check_attributes(&mut self, attrs: &[ast::Attribute]) {
        let features = self.cx.ecfg.features.unwrap();
        for attr in attrs.iter() {
            rustc_ast_passes::feature_gate::check_attribute(attr, self.cx.parse_sess, features);
            validate_attr::check_meta(self.cx.parse_sess, attr);

            // macros are expanded before any lint passes so this warning has to be hardcoded
            if attr.has_name(sym::derive) {
                self.cx
                    .parse_sess()
                    .span_diagnostic
                    .struct_span_warn(attr.span, "`#[derive]` does nothing on macro invocations")
                    .note("this may become a hard error in a future release")
                    .emit();
            }

            if attr.doc_str().is_some() {
                self.cx.parse_sess.buffer_lint_with_diagnostic(
                    &UNUSED_DOC_COMMENTS,
                    attr.span,
                    ast::CRATE_NODE_ID,
                    "unused doc comment",
                    BuiltinLintDiagnostics::UnusedDocComment(attr.span),
                );
            }
        }
    }
}

impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
    fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
        self.cfg.configure_expr(expr);
        visit_clobber(expr.deref_mut(), |mut expr| {
            self.cfg.configure_expr_kind(&mut expr.kind);

            // ignore derives so they remain unused
            let (attr, after_derive) = self.classify_nonitem(&mut expr);

            if let Some(ref attr_value) = attr {
                // Collect the invoc regardless of whether or not attributes are permitted here
                // expansion will eat the attribute so it won't error later.
                self.cfg.maybe_emit_expr_attr_err(attr_value);

                // AstFragmentKind::Expr requires the macro to emit an expression.
                return self
                    .collect_attr(
                        attr,
                        vec![],
                        Annotatable::Expr(P(expr)),
                        AstFragmentKind::Expr,
                        after_derive,
                    )
                    .make_expr()
                    .into_inner();
            }

            if let ast::ExprKind::MacCall(mac) = expr.kind {
                self.check_attributes(&expr.attrs);
                self.collect_bang(mac, expr.span, AstFragmentKind::Expr).make_expr().into_inner()
            } else {
                noop_visit_expr(&mut expr, self);
                expr
            }
        });
    }

    fn flat_map_arm(&mut self, arm: ast::Arm) -> SmallVec<[ast::Arm; 1]> {
        let mut arm = configure!(self, arm);

        let (attr, traits, after_derive) = self.classify_item(&mut arm);
        if attr.is_some() || !traits.is_empty() {
            return self
                .collect_attr(
                    attr,
                    traits,
                    Annotatable::Arm(arm),
                    AstFragmentKind::Arms,
                    after_derive,
                )
                .make_arms();
        }

        noop_flat_map_arm(arm, self)
    }

    fn flat_map_field(&mut self, field: ast::Field) -> SmallVec<[ast::Field; 1]> {
        let mut field = configure!(self, field);

        let (attr, traits, after_derive) = self.classify_item(&mut field);
        if attr.is_some() || !traits.is_empty() {
            return self
                .collect_attr(
                    attr,
                    traits,
                    Annotatable::Field(field),
                    AstFragmentKind::Fields,
                    after_derive,
                )
                .make_fields();
        }

        noop_flat_map_field(field, self)
    }

    fn flat_map_field_pattern(&mut self, fp: ast::FieldPat) -> SmallVec<[ast::FieldPat; 1]> {
        let mut fp = configure!(self, fp);

        let (attr, traits, after_derive) = self.classify_item(&mut fp);
        if attr.is_some() || !traits.is_empty() {
            return self
                .collect_attr(
                    attr,
                    traits,
                    Annotatable::FieldPat(fp),
                    AstFragmentKind::FieldPats,
                    after_derive,
                )
                .make_field_patterns();
        }

        noop_flat_map_field_pattern(fp, self)
    }

    fn flat_map_param(&mut self, p: ast::Param) -> SmallVec<[ast::Param; 1]> {
        let mut p = configure!(self, p);

        let (attr, traits, after_derive) = self.classify_item(&mut p);
        if attr.is_some() || !traits.is_empty() {
            return self
                .collect_attr(
                    attr,
                    traits,
                    Annotatable::Param(p),
                    AstFragmentKind::Params,
                    after_derive,
                )
                .make_params();
        }

        noop_flat_map_param(p, self)
    }

    fn flat_map_struct_field(&mut self, sf: ast::StructField) -> SmallVec<[ast::StructField; 1]> {
        let mut sf = configure!(self, sf);

        let (attr, traits, after_derive) = self.classify_item(&mut sf);
        if attr.is_some() || !traits.is_empty() {
            return self
                .collect_attr(
                    attr,
                    traits,
                    Annotatable::StructField(sf),
                    AstFragmentKind::StructFields,
                    after_derive,
                )
                .make_struct_fields();
        }

        noop_flat_map_struct_field(sf, self)
    }

    fn flat_map_variant(&mut self, variant: ast::Variant) -> SmallVec<[ast::Variant; 1]> {
        let mut variant = configure!(self, variant);

        let (attr, traits, after_derive) = self.classify_item(&mut variant);
        if attr.is_some() || !traits.is_empty() {
            return self
                .collect_attr(
                    attr,
                    traits,
                    Annotatable::Variant(variant),
                    AstFragmentKind::Variants,
                    after_derive,
                )
                .make_variants();
        }

        noop_flat_map_variant(variant, self)
    }

    fn filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
        let expr = configure!(self, expr);
        expr.filter_map(|mut expr| {
            self.cfg.configure_expr_kind(&mut expr.kind);

            // Ignore derives so they remain unused.
            let (attr, after_derive) = self.classify_nonitem(&mut expr);

            if let Some(ref attr_value) = attr {
                self.cfg.maybe_emit_expr_attr_err(attr_value);

                return self
                    .collect_attr(
                        attr,
                        vec![],
                        Annotatable::Expr(P(expr)),
                        AstFragmentKind::OptExpr,
                        after_derive,
                    )
                    .make_opt_expr()
                    .map(|expr| expr.into_inner());
            }

            if let ast::ExprKind::MacCall(mac) = expr.kind {
                self.check_attributes(&expr.attrs);
                self.collect_bang(mac, expr.span, AstFragmentKind::OptExpr)
                    .make_opt_expr()
                    .map(|expr| expr.into_inner())
            } else {
                Some({
                    noop_visit_expr(&mut expr, self);
                    expr
                })
            }
        })
    }

    fn visit_pat(&mut self, pat: &mut P<ast::Pat>) {
        self.cfg.configure_pat(pat);
        match pat.kind {
            PatKind::MacCall(_) => {}
            _ => return noop_visit_pat(pat, self),
        }

        visit_clobber(pat, |mut pat| match mem::replace(&mut pat.kind, PatKind::Wild) {
            PatKind::MacCall(mac) => {
                self.collect_bang(mac, pat.span, AstFragmentKind::Pat).make_pat()
            }
            _ => unreachable!(),
        });
    }

    fn flat_map_stmt(&mut self, stmt: ast::Stmt) -> SmallVec<[ast::Stmt; 1]> {
        let mut stmt = configure!(self, stmt);

        // we'll expand attributes on expressions separately
        if !stmt.is_expr() {
            let (attr, derives, after_derive) = if stmt.is_item() {
                self.classify_item(&mut stmt)
            } else {
                // ignore derives on non-item statements so it falls through
                // to the unused-attributes lint
                let (attr, after_derive) = self.classify_nonitem(&mut stmt);
                (attr, vec![], after_derive)
            };

            if attr.is_some() || !derives.is_empty() {
                return self
                    .collect_attr(
                        attr,
                        derives,
                        Annotatable::Stmt(P(stmt)),
                        AstFragmentKind::Stmts,
                        after_derive,
                    )
                    .make_stmts();
            }
        }

        if let StmtKind::MacCall(mac) = stmt.kind {
            let (mac, style, attrs) = mac.into_inner();
            self.check_attributes(&attrs);
            let mut placeholder =
                self.collect_bang(mac, stmt.span, AstFragmentKind::Stmts).make_stmts();

            // If this is a macro invocation with a semicolon, then apply that
            // semicolon to the final statement produced by expansion.
            if style == MacStmtStyle::Semicolon {
                if let Some(stmt) = placeholder.pop() {
                    placeholder.push(stmt.add_trailing_semicolon());
                }
            }

            return placeholder;
        }

        // The placeholder expander gives ids to statements, so we avoid folding the id here.
        let ast::Stmt { id, kind, span } = stmt;
        noop_flat_map_stmt_kind(kind, self)
            .into_iter()
            .map(|kind| ast::Stmt { id, kind, span })
            .collect()
    }

    fn visit_block(&mut self, block: &mut P<Block>) {
        let old_directory_ownership = self.cx.current_expansion.directory_ownership;
        self.cx.current_expansion.directory_ownership = DirectoryOwnership::UnownedViaBlock;
        noop_visit_block(block, self);
        self.cx.current_expansion.directory_ownership = old_directory_ownership;
    }

    fn flat_map_item(&mut self, item: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
        let mut item = configure!(self, item);

        let (attr, traits, after_derive) = self.classify_item(&mut item);
        if attr.is_some() || !traits.is_empty() {
            return self
                .collect_attr(
                    attr,
                    traits,
                    Annotatable::Item(item),
                    AstFragmentKind::Items,
                    after_derive,
                )
                .make_items();
        }

        let mut attrs = mem::take(&mut item.attrs); // We do this to please borrowck.
        let ident = item.ident;
        let span = item.span;

        match item.kind {
            ast::ItemKind::MacCall(..) => {
                item.attrs = attrs;
                self.check_attributes(&item.attrs);
                item.and_then(|item| match item.kind {
                    ItemKind::MacCall(mac) => self
                        .collect(AstFragmentKind::Items, InvocationKind::Bang { mac, span })
                        .make_items(),
                    _ => unreachable!(),
                })
            }
            ast::ItemKind::Mod(ref mut old_mod @ ast::Mod { .. }) if ident != Ident::invalid() => {
                let sess = self.cx.parse_sess;
                let orig_ownership = self.cx.current_expansion.directory_ownership;
                let mut module = (*self.cx.current_expansion.module).clone();

                let pushed = &mut false; // Record `parse_external_mod` pushing so we can pop.
                let dir = Directory { ownership: orig_ownership, path: module.directory };
                let Directory { ownership, path } = if old_mod.inline {
                    // Inline `mod foo { ... }`, but we still need to push directories.
                    item.attrs = attrs;
                    push_directory(ident, &item.attrs, dir)
                } else {
                    // We have an outline `mod foo;` so we need to parse the file.
                    let (new_mod, dir) =
                        parse_external_mod(sess, ident, span, dir, &mut attrs, pushed);

                    let krate = ast::Crate {
                        span: new_mod.inner,
                        module: new_mod,
                        attrs,
                        proc_macros: vec![],
                    };
                    if let Some(extern_mod_loaded) = self.cx.extern_mod_loaded {
                        extern_mod_loaded(&krate);
                    }

                    *old_mod = krate.module;
                    item.attrs = krate.attrs;
                    // File can have inline attributes, e.g., `#![cfg(...)]` & co. => Reconfigure.
                    item = match self.configure(item) {
                        Some(node) => node,
                        None => {
                            if *pushed {
                                sess.included_mod_stack.borrow_mut().pop();
                            }
                            return Default::default();
                        }
                    };
                    dir
                };

                // Set the module info before we flat map.
                self.cx.current_expansion.directory_ownership = ownership;
                module.directory = path;
                module.mod_path.push(ident);
                let orig_module =
                    mem::replace(&mut self.cx.current_expansion.module, Rc::new(module));

                let result = noop_flat_map_item(item, self);

                // Restore the module info.
                self.cx.current_expansion.module = orig_module;
                self.cx.current_expansion.directory_ownership = orig_ownership;
                if *pushed {
                    sess.included_mod_stack.borrow_mut().pop();
                }
                result
            }
            _ => {
                item.attrs = attrs;
                noop_flat_map_item(item, self)
            }
        }
    }

    fn flat_map_trait_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
        let mut item = configure!(self, item);

        let (attr, traits, after_derive) = self.classify_item(&mut item);
        if attr.is_some() || !traits.is_empty() {
            return self
                .collect_attr(
                    attr,
                    traits,
                    Annotatable::TraitItem(item),
                    AstFragmentKind::TraitItems,
                    after_derive,
                )
                .make_trait_items();
        }

        match item.kind {
            ast::AssocItemKind::MacCall(..) => {
                self.check_attributes(&item.attrs);
                item.and_then(|item| match item.kind {
                    ast::AssocItemKind::MacCall(mac) => self
                        .collect_bang(mac, item.span, AstFragmentKind::TraitItems)
                        .make_trait_items(),
                    _ => unreachable!(),
                })
            }
            _ => noop_flat_map_assoc_item(item, self),
        }
    }

    fn flat_map_impl_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
        let mut item = configure!(self, item);

        let (attr, traits, after_derive) = self.classify_item(&mut item);
        if attr.is_some() || !traits.is_empty() {
            return self
                .collect_attr(
                    attr,
                    traits,
                    Annotatable::ImplItem(item),
                    AstFragmentKind::ImplItems,
                    after_derive,
                )
                .make_impl_items();
        }

        match item.kind {
            ast::AssocItemKind::MacCall(..) => {
                self.check_attributes(&item.attrs);
                item.and_then(|item| match item.kind {
                    ast::AssocItemKind::MacCall(mac) => self
                        .collect_bang(mac, item.span, AstFragmentKind::ImplItems)
                        .make_impl_items(),
                    _ => unreachable!(),
                })
            }
            _ => noop_flat_map_assoc_item(item, self),
        }
    }

    fn visit_ty(&mut self, ty: &mut P<ast::Ty>) {
        match ty.kind {
            ast::TyKind::MacCall(_) => {}
            _ => return noop_visit_ty(ty, self),
        };

        visit_clobber(ty, |mut ty| match mem::replace(&mut ty.kind, ast::TyKind::Err) {
            ast::TyKind::MacCall(mac) => {
                self.collect_bang(mac, ty.span, AstFragmentKind::Ty).make_ty()
            }
            _ => unreachable!(),
        });
    }

    fn visit_foreign_mod(&mut self, foreign_mod: &mut ast::ForeignMod) {
        self.cfg.configure_foreign_mod(foreign_mod);
        noop_visit_foreign_mod(foreign_mod, self);
    }

    fn flat_map_foreign_item(
        &mut self,
        mut foreign_item: P<ast::ForeignItem>,
    ) -> SmallVec<[P<ast::ForeignItem>; 1]> {
        let (attr, traits, after_derive) = self.classify_item(&mut foreign_item);

        if attr.is_some() || !traits.is_empty() {
            return self
                .collect_attr(
                    attr,
                    traits,
                    Annotatable::ForeignItem(foreign_item),
                    AstFragmentKind::ForeignItems,
                    after_derive,
                )
                .make_foreign_items();
        }

        match foreign_item.kind {
            ast::ForeignItemKind::MacCall(..) => {
                self.check_attributes(&foreign_item.attrs);
                foreign_item.and_then(|item| match item.kind {
                    ast::ForeignItemKind::MacCall(mac) => self
                        .collect_bang(mac, item.span, AstFragmentKind::ForeignItems)
                        .make_foreign_items(),
                    _ => unreachable!(),
                })
            }
            _ => noop_flat_map_foreign_item(foreign_item, self),
        }
    }

    fn visit_item_kind(&mut self, item: &mut ast::ItemKind) {
        match item {
            ast::ItemKind::MacroDef(..) => {}
            _ => {
                self.cfg.configure_item_kind(item);
                noop_visit_item_kind(item, self);
            }
        }
    }

    fn flat_map_generic_param(
        &mut self,
        param: ast::GenericParam,
    ) -> SmallVec<[ast::GenericParam; 1]> {
        let mut param = configure!(self, param);

        let (attr, traits, after_derive) = self.classify_item(&mut param);
        if attr.is_some() || !traits.is_empty() {
            return self
                .collect_attr(
                    attr,
                    traits,
                    Annotatable::GenericParam(param),
                    AstFragmentKind::GenericParams,
                    after_derive,
                )
                .make_generic_params();
        }

        noop_flat_map_generic_param(param, self)
    }

    fn visit_attribute(&mut self, at: &mut ast::Attribute) {
        // turn `#[doc(include="filename")]` attributes into `#[doc(include(file="filename",
        // contents="file contents")]` attributes
        if !at.check_name(sym::doc) {
            return noop_visit_attribute(at, self);
        }

        if let Some(list) = at.meta_item_list() {
            if !list.iter().any(|it| it.check_name(sym::include)) {
                return noop_visit_attribute(at, self);
            }

            let mut items = vec![];

            for mut it in list {
                if !it.check_name(sym::include) {
                    items.push({
                        noop_visit_meta_list_item(&mut it, self);
                        it
                    });
                    continue;
                }

                if let Some(file) = it.value_str() {
                    let err_count = self.cx.parse_sess.span_diagnostic.err_count();
                    self.check_attributes(slice::from_ref(at));
                    if self.cx.parse_sess.span_diagnostic.err_count() > err_count {
                        // avoid loading the file if they haven't enabled the feature
                        return noop_visit_attribute(at, self);
                    }

                    let filename = match self.cx.resolve_path(&*file.as_str(), it.span()) {
                        Ok(filename) => filename,
                        Err(mut err) => {
                            err.emit();
                            continue;
                        }
                    };

                    match self.cx.source_map().load_file(&filename) {
                        Ok(source_file) => {
                            let src = source_file
                                .src
                                .as_ref()
                                .expect("freshly loaded file should have a source");
                            let src_interned = Symbol::intern(src.as_str());

                            let include_info = vec![
                                ast::NestedMetaItem::MetaItem(attr::mk_name_value_item_str(
                                    Ident::with_dummy_span(sym::file),
                                    file,
                                    DUMMY_SP,
                                )),
                                ast::NestedMetaItem::MetaItem(attr::mk_name_value_item_str(
                                    Ident::with_dummy_span(sym::contents),
                                    src_interned,
                                    DUMMY_SP,
                                )),
                            ];

                            let include_ident = Ident::with_dummy_span(sym::include);
                            let item = attr::mk_list_item(include_ident, include_info);
                            items.push(ast::NestedMetaItem::MetaItem(item));
                        }
                        Err(e) => {
                            let lit =
                                it.meta_item().and_then(|item| item.name_value_literal()).unwrap();

                            if e.kind() == ErrorKind::InvalidData {
                                self.cx
                                    .struct_span_err(
                                        lit.span,
                                        &format!("{} wasn't a utf-8 file", filename.display()),
                                    )
                                    .span_label(lit.span, "contains invalid utf-8")
                                    .emit();
                            } else {
                                let mut err = self.cx.struct_span_err(
                                    lit.span,
                                    &format!("couldn't read {}: {}", filename.display(), e),
                                );
                                err.span_label(lit.span, "couldn't read file");

                                err.emit();
                            }
                        }
                    }
                } else {
                    let mut err = self
                        .cx
                        .struct_span_err(it.span(), "expected path to external documentation");

                    // Check if the user erroneously used `doc(include(...))` syntax.
                    let literal = it.meta_item_list().and_then(|list| {
                        if list.len() == 1 {
                            list[0].literal().map(|literal| &literal.kind)
                        } else {
                            None
                        }
                    });

                    let (path, applicability) = match &literal {
                        Some(LitKind::Str(path, ..)) => {
                            (path.to_string(), Applicability::MachineApplicable)
                        }
                        _ => (String::from("<path>"), Applicability::HasPlaceholders),
                    };

                    err.span_suggestion(
                        it.span(),
                        "provide a file path with `=`",
                        format!("include = \"{}\"", path),
                        applicability,
                    );

                    err.emit();
                }
            }

            let meta = attr::mk_list_item(Ident::with_dummy_span(sym::doc), items);
            *at = ast::Attribute {
                kind: ast::AttrKind::Normal(AttrItem {
                    path: meta.path,
                    args: meta.kind.mac_args(meta.span),
                }),
                span: at.span,
                id: at.id,
                style: at.style,
            };
        } else {
            noop_visit_attribute(at, self)
        }
    }

    fn visit_id(&mut self, id: &mut ast::NodeId) {
        if self.monotonic {
            debug_assert_eq!(*id, ast::DUMMY_NODE_ID);
            *id = self.cx.resolver.next_node_id()
        }
    }

    fn visit_fn_decl(&mut self, mut fn_decl: &mut P<ast::FnDecl>) {
        self.cfg.configure_fn_decl(&mut fn_decl);
        noop_visit_fn_decl(fn_decl, self);
    }
}

pub struct ExpansionConfig<'feat> {
    pub crate_name: String,
    pub features: Option<&'feat Features>,
    pub recursion_limit: Limit,
    pub trace_mac: bool,
    pub should_test: bool, // If false, strip `#[test]` nodes
    pub keep_macs: bool,
    pub span_debug: bool, // If true, use verbose debugging for `proc_macro::Span`
}

impl<'feat> ExpansionConfig<'feat> {
    pub fn default(crate_name: String) -> ExpansionConfig<'static> {
        ExpansionConfig {
            crate_name,
            features: None,
            recursion_limit: Limit::new(1024),
            trace_mac: false,
            should_test: false,
            keep_macs: false,
            span_debug: false,
        }
    }

    fn proc_macro_hygiene(&self) -> bool {
        self.features.map_or(false, |features| features.proc_macro_hygiene)
    }
    fn custom_inner_attributes(&self) -> bool {
        self.features.map_or(false, |features| features.custom_inner_attributes)
    }
}
