use std::fmt;
use crate::fix_hint::FixHint;
use crate::span::Span;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Severity {
Error,
Warning,
Hint,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum DiagnosticKind {
LexError,
ParseError,
Lint,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Diagnostic {
pub severity: Severity,
pub kind: DiagnosticKind,
pub message: String,
pub span: Span,
pub help: Option<String>,
pub code: Option<String>,
pub fix: Option<FixHint>,
}
impl fmt::Display for Diagnostic {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(&self.message)
}
}
impl Diagnostic {
pub fn error(kind: DiagnosticKind, message: impl Into<String>, span: Span) -> Self {
Self {
severity: Severity::Error,
kind,
message: message.into(),
span,
help: None,
code: None,
fix: None,
}
}
pub fn with_help(mut self, help: impl Into<String>) -> Self {
self.help = Some(help.into());
self
}
pub fn with_code(mut self, code: impl Into<String>) -> Self {
self.code = Some(code.into());
self
}
pub fn with_fix(mut self, fix: FixHint) -> Self {
self.fix = Some(fix);
self
}
pub fn format(&self, source: &str, file: &str) -> String {
let (line, col) = self.span.line_col(source);
let mut out = format!(
"{file}:{line}:{col}: {:?}: {}",
self.severity, self.message
);
if let Some(help) = &self.help {
out.push_str("\n help: ");
out.push_str(help);
}
out
}
}