//! This module contains paths to types and functions Clippy needs to know
//! about.
//!
//! Whenever possible, please consider diagnostic items over hardcoded paths.
//! See <https://github.com/rust-lang/rust-clippy/issues/5393> for more information.

use crate::res::MaybeQPath;
use crate::sym;
use rustc_ast::Mutability;
use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def::Namespace::{MacroNS, TypeNS, ValueNS};
use rustc_hir::def::{DefKind, Namespace, Res};
use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};
use rustc_hir::{ItemKind, Node, UseKind};
use rustc_lint::LateContext;
use rustc_middle::ty::fast_reject::SimplifiedType;
use rustc_middle::ty::layout::HasTyCtxt;
use rustc_middle::ty::{FloatTy, IntTy, Ty, TyCtxt, UintTy};
use rustc_span::{Ident, STDLIB_STABLE_CRATES, Symbol};
use std::sync::OnceLock;

/// Specifies whether to resolve a path in the [`TypeNS`], [`ValueNS`], [`MacroNS`] or in an
/// arbitrary namespace
#[derive(Clone, Copy, PartialEq, Debug)]
pub enum PathNS {
    Type,
    Value,
    Macro,
    Field,

    /// Resolves to the name in the first available namespace, e.g. for `std::vec` this would return
    /// either the macro or the module but **not** both
    ///
    /// Must only be used when the specific resolution is unimportant such as in
    /// `missing_enforced_import_renames`
    Arbitrary,
}

impl PathNS {
    fn matches(self, ns: Option<Namespace>) -> bool {
        let required = match self {
            PathNS::Type => TypeNS,
            PathNS::Value => ValueNS,
            PathNS::Macro => MacroNS,
            PathNS::Field => return false,
            PathNS::Arbitrary => return true,
        };

        ns == Some(required)
    }
}

/// Lazily resolves a path into a list of [`DefId`]s using [`lookup_path`].
///
/// Typically it will contain one [`DefId`] or none, but in some situations there can be multiple:
/// - `memchr::memchr` could return the functions from both memchr 1.0 and memchr 2.0
/// - `alloc::boxed::Box::downcast` would return a function for each of the different inherent impls
///   ([1], [2], [3])
///
/// [1]: https://doc.rust-lang.org/std/boxed/struct.Box.html#method.downcast
/// [2]: https://doc.rust-lang.org/std/boxed/struct.Box.html#method.downcast-1
/// [3]: https://doc.rust-lang.org/std/boxed/struct.Box.html#method.downcast-2
pub struct PathLookup {
    ns: PathNS,
    path: &'static [Symbol],
    once: OnceLock<Vec<DefId>>,
}

impl PathLookup {
    /// Only exported for tests and `clippy_lints_internal`
    #[doc(hidden)]
    pub const fn new(ns: PathNS, path: &'static [Symbol]) -> Self {
        Self {
            ns,
            path,
            once: OnceLock::new(),
        }
    }

    /// Returns the list of [`DefId`]s that the path resolves to
    pub fn get<'tcx>(&self, tcx: &impl HasTyCtxt<'tcx>) -> &[DefId] {
        self.once.get_or_init(|| lookup_path(tcx.tcx(), self.ns, self.path))
    }

    /// Returns the single [`DefId`] that the path resolves to, this can only be used for paths into
    /// stdlib crates to avoid the issue of multiple [`DefId`]s being returned
    ///
    /// May return [`None`] in `no_std`/`no_core` environments
    pub fn only(&self, cx: &LateContext<'_>) -> Option<DefId> {
        let ids = self.get(cx);
        debug_assert!(STDLIB_STABLE_CRATES.contains(&self.path[0]));
        debug_assert!(ids.len() <= 1, "{ids:?}");
        ids.first().copied()
    }

    /// Checks if the path resolves to the given `def_id`
    pub fn matches<'tcx>(&self, tcx: &impl HasTyCtxt<'tcx>, def_id: DefId) -> bool {
        self.get(&tcx.tcx()).contains(&def_id)
    }

    /// Resolves `maybe_path` to a [`DefId`] and checks if the [`PathLookup`] matches it
    pub fn matches_path<'tcx>(&self, cx: &LateContext<'_>, maybe_path: impl MaybeQPath<'tcx>) -> bool {
        maybe_path
            .res(cx)
            .opt_def_id()
            .is_some_and(|def_id| self.matches(cx, def_id))
    }

    /// Checks if the path resolves to `ty`'s definition, must be an `Adt`
    pub fn matches_ty<'tcx>(&self, tcx: &impl HasTyCtxt<'tcx>, ty: Ty<'_>) -> bool {
        ty.ty_adt_def().is_some_and(|adt| self.matches(&tcx.tcx(), adt.did()))
    }
}

macro_rules! path_macros {
    ($($name:ident: $ns:expr,)*) => {
        $(
            /// Only exported for tests and `clippy_lints_internal`
            #[doc(hidden)]
            #[macro_export]
            macro_rules! $name {
                ($$($$seg:ident $$(::)?)*) => {
                    PathLookup::new($ns, &[$$(sym::$$seg,)*])
                };
            }
        )*
    };
}

path_macros! {
    type_path: PathNS::Type,
    value_path: PathNS::Value,
    macro_path: PathNS::Macro,
}

// Paths in the standard library missing a diagnostic item

// Paths in external crates
pub static FUTURES_IO_ASYNCREADEXT: PathLookup = type_path!(futures_util::AsyncReadExt);
pub static FUTURES_IO_ASYNCWRITEEXT: PathLookup = type_path!(futures_util::AsyncWriteExt);
pub static ITERTOOLS_NEXT_TUPLE: PathLookup = value_path!(itertools::Itertools::next_tuple);
pub static PARKING_LOT_GUARDS: [PathLookup; 3] = [
    type_path!(lock_api::mutex::MutexGuard),
    type_path!(lock_api::rwlock::RwLockReadGuard),
    type_path!(lock_api::rwlock::RwLockWriteGuard),
];
pub static REGEX_BUILDER_NEW: PathLookup = value_path!(regex::RegexBuilder::new);
pub static REGEX_BYTES_BUILDER_NEW: PathLookup = value_path!(regex::bytes::RegexBuilder::new);
pub static REGEX_BYTES_NEW: PathLookup = value_path!(regex::bytes::Regex::new);
pub static REGEX_BYTES_SET_NEW: PathLookup = value_path!(regex::bytes::RegexSet::new);
pub static REGEX_NEW: PathLookup = value_path!(regex::Regex::new);
pub static REGEX_SET_NEW: PathLookup = value_path!(regex::RegexSet::new);
pub static SERDE_DESERIALIZE: PathLookup = type_path!(serde::de::Deserialize);
pub static SERDE_DE_VISITOR: PathLookup = type_path!(serde::de::Visitor);
pub static TOKIO_FILE_OPTIONS: PathLookup = value_path!(tokio::fs::File::options);
pub static TOKIO_IO_ASYNCREADEXT: PathLookup = type_path!(tokio::io::AsyncReadExt);
pub static TOKIO_IO_ASYNCWRITEEXT: PathLookup = type_path!(tokio::io::AsyncWriteExt);
pub static TOKIO_IO_OPEN_OPTIONS: PathLookup = type_path!(tokio::fs::OpenOptions);
pub static TOKIO_IO_OPEN_OPTIONS_NEW: PathLookup = value_path!(tokio::fs::OpenOptions::new);
pub static LAZY_STATIC: PathLookup = macro_path!(lazy_static::lazy_static);
pub static ONCE_CELL_SYNC_LAZY: PathLookup = type_path!(once_cell::sync::Lazy);
pub static ONCE_CELL_SYNC_LAZY_NEW: PathLookup = value_path!(once_cell::sync::Lazy::new);

// Paths for internal lints go in `clippy_lints_internal/src/internal_paths.rs`

/// Equivalent to a [`lookup_path`] after splitting the input string on `::`
///
/// This function is expensive and should be used sparingly.
pub fn lookup_path_str(tcx: TyCtxt<'_>, ns: PathNS, path: &str) -> Vec<DefId> {
    let path: Vec<Symbol> = path.split("::").map(Symbol::intern).collect();
    lookup_path(tcx, ns, &path)
}

/// Resolves a def path like `std::vec::Vec`.
///
/// Typically it will return one [`DefId`] or none, but in some situations there can be multiple:
/// - `memchr::memchr` could return the functions from both memchr 1.0 and memchr 2.0
/// - `alloc::boxed::Box::downcast` would return a function for each of the different inherent impls
///   ([1], [2], [3])
///
/// This function is expensive and should be used sparingly.
///
/// [1]: https://doc.rust-lang.org/std/boxed/struct.Box.html#method.downcast
/// [2]: https://doc.rust-lang.org/std/boxed/struct.Box.html#method.downcast-1
/// [3]: https://doc.rust-lang.org/std/boxed/struct.Box.html#method.downcast-2
pub fn lookup_path(tcx: TyCtxt<'_>, ns: PathNS, path: &[Symbol]) -> Vec<DefId> {
    let (root, rest) = match *path {
        [] | [_] => return Vec::new(),
        [root, ref rest @ ..] => (root, rest),
    };

    let mut out = Vec::new();
    for &base in find_crates(tcx, root).iter().chain(find_primitive_impls(tcx, root)) {
        lookup_with_base(tcx, base, ns, rest, &mut out);
    }
    out
}

/// Finds the crates called `name`, may be multiple due to multiple major versions.
pub fn find_crates(tcx: TyCtxt<'_>, name: Symbol) -> &'static [DefId] {
    static BY_NAME: OnceLock<FxHashMap<Symbol, Vec<DefId>>> = OnceLock::new();
    let map = BY_NAME.get_or_init(|| {
        let mut map = FxHashMap::default();
        map.insert(tcx.crate_name(LOCAL_CRATE), vec![LOCAL_CRATE.as_def_id()]);
        for &num in tcx.crates(()) {
            map.entry(tcx.crate_name(num)).or_default().push(num.as_def_id());
        }
        map
    });
    match map.get(&name) {
        Some(def_ids) => def_ids,
        None => &[],
    }
}

fn find_primitive_impls(tcx: TyCtxt<'_>, name: Symbol) -> &[DefId] {
    let ty = match name {
        sym::bool => SimplifiedType::Bool,
        sym::char => SimplifiedType::Char,
        sym::str => SimplifiedType::Str,
        sym::array => SimplifiedType::Array,
        sym::slice => SimplifiedType::Slice,
        // FIXME: rustdoc documents these two using just `pointer`.
        //
        // Maybe this is something we should do here too.
        sym::const_ptr => SimplifiedType::Ptr(Mutability::Not),
        sym::mut_ptr => SimplifiedType::Ptr(Mutability::Mut),
        sym::isize => SimplifiedType::Int(IntTy::Isize),
        sym::i8 => SimplifiedType::Int(IntTy::I8),
        sym::i16 => SimplifiedType::Int(IntTy::I16),
        sym::i32 => SimplifiedType::Int(IntTy::I32),
        sym::i64 => SimplifiedType::Int(IntTy::I64),
        sym::i128 => SimplifiedType::Int(IntTy::I128),
        sym::usize => SimplifiedType::Uint(UintTy::Usize),
        sym::u8 => SimplifiedType::Uint(UintTy::U8),
        sym::u16 => SimplifiedType::Uint(UintTy::U16),
        sym::u32 => SimplifiedType::Uint(UintTy::U32),
        sym::u64 => SimplifiedType::Uint(UintTy::U64),
        sym::u128 => SimplifiedType::Uint(UintTy::U128),
        sym::f32 => SimplifiedType::Float(FloatTy::F32),
        sym::f64 => SimplifiedType::Float(FloatTy::F64),
        _ => return &[],
    };

    tcx.incoherent_impls(ty)
}

/// Resolves a def path like `vec::Vec` with the base `std`.
fn lookup_with_base(tcx: TyCtxt<'_>, mut base: DefId, ns: PathNS, mut path: &[Symbol], out: &mut Vec<DefId>) {
    loop {
        match *path {
            [segment] => {
                out.extend(item_child_by_name(tcx, base, ns, segment));

                // When the current def_id is e.g. `struct S`, check the impl items in
                // `impl S { ... }`
                let inherent_impl_children = tcx
                    .inherent_impls(base)
                    .iter()
                    .filter_map(|&impl_def_id| item_child_by_name(tcx, impl_def_id, ns, segment));
                out.extend(inherent_impl_children);

                return;
            },
            [segment, ref rest @ ..] => {
                path = rest;
                let Some(child) = item_child_by_name(tcx, base, PathNS::Type, segment) else {
                    return;
                };
                base = child;
            },
            [] => unreachable!(),
        }
    }
}

fn item_child_by_name(tcx: TyCtxt<'_>, def_id: DefId, ns: PathNS, name: Symbol) -> Option<DefId> {
    if let Some(local_id) = def_id.as_local() {
        local_item_child_by_name(tcx, local_id, ns, name)
    } else {
        non_local_item_child_by_name(tcx, def_id, ns, name)
    }
}

fn local_item_child_by_name(tcx: TyCtxt<'_>, local_id: LocalDefId, ns: PathNS, name: Symbol) -> Option<DefId> {
    let root_mod;
    let item_kind = match tcx.hir_node_by_def_id(local_id) {
        Node::Crate(r#mod) => {
            root_mod = ItemKind::Mod(Ident::dummy(), r#mod);
            &root_mod
        },
        Node::Item(item) => &item.kind,
        Node::Variant(variant) if ns == PathNS::Field => {
            return if let rustc_hir::VariantData::Struct { fields, .. } = variant.data
                && let Some(field_def_id) = fields.iter().find_map(|field| {
                    if field.ident.name == name {
                        Some(field.def_id.to_def_id())
                    } else {
                        None
                    }
                }) {
                Some(field_def_id)
            } else {
                None
            };
        },
        _ => return None,
    };

    match item_kind {
        ItemKind::Mod(_, r#mod) => r#mod.item_ids.iter().find_map(|&item_id| {
            let item = tcx.hir_item(item_id);
            if let ItemKind::Use(path, UseKind::Single(ident)) = item.kind {
                if ident.name == name {
                    let opt_def_id = |ns: Option<Res>| ns.and_then(|res| res.opt_def_id());
                    match ns {
                        PathNS::Type => opt_def_id(path.res.type_ns),
                        PathNS::Value => opt_def_id(path.res.value_ns),
                        PathNS::Macro => opt_def_id(path.res.macro_ns),
                        PathNS::Field => None,
                        PathNS::Arbitrary => unreachable!(),
                    }
                } else {
                    None
                }
            } else if let Some(ident) = item.kind.ident()
                && ident.name == name
                && ns.matches(tcx.def_kind(item.owner_id).ns())
            {
                Some(item.owner_id.to_def_id())
            } else {
                None
            }
        }),
        ItemKind::Impl(..) | ItemKind::Trait { .. } => tcx
            .associated_items(local_id)
            .filter_by_name_unhygienic(name)
            .find(|assoc_item| ns.matches(Some(assoc_item.namespace())))
            .map(|assoc_item| assoc_item.def_id),
        ItemKind::Struct(_, _, rustc_hir::VariantData::Struct { fields, .. }) if ns == PathNS::Field => {
            fields.iter().find_map(|field| {
                if field.ident.name == name {
                    Some(field.def_id.to_def_id())
                } else {
                    None
                }
            })
        },
        ItemKind::Enum(_, _, rustc_hir::EnumDef { variants }) if ns == PathNS::Type => {
            variants.iter().find_map(|variant| {
                if variant.ident.name == name {
                    Some(variant.def_id.to_def_id())
                } else {
                    None
                }
            })
        },
        _ => None,
    }
}

fn non_local_item_child_by_name(tcx: TyCtxt<'_>, def_id: DefId, ns: PathNS, name: Symbol) -> Option<DefId> {
    match tcx.def_kind(def_id) {
        DefKind::Mod | DefKind::Enum | DefKind::Trait => tcx.module_children(def_id).iter().find_map(|child| {
            if child.ident.name == name && ns.matches(child.res.ns()) {
                child.res.opt_def_id()
            } else {
                None
            }
        }),
        DefKind::Impl { .. } => tcx
            .associated_item_def_ids(def_id)
            .iter()
            .copied()
            .find(|&assoc_def_id| tcx.item_name(assoc_def_id) == name && ns.matches(tcx.def_kind(assoc_def_id).ns())),
        DefKind::Struct => tcx
            .associated_item_def_ids(def_id)
            .iter()
            .copied()
            .find(|&assoc_def_id| tcx.item_name(assoc_def_id) == name),
        _ => None,
    }
}
