Skip to main content

miniextendr_lint/
diagnostic.rs

1//! Structured diagnostic output for lint rules.
2
3use std::fmt;
4use std::path::PathBuf;
5
6use crate::lint_code::LintCode;
7
8/// Diagnostic severity level.
9#[derive(#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for Severity { }
#[automatically_derived]
impl ::core::clone::Clone for Severity {
    #[inline]
    fn clone(&self) -> Self { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for Severity { }Copy, #[automatically_derived]
impl ::core::fmt::Debug for Severity {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                Severity::Info => "Info",
                Severity::Warning => "Warning",
                Severity::Error => "Error",
            })
    }
}Debug, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for Severity { }
#[automatically_derived]
impl ::core::cmp::PartialEq for Severity {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        ::core::intrinsics::discriminant_value(self) ==
            ::core::intrinsics::discriminant_value(other)
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for Severity { }Eq, #[automatically_derived]
impl ::core::cmp::PartialOrd for Severity {
    #[inline]
    fn partial_cmp(&self, other: &Self)
        -> ::core::option::Option<::core::cmp::Ordering> {
        ::core::option::Option::Some(::core::cmp::Ord::cmp(self, other))
    }
}PartialOrd, #[automatically_derived]
impl ::core::cmp::Ord for Severity {
    #[inline]
    fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
        ::core::cmp::Ord::cmp(&::core::intrinsics::discriminant_value(self),
            &::core::intrinsics::discriminant_value(other))
    }
}Ord)]
10pub enum Severity {
11    /// Migration hints and informational notes.
12    Info,
13    /// Default for new rules; non-blocking.
14    Warning,
15    /// CI-blocking in strict mode.
16    Error,
17}
18
19impl fmt::Display for Severity {
20    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
21        match self {
22            Self::Info => f.write_str("info"),
23            Self::Warning => f.write_str("warning"),
24            Self::Error => f.write_str("error"),
25        }
26    }
27}
28
29/// A single lint diagnostic with structured metadata.
30#[derive(#[automatically_derived]
impl ::core::clone::Clone for Diagnostic {
    #[inline]
    fn clone(&self) -> Self {
        Diagnostic {
            code: ::core::clone::Clone::clone(&self.code),
            severity: ::core::clone::Clone::clone(&self.severity),
            path: ::core::clone::Clone::clone(&self.path),
            line: ::core::clone::Clone::clone(&self.line),
            message: ::core::clone::Clone::clone(&self.message),
            help: ::core::clone::Clone::clone(&self.help),
        }
    }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for Diagnostic {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        let names: &'static _ =
            &["code", "severity", "path", "line", "message", "help"];
        let values: &[&dyn ::core::fmt::Debug] =
            &[&self.code, &self.severity, &self.path, &self.line,
                        &self.message, &&self.help];
        ::core::fmt::Formatter::debug_struct_fields_finish(f, "Diagnostic",
            names, values)
    }
}Debug)]
31pub struct Diagnostic {
32    /// Stable rule code (e.g. `MXL106`).
33    pub code: LintCode,
34    /// Severity level.
35    pub severity: Severity,
36    /// Source file path.
37    pub path: PathBuf,
38    /// 1-based line number (0 if unknown).
39    pub line: usize,
40    /// Primary diagnostic message.
41    pub message: String,
42    /// Optional fix guidance.
43    pub help: Option<String>,
44}
45
46impl Diagnostic {
47    /// Create a new diagnostic with the rule's default severity.
48    pub fn new(code: LintCode, path: impl Into<PathBuf>, line: usize, message: String) -> Self {
49        Self {
50            severity: code.default_severity(),
51            code,
52            path: path.into(),
53            line,
54            message,
55            help: None,
56        }
57    }
58
59    /// Attach a help message.
60    pub fn with_help(mut self, help: impl Into<String>) -> Self {
61        self.help = Some(help.into());
62        self
63    }
64
65    /// Format as a legacy error string (for backward-compatible `LintReport::errors`).
66    pub fn to_legacy_string(&self) -> String {
67        let mut s = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}:{1}: {2}", self.path.display(),
                self.line, self.message))
    })format!("{}:{}: {}", self.path.display(), self.line, self.message);
68        if let Some(ref help) = self.help {
69            s.push(' ');
70            s.push_str(help);
71        }
72        s
73    }
74}
75
76impl fmt::Display for Diagnostic {
77    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
78        f.write_fmt(format_args!("[{0}] {1}:{2}: {3}", self.code, self.path.display(),
        self.line, self.message))write!(
79            f,
80            "[{}] {}:{}: {}",
81            self.code,
82            self.path.display(),
83            self.line,
84            self.message,
85        )?;
86        if let Some(ref help) = self.help {
87            f.write_fmt(format_args!(" Help: {0}", help))write!(f, " Help: {}", help)?;
88        }
89        Ok(())
90    }
91}