mod code;
mod collection;
mod counted;
mod distinct;
mod label;
mod quoted_form;
mod render;
mod similar_name;
mod source_window;
pub use code::DiagnosticCode;
pub use collection::Diagnostics;
pub use counted::Counted;
pub use distinct::DistinctDiagnostics;
pub use label::{Help, Label, Suggestion};
pub use render::DiagnosticRenderer;
pub use similar_name::SimilarName;
use std::rc::Rc;
use crate::core::Namespace;
use crate::source::{SourceId, Span};
#[derive(Clone, Debug)]
pub struct Diagnostic {
report: Box<Report>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
enum Severity {
Error,
Warning,
Note,
}
#[derive(Clone, Debug)]
struct Report {
severity: Severity,
code: Option<DiagnosticCode>,
title: String,
primary: Label,
secondary: Vec<Label>,
notes: Vec<String>,
helps: Vec<Help>,
missing_name: Option<MissingName>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct MissingName {
pub name: Rc<str>,
pub namespace: Namespace,
}
impl Diagnostic {
pub fn error(code: DiagnosticCode, title: impl Into<String>, primary: Label) -> Self {
Self::new(Severity::Error, Some(code), title, primary)
}
pub fn warning(code: DiagnosticCode, title: impl Into<String>, primary: Label) -> Self {
Self::new(Severity::Warning, Some(code), title, primary)
}
pub fn note(title: impl Into<String>, primary: Label) -> Self {
Self::new(Severity::Note, None, title, primary)
}
fn new(
severity: Severity,
code: Option<DiagnosticCode>,
title: impl Into<String>,
primary: Label,
) -> Self {
Self {
report: Box::new(Report {
severity,
code,
title: title.into(),
primary,
secondary: Vec::new(),
notes: Vec::new(),
helps: Vec::new(),
missing_name: None,
}),
}
}
pub fn is_error(&self) -> bool {
self.report.severity == Severity::Error
}
pub fn is_note(&self) -> bool {
self.report.severity == Severity::Note
}
pub fn severity_name(&self) -> &'static str {
match self.report.severity {
Severity::Error => "error",
Severity::Warning => "warning",
Severity::Note => "note",
}
}
pub fn with_label(mut self, label: Label) -> Self {
self.report.secondary.push(label);
self
}
pub fn without_labels_in(mut self, source: SourceId) -> Self {
self.report
.secondary
.retain(|label| label.span().source() != source);
self
}
pub fn with_note(mut self, note: impl Into<String>) -> Self {
self.report.notes.push(note.into());
self
}
pub fn with_help(mut self, help: impl Into<String>) -> Self {
self.report.helps.push(Help::new(help.into()));
self
}
pub fn with_copied_help(mut self, help: Help) -> Self {
self.report.helps.push(help);
self
}
pub fn with_quoting_help(mut self, help: impl Into<String>, form: Span) -> Self {
self.report.helps.push(Help::quoting(help.into(), form));
self
}
pub fn with_suggestion(mut self, help: impl Into<String>, suggestion: Suggestion) -> Self {
self.report
.helps
.push(Help::new(help.into()).with_suggestion(suggestion));
self
}
pub fn with_missing_name(mut self, missing: MissingName) -> Self {
self.report.missing_name = Some(missing);
self
}
pub fn missing_name(&self) -> Option<&MissingName> {
self.report.missing_name.as_ref()
}
pub fn code(&self) -> Option<&DiagnosticCode> {
self.report.code.as_ref()
}
pub fn title(&self) -> &str {
&self.report.title
}
pub fn labels(&self) -> impl Iterator<Item = &Label> {
std::iter::once(&self.report.primary).chain(&self.report.secondary)
}
pub fn primary(&self) -> &Label {
&self.report.primary
}
pub fn notes(&self) -> &[String] {
&self.report.notes
}
pub fn helps(&self) -> &[Help] {
&self.report.helps
}
}