use std::fmt::Display;
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum Severity {
Error,
Warning,
}
impl Display for Severity {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Severity::Error => write!(f, "error"),
Severity::Warning => write!(f, "warning"),
}
}
}
#[derive(Debug)]
pub struct Pos {
offset: usize,
line: u32,
column: u32,
}
impl Pos {
pub(crate) fn new(offset: usize, line: u32, column: u32) -> Self {
Self {
offset,
line,
column,
}
}
pub(crate) fn dup(&self) -> Self {
Self {
offset: self.offset,
line: self.line,
column: self.column,
}
}
pub fn byte_offset(&self) -> usize {
self.offset
}
pub fn line_offset(&self) -> u32 {
self.line
}
pub fn column_offset(&self) -> u32 {
self.column
}
pub fn line_number(&self) -> u32 {
self.line + 1
}
pub fn column_number(&self) -> u32 {
self.column + 1
}
fn clone(&self) -> Self {
Self::new(self.offset, self.line, self.column)
}
}
#[derive(Debug)]
pub struct Span {
start: Pos,
end: Pos,
}
impl Span {
pub(crate) fn dup(&self) -> Self {
Self {
start: self.start.dup(),
end: self.end.dup(),
}
}
pub(crate) fn new(start: Pos, end: Pos) -> Self {
Self { start, end }
}
pub fn start(&self) -> Pos {
self.start.clone()
}
pub fn end(&self) -> Pos {
self.end.clone()
}
}
pub struct Diag {
severity: Severity,
span: Span,
message: String,
annotations: Vec<Annotation>,
notes: Vec<Note>,
patches: Vec<Patch>,
}
#[non_exhaustive]
pub enum AnnotationKind {
Primary,
Context,
}
impl AnnotationKind {
fn dup(&self) -> Self {
match self {
AnnotationKind::Primary => AnnotationKind::Primary,
AnnotationKind::Context => AnnotationKind::Context,
}
}
}
pub struct Annotation {
pub(crate) kind: AnnotationKind,
pub(crate) span: Span,
pub(crate) message: String,
}
impl Annotation {
pub fn kind(&self) -> AnnotationKind {
self.kind.dup()
}
pub fn span(&self) -> Span {
self.span.dup()
}
pub fn message(&self) -> impl Display + '_ {
self.message.as_str()
}
}
#[non_exhaustive]
pub enum NoteKind {
Info,
Help,
}
impl NoteKind {
fn dup(&self) -> Self {
match self {
NoteKind::Help => NoteKind::Help,
NoteKind::Info => NoteKind::Info,
}
}
}
pub struct Note {
pub(crate) kind: NoteKind,
pub(crate) message: String,
}
impl Note {
pub fn kind(&self) -> NoteKind {
self.kind.dup()
}
pub fn message(&self) -> impl Display + '_ {
self.message.as_str()
}
}
pub struct Patch {
pub(crate) span: Span,
pub(crate) message: String,
pub(crate) sub: String,
}
impl Patch {
pub fn span(&self) -> Span {
self.span.dup()
}
pub fn sub(&self) -> &str {
&self.sub
}
pub fn message(&self) -> &str {
&self.message
}
}
#[derive(Debug)]
pub enum Origin {
ImportItem {
module: Span,
item: Span,
name: Span,
},
ImportModule {
module: Span,
name: Span,
},
PreludeModule {
module: String,
name: String,
},
PreludeItem {
module: String,
item: String,
name: String,
},
Class {
span: Span,
},
Def {
span: Span,
class: Option<Span>,
},
Bind {
span: Span,
class: Option<Span>,
},
Param {
span: Span,
},
SelfParam {
span: Span,
},
}
impl Diag {
pub(crate) fn new(
severity: Severity,
span: Span,
message: impl Into<String>,
annotations: impl Iterator<Item = Annotation>,
notes: impl Iterator<Item = Note>,
patches: impl Iterator<Item = Patch>,
) -> Self {
Self {
severity,
span,
message: message.into(),
notes: notes.collect(),
annotations: annotations.collect(),
patches: patches.collect(),
}
}
pub fn severity(&self) -> Severity {
self.severity
}
pub fn message(&self) -> impl Display + '_ {
self.message.as_str()
}
pub fn span(&self) -> Span {
self.span.dup()
}
pub fn annotations(&self) -> impl Iterator<Item = Annotation> {
self.annotations.iter().map(|a| Annotation {
kind: a.kind.dup(),
span: a.span.dup(),
message: a.message.clone(),
})
}
pub fn patches(&self) -> impl Iterator<Item = Patch> {
self.patches.iter().map(|p| Patch {
span: p.span.dup(),
sub: p.sub.clone(),
message: p.message.clone(),
})
}
pub fn notes(&self) -> impl Iterator<Item = Note> {
self.notes.iter().map(|n| Note {
kind: n.kind.dup(),
message: n.message.clone(),
})
}
}