//! Debugging code to test fingerprints computed for query results.
//! For each node marked with `#[rustc_clean]` or `#[rustc_dirty]`,
//! we will compare the fingerprint from the current and from the previous
//! compilation session as appropriate:
//!
//! - `#[rustc_clean(cfg="rev2", except="typeck_tables_of")]` if we are
//!   in `#[cfg(rev2)]`, then the fingerprints associated with
//!   `DepNode::typeck_tables_of(X)` must be DIFFERENT (`X` is the `DefId` of the
//!   current node).
//! - `#[rustc_clean(cfg="rev2")]` same as above, except that the
//!   fingerprints must be the SAME (along with all other fingerprints).
//!
//! Errors are reported if we are in the suitable configuration but
//! the required condition is not met.

use rustc_ast::ast::{self, Attribute, NestedMetaItem};
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::FxHashSet;
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit;
use rustc_hir::itemlikevisit::ItemLikeVisitor;
use rustc_hir::Node as HirNode;
use rustc_hir::{ImplItemKind, ItemKind as HirItem, TraitItemKind};
use rustc_middle::dep_graph::{label_strs, DepNode, DepNodeExt};
use rustc_middle::hir::map::Map;
use rustc_middle::ty::TyCtxt;
use rustc_span::symbol::{sym, Symbol};
use rustc_span::Span;
use std::iter::FromIterator;
use std::vec::Vec;

const EXCEPT: Symbol = sym::except;
const LABEL: Symbol = sym::label;
const CFG: Symbol = sym::cfg;

// Base and Extra labels to build up the labels

/// For typedef, constants, and statics
const BASE_CONST: &[&str] = &[label_strs::type_of];

/// DepNodes for functions + methods
const BASE_FN: &[&str] = &[
    // Callers will depend on the signature of these items, so we better test
    label_strs::fn_sig,
    label_strs::generics_of,
    label_strs::predicates_of,
    label_strs::type_of,
    // And a big part of compilation (that we eventually want to cache) is type inference
    // information:
    label_strs::typeck_tables_of,
];

/// DepNodes for Hir, which is pretty much everything
const BASE_HIR: &[&str] = &[
    // hir_owner and hir_owner_nodes should be computed for all nodes
    label_strs::hir_owner,
    label_strs::hir_owner_nodes,
];

/// `impl` implementation of struct/trait
const BASE_IMPL: &[&str] =
    &[label_strs::associated_item_def_ids, label_strs::generics_of, label_strs::impl_trait_ref];

/// DepNodes for mir_built/Optimized, which is relevant in "executable"
/// code, i.e., functions+methods
const BASE_MIR: &[&str] =
    &[label_strs::optimized_mir, label_strs::promoted_mir, label_strs::mir_built];

/// Struct, Enum and Union DepNodes
///
/// Note that changing the type of a field does not change the type of the struct or enum, but
/// adding/removing fields or changing a fields name or visibility does.
const BASE_STRUCT: &[&str] =
    &[label_strs::generics_of, label_strs::predicates_of, label_strs::type_of];

/// Trait definition `DepNode`s.
const BASE_TRAIT_DEF: &[&str] = &[
    label_strs::associated_item_def_ids,
    label_strs::generics_of,
    label_strs::object_safety_violations,
    label_strs::predicates_of,
    label_strs::specialization_graph_of,
    label_strs::trait_def,
    label_strs::trait_impls_of,
];

/// Extra `DepNode`s for functions and methods.
const EXTRA_ASSOCIATED: &[&str] = &[label_strs::associated_item];

const EXTRA_TRAIT: &[&str] = &[label_strs::trait_of_item];

// Fully Built Labels

const LABELS_CONST: &[&[&str]] = &[BASE_HIR, BASE_CONST];

/// Constant/Typedef in an impl
const LABELS_CONST_IN_IMPL: &[&[&str]] = &[BASE_HIR, BASE_CONST, EXTRA_ASSOCIATED];

/// Trait-Const/Typedef DepNodes
const LABELS_CONST_IN_TRAIT: &[&[&str]] = &[BASE_HIR, BASE_CONST, EXTRA_ASSOCIATED, EXTRA_TRAIT];

/// Function `DepNode`s.
const LABELS_FN: &[&[&str]] = &[BASE_HIR, BASE_MIR, BASE_FN];

/// Method `DepNode`s.
const LABELS_FN_IN_IMPL: &[&[&str]] = &[BASE_HIR, BASE_MIR, BASE_FN, EXTRA_ASSOCIATED];

/// Trait method `DepNode`s.
const LABELS_FN_IN_TRAIT: &[&[&str]] =
    &[BASE_HIR, BASE_MIR, BASE_FN, EXTRA_ASSOCIATED, EXTRA_TRAIT];

/// For generic cases like inline-assembly, modules, etc.
const LABELS_HIR_ONLY: &[&[&str]] = &[BASE_HIR];

/// Impl `DepNode`s.
const LABELS_IMPL: &[&[&str]] = &[BASE_HIR, BASE_IMPL];

/// Abstract data type (struct, enum, union) `DepNode`s.
const LABELS_ADT: &[&[&str]] = &[BASE_HIR, BASE_STRUCT];

/// Trait definition `DepNode`s.
#[allow(dead_code)]
const LABELS_TRAIT: &[&[&str]] = &[BASE_HIR, BASE_TRAIT_DEF];

// FIXME: Struct/Enum/Unions Fields (there is currently no way to attach these)
//
// Fields are kind of separate from their containers, as they can change independently from
// them. We should at least check
//
//     type_of for these.

type Labels = FxHashSet<String>;

/// Represents the requested configuration by rustc_clean/dirty
struct Assertion {
    clean: Labels,
    dirty: Labels,
}

impl Assertion {
    fn from_clean_labels(labels: Labels) -> Assertion {
        Assertion { clean: labels, dirty: Labels::default() }
    }

    fn from_dirty_labels(labels: Labels) -> Assertion {
        Assertion { clean: Labels::default(), dirty: labels }
    }
}

pub fn check_dirty_clean_annotations(tcx: TyCtxt<'_>) {
    // can't add `#[rustc_dirty]` etc without opting in to this feature
    if !tcx.features().rustc_attrs {
        return;
    }

    tcx.dep_graph.with_ignore(|| {
        let krate = tcx.hir().krate();
        let mut dirty_clean_visitor = DirtyCleanVisitor { tcx, checked_attrs: Default::default() };
        krate.visit_all_item_likes(&mut dirty_clean_visitor);

        let mut all_attrs = FindAllAttrs {
            tcx,
            attr_names: vec![sym::rustc_dirty, sym::rustc_clean],
            found_attrs: vec![],
        };
        intravisit::walk_crate(&mut all_attrs, krate);

        // Note that we cannot use the existing "unused attribute"-infrastructure
        // here, since that is running before codegen. This is also the reason why
        // all codegen-specific attributes are `Whitelisted` in rustc_ast::feature_gate.
        all_attrs.report_unchecked_attrs(&dirty_clean_visitor.checked_attrs);
    })
}

pub struct DirtyCleanVisitor<'tcx> {
    tcx: TyCtxt<'tcx>,
    checked_attrs: FxHashSet<ast::AttrId>,
}

impl DirtyCleanVisitor<'tcx> {
    /// Possibly "deserialize" the attribute into a clean/dirty assertion
    fn assertion_maybe(&mut self, item_id: hir::HirId, attr: &Attribute) -> Option<Assertion> {
        let is_clean = if attr.check_name(sym::rustc_dirty) {
            false
        } else if attr.check_name(sym::rustc_clean) {
            true
        } else {
            // skip: not rustc_clean/dirty
            return None;
        };
        if !check_config(self.tcx, attr) {
            // skip: not the correct `cfg=`
            return None;
        }
        let assertion = if let Some(labels) = self.labels(attr) {
            if is_clean {
                Assertion::from_clean_labels(labels)
            } else {
                Assertion::from_dirty_labels(labels)
            }
        } else {
            self.assertion_auto(item_id, attr, is_clean)
        };
        Some(assertion)
    }

    /// Gets the "auto" assertion on pre-validated attr, along with the `except` labels.
    fn assertion_auto(
        &mut self,
        item_id: hir::HirId,
        attr: &Attribute,
        is_clean: bool,
    ) -> Assertion {
        let (name, mut auto) = self.auto_labels(item_id, attr);
        let except = self.except(attr);
        for e in except.iter() {
            if !auto.remove(e) {
                let msg = format!(
                    "`except` specified DepNodes that can not be affected for \"{}\": \"{}\"",
                    name, e
                );
                self.tcx.sess.span_fatal(attr.span, &msg);
            }
        }
        if is_clean {
            Assertion { clean: auto, dirty: except }
        } else {
            Assertion { clean: except, dirty: auto }
        }
    }

    fn labels(&self, attr: &Attribute) -> Option<Labels> {
        for item in attr.meta_item_list().unwrap_or_else(Vec::new) {
            if item.check_name(LABEL) {
                let value = expect_associated_value(self.tcx, &item);
                return Some(self.resolve_labels(&item, &value.as_str()));
            }
        }
        None
    }

    /// `except=` attribute value
    fn except(&self, attr: &Attribute) -> Labels {
        for item in attr.meta_item_list().unwrap_or_else(Vec::new) {
            if item.check_name(EXCEPT) {
                let value = expect_associated_value(self.tcx, &item);
                return self.resolve_labels(&item, &value.as_str());
            }
        }
        // if no `label` or `except` is given, only the node's group are asserted
        Labels::default()
    }

    /// Return all DepNode labels that should be asserted for this item.
    /// index=0 is the "name" used for error messages
    fn auto_labels(&mut self, item_id: hir::HirId, attr: &Attribute) -> (&'static str, Labels) {
        let node = self.tcx.hir().get(item_id);
        let (name, labels) = match node {
            HirNode::Item(item) => {
                match item.kind {
                    // note: these are in the same order as hir::Item_;
                    // FIXME(michaelwoerister): do commented out ones

                    // // An `extern crate` item, with optional original crate name,
                    // HirItem::ExternCrate(..),  // intentionally no assertions

                    // // `use foo::bar::*;` or `use foo::bar::baz as quux;`
                    // HirItem::Use(..),  // intentionally no assertions

                    // A `static` item
                    HirItem::Static(..) => ("ItemStatic", LABELS_CONST),

                    // A `const` item
                    HirItem::Const(..) => ("ItemConst", LABELS_CONST),

                    // A function declaration
                    HirItem::Fn(..) => ("ItemFn", LABELS_FN),

                    // // A module
                    HirItem::Mod(..) => ("ItemMod", LABELS_HIR_ONLY),

                    // // An external module
                    HirItem::ForeignMod(..) => ("ItemForeignMod", LABELS_HIR_ONLY),

                    // Module-level inline assembly (from global_asm!)
                    HirItem::GlobalAsm(..) => ("ItemGlobalAsm", LABELS_HIR_ONLY),

                    // A type alias, e.g., `type Foo = Bar<u8>`
                    HirItem::TyAlias(..) => ("ItemTy", LABELS_HIR_ONLY),

                    // An enum definition, e.g., `enum Foo<A, B> {C<A>, D<B>}`
                    HirItem::Enum(..) => ("ItemEnum", LABELS_ADT),

                    // A struct definition, e.g., `struct Foo<A> {x: A}`
                    HirItem::Struct(..) => ("ItemStruct", LABELS_ADT),

                    // A union definition, e.g., `union Foo<A, B> {x: A, y: B}`
                    HirItem::Union(..) => ("ItemUnion", LABELS_ADT),

                    // Represents a Trait Declaration
                    // FIXME(michaelwoerister): trait declaration is buggy because sometimes some of
                    // the depnodes don't exist (because they legitametely didn't need to be
                    // calculated)
                    //
                    // michaelwoerister and vitiral came up with a possible solution,
                    // to just do this before every query
                    // ```
                    // ::rustc_middle::ty::query::plumbing::force_from_dep_node(tcx, dep_node)
                    // ```
                    //
                    // However, this did not seem to work effectively and more bugs were hit.
                    // Nebie @vitiral gave up :)
                    //
                    //HirItem::Trait(..) => ("ItemTrait", LABELS_TRAIT),

                    // An implementation, eg `impl<A> Trait for Foo { .. }`
                    HirItem::Impl { .. } => ("ItemKind::Impl", LABELS_IMPL),

                    _ => self.tcx.sess.span_fatal(
                        attr.span,
                        &format!(
                            "clean/dirty auto-assertions not yet defined \
                             for Node::Item.node={:?}",
                            item.kind
                        ),
                    ),
                }
            }
            HirNode::TraitItem(item) => match item.kind {
                TraitItemKind::Fn(..) => ("Node::TraitItem", LABELS_FN_IN_TRAIT),
                TraitItemKind::Const(..) => ("NodeTraitConst", LABELS_CONST_IN_TRAIT),
                TraitItemKind::Type(..) => ("NodeTraitType", LABELS_CONST_IN_TRAIT),
            },
            HirNode::ImplItem(item) => match item.kind {
                ImplItemKind::Fn(..) => ("Node::ImplItem", LABELS_FN_IN_IMPL),
                ImplItemKind::Const(..) => ("NodeImplConst", LABELS_CONST_IN_IMPL),
                ImplItemKind::TyAlias(..) => ("NodeImplType", LABELS_CONST_IN_IMPL),
            },
            _ => self.tcx.sess.span_fatal(
                attr.span,
                &format!("clean/dirty auto-assertions not yet defined for {:?}", node),
            ),
        };
        let labels =
            Labels::from_iter(labels.iter().flat_map(|s| s.iter().map(|l| (*l).to_string())));
        (name, labels)
    }

    fn resolve_labels(&self, item: &NestedMetaItem, value: &str) -> Labels {
        let mut out = Labels::default();
        for label in value.split(',') {
            let label = label.trim();
            if DepNode::has_label_string(label) {
                if out.contains(label) {
                    self.tcx.sess.span_fatal(
                        item.span(),
                        &format!("dep-node label `{}` is repeated", label),
                    );
                }
                out.insert(label.to_string());
            } else {
                self.tcx
                    .sess
                    .span_fatal(item.span(), &format!("dep-node label `{}` not recognized", label));
            }
        }
        out
    }

    fn dep_nodes<'l>(
        &self,
        labels: &'l Labels,
        def_id: DefId,
    ) -> impl Iterator<Item = DepNode> + 'l {
        let def_path_hash = self.tcx.def_path_hash(def_id);
        labels.iter().map(move |label| match DepNode::from_label_string(label, def_path_hash) {
            Ok(dep_node) => dep_node,
            Err(()) => unreachable!(),
        })
    }

    fn dep_node_str(&self, dep_node: &DepNode) -> String {
        if let Some(def_id) = dep_node.extract_def_id(self.tcx) {
            format!("{:?}({})", dep_node.kind, self.tcx.def_path_str(def_id))
        } else {
            format!("{:?}({:?})", dep_node.kind, dep_node.hash)
        }
    }

    fn assert_dirty(&self, item_span: Span, dep_node: DepNode) {
        debug!("assert_dirty({:?})", dep_node);

        let current_fingerprint = self.get_fingerprint(&dep_node);
        let prev_fingerprint = self.tcx.dep_graph.prev_fingerprint_of(&dep_node);

        if current_fingerprint == prev_fingerprint {
            let dep_node_str = self.dep_node_str(&dep_node);
            self.tcx
                .sess
                .span_err(item_span, &format!("`{}` should be dirty but is not", dep_node_str));
        }
    }

    fn get_fingerprint(&self, dep_node: &DepNode) -> Option<Fingerprint> {
        if self.tcx.dep_graph.dep_node_exists(dep_node) {
            let dep_node_index = self.tcx.dep_graph.dep_node_index_of(dep_node);
            Some(self.tcx.dep_graph.fingerprint_of(dep_node_index))
        } else {
            None
        }
    }

    fn assert_clean(&self, item_span: Span, dep_node: DepNode) {
        debug!("assert_clean({:?})", dep_node);

        let current_fingerprint = self.get_fingerprint(&dep_node);
        let prev_fingerprint = self.tcx.dep_graph.prev_fingerprint_of(&dep_node);

        // if the node wasn't previously evaluated and now is (or vice versa),
        // then the node isn't actually clean or dirty.
        if (current_fingerprint == None) ^ (prev_fingerprint == None) {
            return;
        }

        if current_fingerprint != prev_fingerprint {
            let dep_node_str = self.dep_node_str(&dep_node);
            self.tcx
                .sess
                .span_err(item_span, &format!("`{}` should be clean but is not", dep_node_str));
        }
    }

    fn check_item(&mut self, item_id: hir::HirId, item_span: Span) {
        let def_id = self.tcx.hir().local_def_id(item_id);
        for attr in self.tcx.get_attrs(def_id.to_def_id()).iter() {
            let assertion = match self.assertion_maybe(item_id, attr) {
                Some(a) => a,
                None => continue,
            };
            self.checked_attrs.insert(attr.id);
            for dep_node in self.dep_nodes(&assertion.clean, def_id.to_def_id()) {
                self.assert_clean(item_span, dep_node);
            }
            for dep_node in self.dep_nodes(&assertion.dirty, def_id.to_def_id()) {
                self.assert_dirty(item_span, dep_node);
            }
        }
    }
}

impl ItemLikeVisitor<'tcx> for DirtyCleanVisitor<'tcx> {
    fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
        self.check_item(item.hir_id, item.span);
    }

    fn visit_trait_item(&mut self, item: &hir::TraitItem<'_>) {
        self.check_item(item.hir_id, item.span);
    }

    fn visit_impl_item(&mut self, item: &hir::ImplItem<'_>) {
        self.check_item(item.hir_id, item.span);
    }
}

/// Given a `#[rustc_dirty]` or `#[rustc_clean]` attribute, scan
/// for a `cfg="foo"` attribute and check whether we have a cfg
/// flag called `foo`.
///
/// Also make sure that the `label` and `except` fields do not
/// both exist.
fn check_config(tcx: TyCtxt<'_>, attr: &Attribute) -> bool {
    debug!("check_config(attr={:?})", attr);
    let config = &tcx.sess.parse_sess.config;
    debug!("check_config: config={:?}", config);
    let (mut cfg, mut except, mut label) = (None, false, false);
    for item in attr.meta_item_list().unwrap_or_else(Vec::new) {
        if item.check_name(CFG) {
            let value = expect_associated_value(tcx, &item);
            debug!("check_config: searching for cfg {:?}", value);
            cfg = Some(config.contains(&(value, None)));
        }
        if item.check_name(LABEL) {
            label = true;
        }
        if item.check_name(EXCEPT) {
            except = true;
        }
    }

    if label && except {
        tcx.sess.span_fatal(attr.span, "must specify only one of: `label`, `except`");
    }

    match cfg {
        None => tcx.sess.span_fatal(attr.span, "no cfg attribute"),
        Some(c) => c,
    }
}

fn expect_associated_value(tcx: TyCtxt<'_>, item: &NestedMetaItem) -> Symbol {
    if let Some(value) = item.value_str() {
        value
    } else {
        let msg = if let Some(ident) = item.ident() {
            format!("associated value expected for `{}`", ident)
        } else {
            "expected an associated value".to_string()
        };

        tcx.sess.span_fatal(item.span(), &msg);
    }
}

// A visitor that collects all #[rustc_dirty]/#[rustc_clean] attributes from
// the HIR. It is used to verfiy that we really ran checks for all annotated
// nodes.
pub struct FindAllAttrs<'tcx> {
    tcx: TyCtxt<'tcx>,
    attr_names: Vec<Symbol>,
    found_attrs: Vec<&'tcx Attribute>,
}

impl FindAllAttrs<'tcx> {
    fn is_active_attr(&mut self, attr: &Attribute) -> bool {
        for attr_name in &self.attr_names {
            if attr.check_name(*attr_name) && check_config(self.tcx, attr) {
                return true;
            }
        }

        false
    }

    fn report_unchecked_attrs(&self, checked_attrs: &FxHashSet<ast::AttrId>) {
        for attr in &self.found_attrs {
            if !checked_attrs.contains(&attr.id) {
                self.tcx.sess.span_err(
                    attr.span,
                    "found unchecked `#[rustc_dirty]` / `#[rustc_clean]` attribute",
                );
            }
        }
    }
}

impl intravisit::Visitor<'tcx> for FindAllAttrs<'tcx> {
    type Map = Map<'tcx>;

    fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
        intravisit::NestedVisitorMap::All(self.tcx.hir())
    }

    fn visit_attribute(&mut self, attr: &'tcx Attribute) {
        if self.is_active_attr(attr) {
            self.found_attrs.push(attr);
        }
    }
}
