//! Conditional compilation stripping.

use std::iter;

use rustc_ast::token::{Delimiter, Token, TokenKind};
use rustc_ast::tokenstream::{
    AttrTokenStream, AttrTokenTree, LazyAttrTokenStream, Spacing, TokenTree,
};
use rustc_ast::{
    self as ast, AttrKind, AttrStyle, Attribute, HasAttrs, HasTokens, MetaItem, MetaItemInner,
    NodeId, NormalAttr,
};
use rustc_attr_parsing as attr;
use rustc_attr_parsing::{
    AttributeParser, CFG_TEMPLATE, EvalConfigResult, ShouldEmit, eval_config_entry, parse_cfg_attr,
};
use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
use rustc_feature::{
    ACCEPTED_LANG_FEATURES, AttributeSafety, EnabledLangFeature, EnabledLibFeature, Features,
    REMOVED_LANG_FEATURES, UNSTABLE_LANG_FEATURES,
};
use rustc_lint_defs::BuiltinLintDiag;
use rustc_parse::validate_attr;
use rustc_parse::validate_attr::deny_builtin_meta_unsafety;
use rustc_session::Session;
use rustc_session::parse::feature_err;
use rustc_span::{STDLIB_STABLE_CRATES, Span, Symbol, sym};
use thin_vec::ThinVec;
use tracing::instrument;

use crate::errors::{
    CrateNameInCfgAttr, CrateTypeInCfgAttr, FeatureNotAllowed, FeatureRemoved,
    FeatureRemovedReason, InvalidCfg, MalformedFeatureAttribute, MalformedFeatureAttributeHelp,
    RemoveExprNotSupported,
};

/// A folder that strips out items that do not belong in the current configuration.
pub struct StripUnconfigured<'a> {
    pub sess: &'a Session,
    pub features: Option<&'a Features>,
    /// If `true`, perform cfg-stripping on attached tokens.
    /// This is only used for the input to derive macros,
    /// which needs eager expansion of `cfg` and `cfg_attr`
    pub config_tokens: bool,
    pub lint_node_id: NodeId,
}

pub fn features(sess: &Session, krate_attrs: &[Attribute], crate_name: Symbol) -> Features {
    fn feature_list(attr: &Attribute) -> ThinVec<ast::MetaItemInner> {
        if attr.has_name(sym::feature)
            && let Some(list) = attr.meta_item_list()
        {
            list
        } else {
            ThinVec::new()
        }
    }

    let mut features = Features::default();

    // Process all features enabled in the code.
    for attr in krate_attrs {
        for mi in feature_list(attr) {
            let name = match mi.ident() {
                Some(ident) if mi.is_word() => ident.name,
                Some(ident) => {
                    sess.dcx().emit_err(MalformedFeatureAttribute {
                        span: mi.span(),
                        help: MalformedFeatureAttributeHelp::Suggestion {
                            span: mi.span(),
                            suggestion: ident.name,
                        },
                    });
                    continue;
                }
                None => {
                    sess.dcx().emit_err(MalformedFeatureAttribute {
                        span: mi.span(),
                        help: MalformedFeatureAttributeHelp::Label { span: mi.span() },
                    });
                    continue;
                }
            };

            // If the enabled feature has been removed, issue an error.
            if let Some(f) = REMOVED_LANG_FEATURES.iter().find(|f| name == f.feature.name) {
                let pull_note = if let Some(pull) = f.pull {
                    format!(
                        "; see <https://github.com/rust-lang/rust/pull/{}> for more information",
                        pull
                    )
                } else {
                    "".to_owned()
                };
                sess.dcx().emit_err(FeatureRemoved {
                    span: mi.span(),
                    reason: f.reason.map(|reason| FeatureRemovedReason { reason }),
                    removed_rustc_version: f.feature.since,
                    pull_note,
                });
                continue;
            }

            // If the enabled feature is stable, record it.
            if let Some(f) = ACCEPTED_LANG_FEATURES.iter().find(|f| name == f.name) {
                features.set_enabled_lang_feature(EnabledLangFeature {
                    gate_name: name,
                    attr_sp: mi.span(),
                    stable_since: Some(Symbol::intern(f.since)),
                });
                continue;
            }

            // If `-Z allow-features` is used and the enabled feature is
            // unstable and not also listed as one of the allowed features,
            // issue an error.
            if let Some(allowed) = sess.opts.unstable_opts.allow_features.as_ref() {
                if allowed.iter().all(|f| name.as_str() != f) {
                    sess.dcx().emit_err(FeatureNotAllowed { span: mi.span(), name });
                    continue;
                }
            }

            // If the enabled feature is unstable, record it.
            if UNSTABLE_LANG_FEATURES.iter().find(|f| name == f.name).is_some() {
                // When the ICE comes a standard library crate, there's a chance that the person
                // hitting the ICE may be using -Zbuild-std or similar with an untested target.
                // The bug is probably in the standard library and not the compiler in that case,
                // but that doesn't really matter - we want a bug report.
                if features.internal(name) && !STDLIB_STABLE_CRATES.contains(&crate_name) {
                    sess.using_internal_features.store(true, std::sync::atomic::Ordering::Relaxed);
                }

                features.set_enabled_lang_feature(EnabledLangFeature {
                    gate_name: name,
                    attr_sp: mi.span(),
                    stable_since: None,
                });
                continue;
            }

            // Otherwise, the feature is unknown. Enable it as a lib feature.
            // It will be checked later whether the feature really exists.
            features
                .set_enabled_lib_feature(EnabledLibFeature { gate_name: name, attr_sp: mi.span() });

            // Similar to above, detect internal lib features to suppress
            // the ICE message that asks for a report.
            if features.internal(name) && !STDLIB_STABLE_CRATES.contains(&crate_name) {
                sess.using_internal_features.store(true, std::sync::atomic::Ordering::Relaxed);
            }
        }
    }

    features
}

pub fn pre_configure_attrs(sess: &Session, attrs: &[Attribute]) -> ast::AttrVec {
    let strip_unconfigured = StripUnconfigured {
        sess,
        features: None,
        config_tokens: false,
        lint_node_id: ast::CRATE_NODE_ID,
    };
    attrs
        .iter()
        .flat_map(|attr| strip_unconfigured.process_cfg_attr(attr))
        .take_while(|attr| {
            !is_cfg(attr)
                || strip_unconfigured
                    .cfg_true(attr, strip_unconfigured.lint_node_id, ShouldEmit::Nothing)
                    .as_bool()
        })
        .collect()
}

pub(crate) fn attr_into_trace(mut attr: Attribute, trace_name: Symbol) -> Attribute {
    match &mut attr.kind {
        AttrKind::Normal(normal) => {
            let NormalAttr { item, tokens } = &mut **normal;
            item.path.segments[0].ident.name = trace_name;
            // This makes the trace attributes unobservable to token-based proc macros.
            *tokens = Some(LazyAttrTokenStream::new_direct(AttrTokenStream::default()));
        }
        AttrKind::DocComment(..) => unreachable!(),
    }
    attr
}

#[macro_export]
macro_rules! configure {
    ($this:ident, $node:ident) => {
        match $this.configure($node) {
            Some(node) => node,
            None => return Default::default(),
        }
    };
}

impl<'a> StripUnconfigured<'a> {
    pub fn configure<T: HasAttrs + HasTokens>(&self, mut node: T) -> Option<T> {
        self.process_cfg_attrs(&mut node);
        self.in_cfg(node.attrs()).then(|| {
            self.try_configure_tokens(&mut node);
            node
        })
    }

    fn try_configure_tokens<T: HasTokens>(&self, node: &mut T) {
        if self.config_tokens {
            if let Some(Some(tokens)) = node.tokens_mut() {
                let attr_stream = tokens.to_attr_token_stream();
                *tokens = LazyAttrTokenStream::new_direct(self.configure_tokens(&attr_stream));
            }
        }
    }

    /// Performs cfg-expansion on `stream`, producing a new `AttrTokenStream`.
    /// This is only used during the invocation of `derive` proc-macros,
    /// which require that we cfg-expand their entire input.
    /// Normal cfg-expansion operates on parsed AST nodes via the `configure` method
    fn configure_tokens(&self, stream: &AttrTokenStream) -> AttrTokenStream {
        fn can_skip(stream: &AttrTokenStream) -> bool {
            stream.0.iter().all(|tree| match tree {
                AttrTokenTree::AttrsTarget(_) => false,
                AttrTokenTree::Token(..) => true,
                AttrTokenTree::Delimited(.., inner) => can_skip(inner),
            })
        }

        if can_skip(stream) {
            return stream.clone();
        }

        let trees: Vec<_> = stream
            .0
            .iter()
            .filter_map(|tree| match tree.clone() {
                AttrTokenTree::AttrsTarget(mut target) => {
                    // Expand any `cfg_attr` attributes.
                    target.attrs.flat_map_in_place(|attr| self.process_cfg_attr(&attr));

                    if self.in_cfg(&target.attrs) {
                        target.tokens = LazyAttrTokenStream::new_direct(
                            self.configure_tokens(&target.tokens.to_attr_token_stream()),
                        );
                        Some(AttrTokenTree::AttrsTarget(target))
                    } else {
                        // Remove the target if there's a `cfg` attribute and
                        // the condition isn't satisfied.
                        None
                    }
                }
                AttrTokenTree::Delimited(sp, spacing, delim, mut inner) => {
                    inner = self.configure_tokens(&inner);
                    Some(AttrTokenTree::Delimited(sp, spacing, delim, inner))
                }
                AttrTokenTree::Token(Token { kind, .. }, _) if kind.is_delim() => {
                    panic!("Should be `AttrTokenTree::Delimited`, not delim tokens: {:?}", tree);
                }
                AttrTokenTree::Token(token, spacing) => Some(AttrTokenTree::Token(token, spacing)),
            })
            .collect();
        AttrTokenStream::new(trees)
    }

    /// Parse and expand all `cfg_attr` attributes into a list of attributes
    /// that are within each `cfg_attr` that has a true configuration predicate.
    ///
    /// Gives compiler warnings if any `cfg_attr` does not contain any
    /// attributes and is in the original source code. Gives compiler errors if
    /// the syntax of any `cfg_attr` is incorrect.
    fn process_cfg_attrs<T: HasAttrs>(&self, node: &mut T) {
        node.visit_attrs(|attrs| {
            attrs.flat_map_in_place(|attr| self.process_cfg_attr(&attr));
        });
    }

    fn process_cfg_attr(&self, attr: &Attribute) -> Vec<Attribute> {
        if attr.has_name(sym::cfg_attr) {
            self.expand_cfg_attr(attr, true)
        } else {
            vec![attr.clone()]
        }
    }

    /// Parse and expand a single `cfg_attr` attribute into a list of attributes
    /// when the configuration predicate is true, or otherwise expand into an
    /// empty list of attributes.
    ///
    /// Gives a compiler warning when the `cfg_attr` contains no attributes and
    /// is in the original source file. Gives a compiler error if the syntax of
    /// the attribute is incorrect.
    pub(crate) fn expand_cfg_attr(&self, cfg_attr: &Attribute, recursive: bool) -> Vec<Attribute> {
        validate_attr::check_attribute_safety(
            &self.sess.psess,
            Some(AttributeSafety::Normal),
            &cfg_attr,
            ast::CRATE_NODE_ID,
        );

        // A trace attribute left in AST in place of the original `cfg_attr` attribute.
        // It can later be used by lints or other diagnostics.
        let trace_attr = attr_into_trace(cfg_attr.clone(), sym::cfg_attr_trace);

        let Some((cfg_predicate, expanded_attrs)) =
            rustc_parse::parse_cfg_attr(cfg_attr, &self.sess.psess)
        else {
            return vec![trace_attr];
        };

        // Lint on zero attributes in source.
        if expanded_attrs.is_empty() {
            self.sess.psess.buffer_lint(
                rustc_lint_defs::builtin::UNUSED_ATTRIBUTES,
                cfg_attr.span,
                ast::CRATE_NODE_ID,
                BuiltinLintDiag::CfgAttrNoAttributes,
            );
        }

        if !attr::cfg_matches(&cfg_predicate, &self.sess, self.lint_node_id, self.features) {
            return vec![trace_attr];
        }

        if recursive {
            // We call `process_cfg_attr` recursively in case there's a
            // `cfg_attr` inside of another `cfg_attr`. E.g.
            //  `#[cfg_attr(false, cfg_attr(true, some_attr))]`.
            let expanded_attrs = expanded_attrs
                .into_iter()
                .flat_map(|item| self.process_cfg_attr(&self.expand_cfg_attr_item(cfg_attr, item)));
            iter::once(trace_attr).chain(expanded_attrs).collect()
        } else {
            let expanded_attrs =
                expanded_attrs.into_iter().map(|item| self.expand_cfg_attr_item(cfg_attr, item));
            iter::once(trace_attr).chain(expanded_attrs).collect()
        }
    }

    fn expand_cfg_attr_item(
        &self,
        cfg_attr: &Attribute,
        (item, item_span): (ast::AttrItem, Span),
    ) -> Attribute {
        // Convert `#[cfg_attr(pred, attr)]` to `#[attr]`.

        // Use the `#` from `#[cfg_attr(pred, attr)]` in the result `#[attr]`.
        let mut orig_trees = cfg_attr.token_trees().into_iter();
        let Some(TokenTree::Token(pound_token @ Token { kind: TokenKind::Pound, .. }, _)) =
            orig_trees.next()
        else {
            panic!("Bad tokens for attribute {cfg_attr:?}");
        };

        // For inner attributes, we do the same thing for the `!` in `#![attr]`.
        let mut trees = if cfg_attr.style == AttrStyle::Inner {
            let Some(TokenTree::Token(bang_token @ Token { kind: TokenKind::Bang, .. }, _)) =
                orig_trees.next()
            else {
                panic!("Bad tokens for attribute {cfg_attr:?}");
            };
            vec![
                AttrTokenTree::Token(pound_token, Spacing::Joint),
                AttrTokenTree::Token(bang_token, Spacing::JointHidden),
            ]
        } else {
            vec![AttrTokenTree::Token(pound_token, Spacing::JointHidden)]
        };

        // And the same thing for the `[`/`]` delimiters in `#[attr]`.
        let Some(TokenTree::Delimited(delim_span, delim_spacing, Delimiter::Bracket, _)) =
            orig_trees.next()
        else {
            panic!("Bad tokens for attribute {cfg_attr:?}");
        };
        trees.push(AttrTokenTree::Delimited(
            delim_span,
            delim_spacing,
            Delimiter::Bracket,
            item.tokens
                .as_ref()
                .unwrap_or_else(|| panic!("Missing tokens for {item:?}"))
                .to_attr_token_stream(),
        ));

        let tokens = Some(LazyAttrTokenStream::new_direct(AttrTokenStream::new(trees)));
        let attr = ast::attr::mk_attr_from_item(
            &self.sess.psess.attr_id_generator,
            item,
            tokens,
            cfg_attr.style,
            item_span,
        );
        if attr.has_name(sym::crate_type) {
            self.sess.dcx().emit_err(CrateTypeInCfgAttr { span: attr.span });
        }
        if attr.has_name(sym::crate_name) {
            self.sess.dcx().emit_err(CrateNameInCfgAttr { span: attr.span });
        }
        attr
    }

    /// Determines if a node with the given attributes should be included in this configuration.
    fn in_cfg(&self, attrs: &[Attribute]) -> bool {
        attrs.iter().all(|attr| {
            !is_cfg(attr)
                || self.cfg_true(attr, self.lint_node_id, ShouldEmit::ErrorsAndLints).as_bool()
        })
    }

    pub(crate) fn cfg_true(
        &self,
        attr: &Attribute,
        node: NodeId,
        emit_errors: ShouldEmit,
    ) -> EvalConfigResult {
        // We need to run this to do basic validation of the attribute, such as that lits are valid, etc
        // FIXME(jdonszelmann) this should not be necessary in the future
        match validate_attr::parse_meta(&self.sess.psess, attr) {
            Ok(_) => {}
            Err(err) => {
                err.emit();
                return EvalConfigResult::True;
            }
        }

        // Unsafety check needs to be done explicitly here because this attribute will be removed before the normal check
        deny_builtin_meta_unsafety(
            self.sess.dcx(),
            attr.get_normal_item().unsafety,
            &rustc_ast::Path::from_ident(attr.ident().unwrap()),
        );

        let Some(cfg) = AttributeParser::parse_single(
            self.sess,
            attr,
            attr.span,
            node,
            self.features,
            emit_errors,
            parse_cfg_attr,
            &CFG_TEMPLATE,
        ) else {
            // Cfg attribute was not parsable, give up
            return EvalConfigResult::True;
        };

        eval_config_entry(self.sess, &cfg, self.lint_node_id, self.features, emit_errors)
    }

    /// If attributes are not allowed on expressions, emit an error for `attr`
    #[instrument(level = "trace", skip(self))]
    pub(crate) fn maybe_emit_expr_attr_err(&self, attr: &Attribute) {
        if self.features.is_some_and(|features| !features.stmt_expr_attributes())
            && !attr.span.allows_unstable(sym::stmt_expr_attributes)
        {
            let mut err = feature_err(
                &self.sess,
                sym::stmt_expr_attributes,
                attr.span,
                crate::fluent_generated::expand_attributes_on_expressions_experimental,
            );

            if attr.is_doc_comment() {
                err.help(if attr.style == AttrStyle::Outer {
                    crate::fluent_generated::expand_help_outer_doc
                } else {
                    crate::fluent_generated::expand_help_inner_doc
                });
            }

            err.emit();
        }
    }

    #[instrument(level = "trace", skip(self))]
    pub fn configure_expr(&self, expr: &mut ast::Expr, method_receiver: bool) {
        if !method_receiver {
            for attr in expr.attrs.iter() {
                self.maybe_emit_expr_attr_err(attr);
            }
        }

        // If an expr is valid to cfg away it will have been removed by the
        // outer stmt or expression folder before descending in here.
        // Anything else is always required, and thus has to error out
        // in case of a cfg attr.
        //
        // N.B., this is intentionally not part of the visit_expr() function
        //     in order for filter_map_expr() to be able to avoid this check
        if let Some(attr) = expr.attrs().iter().find(|a| is_cfg(a)) {
            self.sess.dcx().emit_err(RemoveExprNotSupported { span: attr.span });
        }

        self.process_cfg_attrs(expr);
        self.try_configure_tokens(&mut *expr);
    }
}

/// FIXME: Still used by Rustdoc, should be removed after
pub fn parse_cfg<'a>(meta_item: &'a MetaItem, sess: &Session) -> Option<&'a MetaItemInner> {
    let span = meta_item.span;
    match meta_item.meta_item_list() {
        None => {
            sess.dcx().emit_err(InvalidCfg::NotFollowedByParens { span });
            None
        }
        Some([]) => {
            sess.dcx().emit_err(InvalidCfg::NoPredicate { span });
            None
        }
        Some([_, .., l]) => {
            sess.dcx().emit_err(InvalidCfg::MultiplePredicates { span: l.span() });
            None
        }
        Some([single]) => match single.meta_item_or_bool() {
            Some(meta_item) => Some(meta_item),
            None => {
                sess.dcx().emit_err(InvalidCfg::PredicateLiteral { span: single.span() });
                None
            }
        },
    }
}

fn is_cfg(attr: &Attribute) -> bool {
    attr.has_name(sym::cfg)
}
