//! The current rustc diagnostics emitter.
//!
//! An `Emitter` takes care of generating the output from a `Diag` struct.
//!
//! There are various `Emitter` implementations that generate different output formats such as
//! JSON and human readable output.
//!
//! The output types are defined in `rustc_session::config::ErrorOutputType`.

use std::borrow::Cow;
use std::io::prelude::*;
use std::io::{self, IsTerminal};
use std::iter;
use std::path::Path;

use anstream::{AutoStream, ColorChoice};
use anstyle::{AnsiColor, Effects};
use rustc_data_structures::fx::FxIndexSet;
use rustc_data_structures::sync::DynSend;
use rustc_error_messages::DiagArgMap;
use rustc_span::hygiene::{ExpnKind, MacroKind};
use rustc_span::source_map::SourceMap;
use rustc_span::{FileName, SourceFile, Span};
use tracing::{debug, warn};

use crate::formatting::format_diag_message;
use crate::timings::TimingRecord;
use crate::{
    CodeSuggestion, DiagInner, DiagMessage, Level, MultiSpan, Style, Subdiag, SuggestionStyle,
};

/// Describes the way the content of the `rendered` field of the json output is generated
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct HumanReadableErrorType {
    pub short: bool,
    pub unicode: bool,
}

impl HumanReadableErrorType {
    pub fn short(&self) -> bool {
        self.short
    }
}

pub enum TimingEvent {
    Start,
    End,
}

pub type DynEmitter = dyn Emitter + DynSend;

/// Emitter trait for emitting errors and other structured information.
pub trait Emitter {
    /// Emit a structured diagnostic.
    fn emit_diagnostic(&mut self, diag: DiagInner);

    /// Emit a notification that an artifact has been output.
    /// Currently only supported for the JSON format.
    fn emit_artifact_notification(&mut self, _path: &Path, _artifact_type: &str) {}

    /// Emit a timestamp with start/end of a timing section.
    /// Currently only supported for the JSON format.
    fn emit_timing_section(&mut self, _record: TimingRecord, _event: TimingEvent) {}

    /// Emit a report about future breakage.
    /// Currently only supported for the JSON format.
    fn emit_future_breakage_report(&mut self, _diags: Vec<DiagInner>) {}

    /// Emit list of unused externs.
    /// Currently only supported for the JSON format.
    fn emit_unused_externs(
        &mut self,
        _lint_level: rustc_lint_defs::Level,
        _unused_externs: &[&str],
    ) {
    }

    /// Checks if should show explanations about "rustc --explain"
    fn should_show_explain(&self) -> bool {
        true
    }

    /// Checks if we can use colors in the current output stream.
    fn supports_color(&self) -> bool {
        false
    }

    fn source_map(&self) -> Option<&SourceMap>;

    /// Formats the substitutions of the primary_span
    ///
    /// There are a lot of conditions to this method, but in short:
    ///
    /// * If the current `DiagInner` has only one visible `CodeSuggestion`,
    ///   we format the `help` suggestion depending on the content of the
    ///   substitutions. In that case, we modify the span and clear the
    ///   suggestions.
    ///
    /// * If the current `DiagInner` has multiple suggestions,
    ///   we leave `primary_span` and the suggestions untouched.
    fn primary_span_formatted(
        &self,
        primary_span: &mut MultiSpan,
        suggestions: &mut Vec<CodeSuggestion>,
        fluent_args: &DiagArgMap,
    ) {
        if let Some((sugg, rest)) = suggestions.split_first() {
            let msg = format_diag_message(&sugg.msg, fluent_args);
            if rest.is_empty()
               // ^ if there is only one suggestion
               // don't display multi-suggestions as labels
               && let [substitution] = sugg.substitutions.as_slice()
               // don't display multipart suggestions as labels
               && let [part] = substitution.parts.as_slice()
               // don't display long messages as labels
               && msg.split_whitespace().count() < 10
               // don't display multiline suggestions as labels
               && !part.snippet.contains('\n')
               && ![
                    // when this style is set we want the suggestion to be a message, not inline
                    SuggestionStyle::HideCodeAlways,
                    // trivial suggestion for tooling's sake, never shown
                    SuggestionStyle::CompletelyHidden,
                    // subtle suggestion, never shown inline
                    SuggestionStyle::ShowAlways,
               ].contains(&sugg.style)
            {
                let snippet = part.snippet.trim();
                let msg = if snippet.is_empty() || sugg.style.hide_inline() {
                    // This substitution is only removal OR we explicitly don't want to show the
                    // code inline (`hide_inline`). Therefore, we don't show the substitution.
                    format!("help: {msg}")
                } else {
                    // Show the default suggestion text with the substitution
                    let confusion_type = self
                        .source_map()
                        .map(|sm| detect_confusion_type(sm, snippet, part.span))
                        .unwrap_or(ConfusionType::None);
                    format!("help: {}{}: `{}`", msg, confusion_type.label_text(), snippet,)
                };
                primary_span.push_span_label(part.span, msg);

                // We return only the modified primary_span
                suggestions.clear();
            } else {
                // if there are multiple suggestions, print them all in full
                // to be consistent. We could try to figure out if we can
                // make one (or the first one) inline, but that would give
                // undue importance to a semi-random suggestion
            }
        } else {
            // do nothing
        }
    }

    fn fix_multispans_in_extern_macros_and_render_macro_backtrace(
        &self,
        span: &mut MultiSpan,
        children: &mut Vec<Subdiag>,
        level: &Level,
        backtrace: bool,
    ) {
        // Check for spans in macros, before `fix_multispans_in_extern_macros`
        // has a chance to replace them.
        let has_macro_spans: Vec<_> = iter::once(&*span)
            .chain(children.iter().map(|child| &child.span))
            .flat_map(|span| span.primary_spans())
            .flat_map(|sp| sp.macro_backtrace())
            .filter_map(|expn_data| {
                match expn_data.kind {
                    ExpnKind::Root => None,

                    // Skip past non-macro entries, just in case there
                    // are some which do actually involve macros.
                    ExpnKind::Desugaring(..) | ExpnKind::AstPass(..) => None,

                    ExpnKind::Macro(macro_kind, name) => {
                        Some((macro_kind, name, expn_data.hide_backtrace))
                    }
                }
            })
            .collect();

        if !backtrace {
            self.fix_multispans_in_extern_macros(span, children);
        }

        self.render_multispans_macro_backtrace(span, children, backtrace);

        if !backtrace {
            // Skip builtin macros, as their expansion isn't relevant to the end user. This includes
            // actual intrinsics, like `asm!`.
            if let Some((macro_kind, name, _)) = has_macro_spans.first()
                && let Some((_, _, false)) = has_macro_spans.last()
            {
                // Mark the actual macro this originates from
                let and_then = if let Some((macro_kind, last_name, _)) = has_macro_spans.last()
                    && last_name != name
                {
                    let descr = macro_kind.descr();
                    format!(" which comes from the expansion of the {descr} `{last_name}`")
                } else {
                    "".to_string()
                };

                let descr = macro_kind.descr();
                let msg = format!(
                    "this {level} originates in the {descr} `{name}`{and_then} \
                    (in Nightly builds, run with -Z macro-backtrace for more info)",
                );

                children.push(Subdiag {
                    level: Level::Note,
                    messages: vec![(DiagMessage::from(msg), Style::NoStyle)],
                    span: MultiSpan::new(),
                });
            }
        }
    }

    fn render_multispans_macro_backtrace(
        &self,
        span: &mut MultiSpan,
        children: &mut Vec<Subdiag>,
        backtrace: bool,
    ) {
        for span in iter::once(span).chain(children.iter_mut().map(|child| &mut child.span)) {
            self.render_multispan_macro_backtrace(span, backtrace);
        }
    }

    fn render_multispan_macro_backtrace(&self, span: &mut MultiSpan, always_backtrace: bool) {
        let mut new_labels = FxIndexSet::default();

        for &sp in span.primary_spans() {
            if sp.is_dummy() {
                continue;
            }

            // FIXME(eddyb) use `retain` on `macro_backtrace` to remove all the
            // entries we don't want to print, to make sure the indices being
            // printed are contiguous (or omitted if there's only one entry).
            let macro_backtrace: Vec<_> = sp.macro_backtrace().collect();
            for (i, trace) in macro_backtrace.iter().rev().enumerate() {
                if trace.def_site.is_dummy() {
                    continue;
                }

                if always_backtrace {
                    new_labels.insert((
                        trace.def_site,
                        format!(
                            "in this expansion of `{}`{}",
                            trace.kind.descr(),
                            if macro_backtrace.len() > 1 {
                                // if macro_backtrace.len() == 1 it'll be
                                // pointed at by "in this macro invocation"
                                format!(" (#{})", i + 1)
                            } else {
                                String::new()
                            },
                        ),
                    ));
                }

                // Don't add a label on the call site if the diagnostic itself
                // already points to (a part of) that call site, as the label
                // is meant for showing the relevant invocation when the actual
                // diagnostic is pointing to some part of macro definition.
                //
                // This also handles the case where an external span got replaced
                // with the call site span by `fix_multispans_in_extern_macros`.
                //
                // NB: `-Zmacro-backtrace` overrides this, for uniformity, as the
                // "in this expansion of" label above is always added in that mode,
                // and it needs an "in this macro invocation" label to match that.
                let redundant_span = trace.call_site.contains(sp);

                if !redundant_span || always_backtrace {
                    let msg: Cow<'static, _> = match trace.kind {
                        ExpnKind::Macro(MacroKind::Attr, _) => {
                            "this attribute macro expansion".into()
                        }
                        ExpnKind::Macro(MacroKind::Derive, _) => {
                            "this derive macro expansion".into()
                        }
                        ExpnKind::Macro(MacroKind::Bang, _) => "this macro invocation".into(),
                        ExpnKind::Root => "the crate root".into(),
                        ExpnKind::AstPass(kind) => kind.descr().into(),
                        ExpnKind::Desugaring(kind) => {
                            format!("this {} desugaring", kind.descr()).into()
                        }
                    };
                    new_labels.insert((
                        trace.call_site,
                        format!(
                            "in {}{}",
                            msg,
                            if macro_backtrace.len() > 1 && always_backtrace {
                                // only specify order when the macro
                                // backtrace is multiple levels deep
                                format!(" (#{})", i + 1)
                            } else {
                                String::new()
                            },
                        ),
                    ));
                }
                if !always_backtrace {
                    break;
                }
            }
        }

        for (label_span, label_text) in new_labels {
            span.push_span_label(label_span, label_text);
        }
    }

    // This does a small "fix" for multispans by looking to see if it can find any that
    // point directly at external macros. Since these are often difficult to read,
    // this will change the span to point at the use site.
    fn fix_multispans_in_extern_macros(&self, span: &mut MultiSpan, children: &mut Vec<Subdiag>) {
        debug!("fix_multispans_in_extern_macros: before: span={:?} children={:?}", span, children);
        self.fix_multispan_in_extern_macros(span);
        for child in children.iter_mut() {
            self.fix_multispan_in_extern_macros(&mut child.span);
        }
        debug!("fix_multispans_in_extern_macros: after: span={:?} children={:?}", span, children);
    }

    // This "fixes" MultiSpans that contain `Span`s pointing to locations inside of external macros.
    // Since these locations are often difficult to read,
    // we move these spans from the external macros to their corresponding use site.
    fn fix_multispan_in_extern_macros(&self, span: &mut MultiSpan) {
        let Some(source_map) = self.source_map() else { return };
        // First, find all the spans in external macros and point instead at their use site.
        let replacements: Vec<(Span, Span)> = span
            .primary_spans()
            .iter()
            .copied()
            .chain(span.span_labels().iter().map(|sp_label| sp_label.span))
            .filter_map(|sp| {
                if !sp.is_dummy() && source_map.is_imported(sp) {
                    let mut span = sp;
                    while let Some(callsite) = span.parent_callsite() {
                        span = callsite;
                        if !source_map.is_imported(span) {
                            return Some((sp, span));
                        }
                    }
                }
                None
            })
            .collect();

        // After we have them, make sure we replace these 'bad' def sites with their use sites.
        for (from, to) in replacements {
            span.replace(from, to);
        }
    }
}

/// An emitter that adds a note to each diagnostic.
pub struct EmitterWithNote {
    pub emitter: Box<dyn Emitter + DynSend>,
    pub note: String,
}

impl Emitter for EmitterWithNote {
    fn source_map(&self) -> Option<&SourceMap> {
        None
    }

    fn emit_diagnostic(&mut self, mut diag: DiagInner) {
        diag.sub(Level::Note, self.note.clone(), MultiSpan::new());
        self.emitter.emit_diagnostic(diag);
    }
}

pub struct SilentEmitter;

impl Emitter for SilentEmitter {
    fn source_map(&self) -> Option<&SourceMap> {
        None
    }

    fn emit_diagnostic(&mut self, _diag: DiagInner) {}
}

/// Maximum number of suggestions to be shown
///
/// Arbitrary, but taken from trait import suggestion limit
pub const MAX_SUGGESTIONS: usize = 4;

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ColorConfig {
    Auto,
    Always,
    Never,
}

impl ColorConfig {
    pub fn to_color_choice(self) -> ColorChoice {
        match self {
            ColorConfig::Always => {
                if io::stderr().is_terminal() {
                    ColorChoice::Always
                } else {
                    ColorChoice::AlwaysAnsi
                }
            }
            ColorConfig::Never => ColorChoice::Never,
            ColorConfig::Auto if io::stderr().is_terminal() => ColorChoice::Auto,
            ColorConfig::Auto => ColorChoice::Never,
        }
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum OutputTheme {
    Ascii,
    Unicode,
}

// We replace some characters so the CLI output is always consistent and underlines aligned.
// Keep the following list in sync with `rustc_span::char_width`.
const OUTPUT_REPLACEMENTS: &[(char, &str)] = &[
    // In terminals without Unicode support the following will be garbled, but in *all* terminals
    // the underlying codepoint will be as well. We could gate this replacement behind a "unicode
    // support" gate.
    ('\0', "␀"),
    ('\u{0001}', "␁"),
    ('\u{0002}', "␂"),
    ('\u{0003}', "␃"),
    ('\u{0004}', "␄"),
    ('\u{0005}', "␅"),
    ('\u{0006}', "␆"),
    ('\u{0007}', "␇"),
    ('\u{0008}', "␈"),
    ('\t', "    "), // We do our own tab replacement
    ('\u{000b}', "␋"),
    ('\u{000c}', "␌"),
    ('\u{000d}', "␍"),
    ('\u{000e}', "␎"),
    ('\u{000f}', "␏"),
    ('\u{0010}', "␐"),
    ('\u{0011}', "␑"),
    ('\u{0012}', "␒"),
    ('\u{0013}', "␓"),
    ('\u{0014}', "␔"),
    ('\u{0015}', "␕"),
    ('\u{0016}', "␖"),
    ('\u{0017}', "␗"),
    ('\u{0018}', "␘"),
    ('\u{0019}', "␙"),
    ('\u{001a}', "␚"),
    ('\u{001b}', "␛"),
    ('\u{001c}', "␜"),
    ('\u{001d}', "␝"),
    ('\u{001e}', "␞"),
    ('\u{001f}', "␟"),
    ('\u{007f}', "␡"),
    ('\u{200d}', ""), // Replace ZWJ for consistent terminal output of grapheme clusters.
    ('\u{202a}', "�"), // The following unicode text flow control characters are inconsistently
    ('\u{202b}', "�"), // supported across CLIs and can cause confusion due to the bytes on disk
    ('\u{202c}', "�"), // not corresponding to the visible source code, so we replace them always.
    ('\u{202d}', "�"),
    ('\u{202e}', "�"),
    ('\u{2066}', "�"),
    ('\u{2067}', "�"),
    ('\u{2068}', "�"),
    ('\u{2069}', "�"),
];

pub(crate) fn normalize_whitespace(s: &str) -> String {
    const {
        let mut i = 1;
        while i < OUTPUT_REPLACEMENTS.len() {
            assert!(
                OUTPUT_REPLACEMENTS[i - 1].0 < OUTPUT_REPLACEMENTS[i].0,
                "The OUTPUT_REPLACEMENTS array must be sorted (for binary search to work) \
                and must contain no duplicate entries"
            );
            i += 1;
        }
    }
    // Scan the input string for a character in the ordered table above.
    // If it's present, replace it with its alternative string (it can be more than 1 char!).
    // Otherwise, retain the input char.
    s.chars().fold(String::with_capacity(s.len()), |mut s, c| {
        match OUTPUT_REPLACEMENTS.binary_search_by_key(&c, |(k, _)| *k) {
            Ok(i) => s.push_str(OUTPUT_REPLACEMENTS[i].1),
            _ => s.push(c),
        }
        s
    })
}

pub type Destination = AutoStream<Box<dyn Write + Send>>;

struct Buffy {
    buffer_writer: std::io::Stderr,
    buffer: Vec<u8>,
}

impl Write for Buffy {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.buffer.write(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.buffer_writer.write_all(&self.buffer)?;
        self.buffer.clear();
        Ok(())
    }
}

impl Drop for Buffy {
    fn drop(&mut self) {
        if !self.buffer.is_empty() {
            self.flush().unwrap();
            panic!("buffers need to be flushed in order to print their contents");
        }
    }
}

pub fn stderr_destination(color: ColorConfig) -> Destination {
    let buffer_writer = std::io::stderr();
    // We need to resolve `ColorChoice::Auto` before `Box`ing since
    // `ColorChoice::Auto` on `dyn Write` will always resolve to `Never`
    let choice = get_stderr_color_choice(color, &buffer_writer);
    // On Windows we'll be performing global synchronization on the entire
    // system for emitting rustc errors, so there's no need to buffer
    // anything.
    //
    // On non-Windows we rely on the atomicity of `write` to ensure errors
    // don't get all jumbled up.
    if cfg!(windows) {
        AutoStream::new(Box::new(buffer_writer), choice)
    } else {
        let buffer = Vec::new();
        AutoStream::new(Box::new(Buffy { buffer_writer, buffer }), choice)
    }
}

pub fn get_stderr_color_choice(color: ColorConfig, stderr: &std::io::Stderr) -> ColorChoice {
    let choice = color.to_color_choice();
    if matches!(choice, ColorChoice::Auto) { AutoStream::choice(stderr) } else { choice }
}

/// On Windows, BRIGHT_BLUE is hard to read on black. Use cyan instead.
///
/// See #36178.
const BRIGHT_BLUE: anstyle::Style = if cfg!(windows) {
    AnsiColor::BrightCyan.on_default()
} else {
    AnsiColor::BrightBlue.on_default()
};

impl Style {
    pub(crate) fn anstyle(&self, lvl: Level) -> anstyle::Style {
        match self {
            Style::Addition => AnsiColor::BrightGreen.on_default(),
            Style::Removal => AnsiColor::BrightRed.on_default(),
            Style::LineAndColumn => anstyle::Style::new(),
            Style::LineNumber => BRIGHT_BLUE.effects(Effects::BOLD),
            Style::Quotation => anstyle::Style::new(),
            Style::MainHeaderMsg => if cfg!(windows) {
                AnsiColor::BrightWhite.on_default()
            } else {
                anstyle::Style::new()
            }
            .effects(Effects::BOLD),
            Style::UnderlinePrimary | Style::LabelPrimary => lvl.color().effects(Effects::BOLD),
            Style::UnderlineSecondary | Style::LabelSecondary => BRIGHT_BLUE.effects(Effects::BOLD),
            Style::HeaderMsg | Style::NoStyle => anstyle::Style::new(),
            Style::Level(lvl) => lvl.color().effects(Effects::BOLD),
            Style::Highlight => AnsiColor::Magenta.on_default().effects(Effects::BOLD),
        }
    }
}

/// Whether the original and suggested code are the same.
pub fn is_different(sm: &SourceMap, suggested: &str, sp: Span) -> bool {
    let found = match sm.span_to_snippet(sp) {
        Ok(snippet) => snippet,
        Err(e) => {
            warn!(error = ?e, "Invalid span {:?}", sp);
            return true;
        }
    };
    found != suggested
}

/// Whether the original and suggested code are visually similar enough to warrant extra wording.
pub fn detect_confusion_type(sm: &SourceMap, suggested: &str, sp: Span) -> ConfusionType {
    let found = match sm.span_to_snippet(sp) {
        Ok(snippet) => snippet,
        Err(e) => {
            warn!(error = ?e, "Invalid span {:?}", sp);
            return ConfusionType::None;
        }
    };

    let mut has_case_confusion = false;
    let mut has_digit_letter_confusion = false;

    if found.len() == suggested.len() {
        let mut has_case_diff = false;
        let mut has_digit_letter_confusable = false;
        let mut has_other_diff = false;

        // Letters whose lowercase version is very similar to the uppercase
        // version.
        let ascii_confusables = &['c', 'f', 'i', 'k', 'o', 's', 'u', 'v', 'w', 'x', 'y', 'z'];

        let digit_letter_confusables = [('0', 'O'), ('1', 'l'), ('5', 'S'), ('8', 'B'), ('9', 'g')];

        for (f, s) in iter::zip(found.chars(), suggested.chars()) {
            if f != s {
                if f.eq_ignore_ascii_case(&s) {
                    // Check for case differences (any character that differs only in case)
                    if ascii_confusables.contains(&f) || ascii_confusables.contains(&s) {
                        has_case_diff = true;
                    } else {
                        has_other_diff = true;
                    }
                } else if digit_letter_confusables.contains(&(f, s))
                    || digit_letter_confusables.contains(&(s, f))
                {
                    // Check for digit-letter confusables (like 0 vs O, 1 vs l, etc.)
                    has_digit_letter_confusable = true;
                } else {
                    has_other_diff = true;
                }
            }
        }

        // If we have case differences and no other differences
        if has_case_diff && !has_other_diff && found != suggested {
            has_case_confusion = true;
        }
        if has_digit_letter_confusable && !has_other_diff && found != suggested {
            has_digit_letter_confusion = true;
        }
    }

    match (has_case_confusion, has_digit_letter_confusion) {
        (true, true) => ConfusionType::Both,
        (true, false) => ConfusionType::Case,
        (false, true) => ConfusionType::DigitLetter,
        (false, false) => ConfusionType::None,
    }
}

/// Represents the type of confusion detected between original and suggested code.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ConfusionType {
    /// No confusion detected
    None,
    /// Only case differences (e.g., "hello" vs "Hello")
    Case,
    /// Only digit-letter confusion (e.g., "0" vs "O", "1" vs "l")
    DigitLetter,
    /// Both case and digit-letter confusion
    Both,
}

impl ConfusionType {
    /// Returns the appropriate label text for this confusion type.
    pub fn label_text(&self) -> &'static str {
        match self {
            ConfusionType::None => "",
            ConfusionType::Case => " (notice the capitalization)",
            ConfusionType::DigitLetter => " (notice the digit/letter confusion)",
            ConfusionType::Both => " (notice the capitalization and digit/letter confusion)",
        }
    }

    /// Combines two confusion types. If either is `Both`, the result is `Both`.
    /// If one is `Case` and the other is `DigitLetter`, the result is `Both`.
    /// Otherwise, returns the non-`None` type, or `None` if both are `None`.
    pub fn combine(self, other: ConfusionType) -> ConfusionType {
        match (self, other) {
            (ConfusionType::None, other) => other,
            (this, ConfusionType::None) => this,
            (ConfusionType::Both, _) | (_, ConfusionType::Both) => ConfusionType::Both,
            (ConfusionType::Case, ConfusionType::DigitLetter)
            | (ConfusionType::DigitLetter, ConfusionType::Case) => ConfusionType::Both,
            (ConfusionType::Case, ConfusionType::Case) => ConfusionType::Case,
            (ConfusionType::DigitLetter, ConfusionType::DigitLetter) => ConfusionType::DigitLetter,
        }
    }

    /// Returns true if this confusion type represents any kind of confusion.
    pub fn has_confusion(&self) -> bool {
        *self != ConfusionType::None
    }
}

pub(crate) fn should_show_source_code(
    ignored_directories: &[String],
    sm: &SourceMap,
    file: &SourceFile,
) -> bool {
    if !sm.ensure_source_file_source_present(file) {
        return false;
    }

    let FileName::Real(name) = &file.name else { return true };
    name.local_path()
        .map(|path| ignored_directories.iter().all(|dir| !path.starts_with(dir)))
        .unwrap_or(true)
}
