use rustc_hir::def::DefKind;
use rustc_hir::{Expr, ExprKind};
use rustc_middle::ty;
use rustc_middle::ty::adjustment::Adjust;
use rustc_session::{declare_lint, declare_lint_pass};
use rustc_span::sym;

use crate::context::LintContext;
use crate::lints::{
    NoopMethodCallDiag, SuspiciousDoubleRefCloneDiag, SuspiciousDoubleRefDerefDiag,
};
use crate::{LateContext, LateLintPass};

declare_lint! {
    /// The `noop_method_call` lint detects specific calls to noop methods
    /// such as a calling `<&T as Clone>::clone` where `T: !Clone`.
    ///
    /// ### Example
    ///
    /// ```rust
    /// # #![allow(unused)]
    /// struct Foo;
    /// let foo = &Foo;
    /// let clone: &Foo = foo.clone();
    /// ```
    ///
    /// {{produces}}
    ///
    /// ### Explanation
    ///
    /// Some method calls are noops meaning that they do nothing. Usually such methods
    /// are the result of blanket implementations that happen to create some method invocations
    /// that end up not doing anything. For instance, `Clone` is implemented on all `&T`, but
    /// calling `clone` on a `&T` where `T` does not implement clone, actually doesn't do anything
    /// as references are copy. This lint detects these calls and warns the user about them.
    pub NOOP_METHOD_CALL,
    Warn,
    "detects the use of well-known noop methods"
}

declare_lint! {
    /// The `suspicious_double_ref_op` lint checks for usage of `.clone()`/`.borrow()`/`.deref()`
    /// on an `&&T` when `T: !Deref/Borrow/Clone`, which means the call will return the inner `&T`,
    /// instead of performing the operation on the underlying `T` and can be confusing.
    ///
    /// ### Example
    ///
    /// ```rust
    /// # #![allow(unused)]
    /// struct Foo;
    /// let foo = &&Foo;
    /// let clone: &Foo = foo.clone();
    /// ```
    ///
    /// {{produces}}
    ///
    /// ### Explanation
    ///
    /// Since `Foo` doesn't implement `Clone`, running `.clone()` only dereferences the double
    /// reference, instead of cloning the inner type which should be what was intended.
    pub SUSPICIOUS_DOUBLE_REF_OP,
    Warn,
    "suspicious call of trait method on `&&T`"
}

declare_lint_pass!(NoopMethodCall => [NOOP_METHOD_CALL, SUSPICIOUS_DOUBLE_REF_OP]);

impl<'tcx> LateLintPass<'tcx> for NoopMethodCall {
    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
        // We only care about method calls.
        let ExprKind::MethodCall(call, receiver, _, call_span) = &expr.kind else {
            return;
        };

        if call_span.from_expansion() {
            return;
        }

        // We only care about method calls corresponding to the `Clone`, `Deref` and `Borrow`
        // traits and ignore any other method call.

        let Some((DefKind::AssocFn, did)) = cx.typeck_results().type_dependent_def(expr.hir_id)
        else {
            return;
        };

        let Some(trait_id) = cx.tcx.trait_of_assoc(did) else { return };

        let Some(trait_) = cx.tcx.get_diagnostic_name(trait_id) else { return };

        if !matches!(trait_, sym::Borrow | sym::Clone | sym::Deref) {
            return;
        };

        let args = cx
            .tcx
            .normalize_erasing_regions(cx.typing_env(), cx.typeck_results().node_args(expr.hir_id));
        // Resolve the trait method instance.
        let Ok(Some(i)) = ty::Instance::try_resolve(cx.tcx, cx.typing_env(), did, args) else {
            return;
        };
        // (Re)check that it implements the noop diagnostic.
        let Some(name) = cx.tcx.get_diagnostic_name(i.def_id()) else { return };
        if !matches!(
            name,
            sym::noop_method_borrow | sym::noop_method_clone | sym::noop_method_deref
        ) {
            return;
        }

        let receiver_ty = cx.typeck_results().expr_ty(receiver);
        let expr_ty = cx.typeck_results().expr_ty_adjusted(expr);
        let arg_adjustments = cx.typeck_results().expr_adjustments(receiver);

        // If there is any user defined auto-deref step, then we don't want to warn.
        // https://github.com/rust-lang/rust-clippy/issues/9272
        if arg_adjustments.iter().any(|adj| matches!(adj.kind, Adjust::Deref(Some(_)))) {
            return;
        }

        let expr_span = expr.span;
        let span = expr_span.with_lo(receiver.span.hi());

        let orig_ty = expr_ty.peel_refs();

        if receiver_ty == expr_ty {
            let suggest_derive = match orig_ty.kind() {
                ty::Adt(def, _) => Some(cx.tcx.def_span(def.did()).shrink_to_lo()),
                _ => None,
            };
            cx.emit_span_lint(
                NOOP_METHOD_CALL,
                span,
                NoopMethodCallDiag {
                    method: call.ident,
                    orig_ty,
                    trait_,
                    label: span,
                    suggest_derive,
                },
            );
        } else {
            match name {
                // If `type_of(x) == T` and `x.borrow()` is used to get `&T`,
                // then that should be allowed
                sym::noop_method_borrow => return,
                sym::noop_method_clone => cx.emit_span_lint(
                    SUSPICIOUS_DOUBLE_REF_OP,
                    span,
                    SuspiciousDoubleRefCloneDiag { ty: expr_ty },
                ),
                sym::noop_method_deref => cx.emit_span_lint(
                    SUSPICIOUS_DOUBLE_REF_OP,
                    span,
                    SuspiciousDoubleRefDerefDiag { ty: expr_ty },
                ),
                _ => return,
            }
        }
    }
}
