use clippy_utils::diagnostics::span_lint;
use rustc_ast::ast::{Crate, ItemKind, ModKind};
use rustc_lint::{EarlyContext, EarlyLintPass};
use rustc_session::declare_lint_pass;

declare_clippy_lint! {
    /// ### What it does
    /// Checks that [`clippy_utils::paths`] is sorted lexically
    ///
    /// ### Why is this bad?
    /// We like to pretend we're an example of tidy code.
    ///
    /// ### Example
    /// Wrong ordering of the util::paths constants.
    pub UNSORTED_CLIPPY_UTILS_PATHS,
    internal,
    "various things that will negatively affect your clippy experience"
}

declare_lint_pass!(UnsortedClippyUtilsPaths => [UNSORTED_CLIPPY_UTILS_PATHS]);

impl EarlyLintPass for UnsortedClippyUtilsPaths {
    fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &Crate) {
        if let Some(utils) = krate.items.iter().find(|item| item.ident.name.as_str() == "utils") {
            if let ItemKind::Mod(_, ModKind::Loaded(ref items, ..)) = utils.kind {
                if let Some(paths) = items.iter().find(|item| item.ident.name.as_str() == "paths") {
                    if let ItemKind::Mod(_, ModKind::Loaded(ref items, ..)) = paths.kind {
                        let mut last_name: Option<&str> = None;
                        for item in items {
                            let name = item.ident.as_str();
                            if let Some(last_name) = last_name {
                                if *last_name > *name {
                                    span_lint(
                                        cx,
                                        UNSORTED_CLIPPY_UTILS_PATHS,
                                        item.span,
                                        "this constant should be before the previous constant due to lexical \
                                         ordering",
                                    );
                                }
                            }
                            last_name = Some(name);
                        }
                    }
                }
            }
        }
    }
}
