//! 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.diagnostic_opaque))
                    }
                }
            })
            .collect();

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

        self.render_multispans_macro_backtrace(span, children, backtrace);

        if !backtrace {
            // Skip macros annotated with `#[diagnostic::opaque]`. Builtin macros are "opaque" too.
            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 };
        let should_hide = |span| {
            source_map.is_imported(span) || {
                let expn = span.data().ctxt.outer_expn_data();
                expn.diagnostic_opaque && matches!(expn.kind, ExpnKind::Macro(MacroKind::Bang, _))
            }
        };

        // 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() && should_hide(sp) {
                    let mut span = sp;
                    while let Some(callsite) = span.parent_callsite() {
                        span = callsite;
                        if !should_hide(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)
}
