//! Detecting lib features (i.e., features that are not lang features).
//!
//! These are declared using stability attributes (e.g., `#[stable (..)]` and `#[unstable (..)]`),
//! but are not declared in one single location (unlike lang features), which means we need to
//! collect them instead.

use rustc_hir::attrs::AttributeKind;
use rustc_hir::intravisit::Visitor;
use rustc_hir::{Attribute, StabilityLevel, StableSince};
use rustc_middle::hir::nested_filter;
use rustc_middle::middle::lib_features::{FeatureStability, LibFeatures};
use rustc_middle::query::{LocalCrate, Providers};
use rustc_middle::ty::TyCtxt;
use rustc_span::{Span, Symbol, sym};

use crate::errors::{FeaturePreviouslyDeclared, FeatureStableTwice};

struct LibFeatureCollector<'tcx> {
    tcx: TyCtxt<'tcx>,
    lib_features: LibFeatures,
}

impl<'tcx> LibFeatureCollector<'tcx> {
    fn new(tcx: TyCtxt<'tcx>) -> LibFeatureCollector<'tcx> {
        LibFeatureCollector { tcx, lib_features: LibFeatures::default() }
    }

    fn extract(&self, attr: &Attribute) -> Option<(Symbol, FeatureStability, Span)> {
        let (feature, level, span) = match attr {
            Attribute::Parsed(AttributeKind::Stability { stability, span }) => {
                (stability.feature, stability.level, *span)
            }
            Attribute::Parsed(AttributeKind::RustcConstStability { stability, span }) => {
                (stability.feature, stability.level, *span)
            }
            Attribute::Parsed(AttributeKind::RustcBodyStability { stability, span }) => {
                (stability.feature, stability.level, *span)
            }
            _ => return None,
        };

        let feature_stability = match level {
            StabilityLevel::Unstable { old_name, .. } => FeatureStability::Unstable { old_name },
            StabilityLevel::Stable { since, .. } => FeatureStability::AcceptedSince(match since {
                StableSince::Version(v) => Symbol::intern(&v.to_string()),
                StableSince::Current => sym::env_CFG_RELEASE,
                StableSince::Err(_) => return None,
            }),
        };

        Some((feature, feature_stability, span))
    }

    fn collect_feature(&mut self, feature: Symbol, stability: FeatureStability, span: Span) {
        let existing_stability = self.lib_features.stability.get(&feature).cloned();

        match (stability, existing_stability) {
            (_, None) => {
                self.lib_features.stability.insert(feature, (stability, span));
            }
            (
                FeatureStability::AcceptedSince(since),
                Some((FeatureStability::AcceptedSince(prev_since), _)),
            ) => {
                if prev_since != since {
                    self.tcx.dcx().emit_err(FeatureStableTwice {
                        span,
                        feature,
                        since,
                        prev_since,
                    });
                }
            }
            (FeatureStability::AcceptedSince(_), Some((FeatureStability::Unstable { .. }, _))) => {
                self.tcx.dcx().emit_err(FeaturePreviouslyDeclared {
                    span,
                    feature,
                    declared: "stable",
                    prev_declared: "unstable",
                });
            }
            (FeatureStability::Unstable { .. }, Some((FeatureStability::AcceptedSince(_), _))) => {
                self.tcx.dcx().emit_err(FeaturePreviouslyDeclared {
                    span,
                    feature,
                    declared: "unstable",
                    prev_declared: "stable",
                });
            }
            // duplicate `unstable` feature is ok.
            (FeatureStability::Unstable { .. }, Some((FeatureStability::Unstable { .. }, _))) => {}
        }
    }
}

impl<'tcx> Visitor<'tcx> for LibFeatureCollector<'tcx> {
    type NestedFilter = nested_filter::All;

    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
        self.tcx
    }

    fn visit_attribute(&mut self, attr: &'tcx Attribute) {
        if let Some((feature, stable, span)) = self.extract(attr) {
            self.collect_feature(feature, stable, span);
        }
    }
}

fn lib_features(tcx: TyCtxt<'_>, LocalCrate: LocalCrate) -> LibFeatures {
    // If `staged_api` is not enabled then we aren't allowed to define lib
    // features; there is no point collecting them.
    if !tcx.features().staged_api() {
        return LibFeatures::default();
    }

    let mut collector = LibFeatureCollector::new(tcx);
    tcx.hir_walk_attributes(&mut collector);
    collector.lib_features
}

pub(crate) fn provide(providers: &mut Providers) {
    providers.lib_features = lib_features;
}
