use crate::{SourceKey, protocol::lsp};
crate::define_dyn_partition!(
Diagnostics,
crate::partitions::known_keys::DIAGNOSTICS,
DiagnosticSortKey,
DiagnosticRecord
);
#[derive(Debug, Clone)]
pub enum DiagnosticSortKey {
Diagnostic {
source_key: SourceKey,
stage: u16,
severity: lsp::DiagnosticSeverity,
sequence: u16,
},
DiagnosticForDecl {
source_key: SourceKey,
stage: u16,
sort_key: Box<[u8]>,
severity: lsp::DiagnosticSeverity,
sequence: u16,
},
All,
FilePrefix(u16),
SourcePrefix(SourceKey),
SourceStagePrefix(SourceKey, u16),
SourceStageDeclPrefix(SourceKey, u16, Box<[u8]>),
}
impl std::fmt::Display for DiagnosticSortKey {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
| DiagnosticSortKey::Diagnostic {
source_key,
stage,
severity,
sequence,
} => write!(
f,
"{}|{:05}|{}|{:04}",
source_key, stage, severity, sequence
),
| DiagnosticSortKey::DiagnosticForDecl {
source_key,
stage,
sort_key,
severity,
sequence,
} => {
write!(f, "{}|{:05}|", source_key, stage)?;
for b in sort_key.iter() {
write!(f, "{:02x}", b)?;
}
write!(f, "|{}|{:04}", severity, sequence)
},
| DiagnosticSortKey::All => Ok(()),
| DiagnosticSortKey::FilePrefix(file_id) => {
write!(f, "{}v", file_id)
},
| DiagnosticSortKey::SourcePrefix(source_key) => {
write!(f, "{}|", source_key)
},
| DiagnosticSortKey::SourceStagePrefix(source_key, stage) => {
write!(f, "{}|{:05}|", source_key, stage)
},
| DiagnosticSortKey::SourceStageDeclPrefix(
source_key,
stage,
sort_key,
) => {
write!(f, "{}|{:05}|", source_key, stage)?;
for b in sort_key.iter() {
write!(f, "{:02x}", b)?;
}
write!(f, "|")
},
}
}
}
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
enum DiagToken {
File(u16),
Version(u16),
Stage(u16),
Decl(Box<[u8]>),
Severity(lsp::DiagnosticSeverity),
Seq(u16),
}
impl DiagnosticSortKey {
fn tokens(&self) -> Vec<DiagToken> {
match self {
| DiagnosticSortKey::All => Vec::new(),
| DiagnosticSortKey::FilePrefix(file_id) => {
vec![DiagToken::File(*file_id)]
},
| DiagnosticSortKey::SourcePrefix(sk) => {
vec![
DiagToken::File(sk.file_id()),
DiagToken::Version(sk.version()),
]
},
| DiagnosticSortKey::SourceStagePrefix(sk, stage) => vec![
DiagToken::File(sk.file_id()),
DiagToken::Version(sk.version()),
DiagToken::Stage(*stage),
],
| DiagnosticSortKey::SourceStageDeclPrefix(sk, stage, sort_key) => vec![
DiagToken::File(sk.file_id()),
DiagToken::Version(sk.version()),
DiagToken::Stage(*stage),
DiagToken::Decl(sort_key.clone()),
],
| DiagnosticSortKey::Diagnostic {
source_key,
stage,
severity,
sequence,
} => vec![
DiagToken::File(source_key.file_id()),
DiagToken::Version(source_key.version()),
DiagToken::Stage(*stage),
DiagToken::Severity(*severity),
DiagToken::Seq(*sequence),
],
| DiagnosticSortKey::DiagnosticForDecl {
source_key,
stage,
sort_key,
severity,
sequence,
} => vec![
DiagToken::File(source_key.file_id()),
DiagToken::Version(source_key.version()),
DiagToken::Stage(*stage),
DiagToken::Decl(sort_key.clone()),
DiagToken::Severity(*severity),
DiagToken::Seq(*sequence),
],
}
}
}
impl PartialEq for DiagnosticSortKey {
fn eq(&self, other: &Self) -> bool {
self.tokens() == other.tokens()
}
}
impl Eq for DiagnosticSortKey {}
impl std::hash::Hash for DiagnosticSortKey {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.tokens().hash(state);
}
}
impl PartialOrd for DiagnosticSortKey {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for DiagnosticSortKey {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.tokens().cmp(&other.tokens())
}
}
impl bluegum::Bluegum for DiagnosticSortKey {
fn node(&self, b: &mut bluegum::Builder) {
b.name("DiagnosticSortKey");
}
}
impl bluegum::BluegumWithState<dyn crate::SourceResolver> for DiagnosticSortKey {
fn node_with_state(
&self,
b: &mut bluegum::Builder,
resolver: &(dyn crate::SourceResolver + 'static),
) {
b.name("DiagnosticSortKey")
.alt(crate::database::PartitionSortKey::resolve(self, resolver));
}
}
impl crate::database::PartitionSortKey for DiagnosticSortKey {
fn is_prefix_of(&self, other: &Self) -> bool {
other.tokens().starts_with(&self.tokens())
}
fn resolve(&self, _resolver: &dyn crate::SourceResolver) -> String {
self.to_string()
}
}
pub trait DiagnosticRecord: Send + Sync + std::fmt::Debug {
fn to_lsp_diagnostic(
&self,
source_cache: &crate::source::cache::reporter::SourceCacheReader,
encoding: &crate::protocol::lsp::PositionEncodingKind,
) -> lsp::Diagnostic;
fn to_ariadne_report(
&self,
source_cache: &crate::source::cache::reporter::SourceCacheReader,
) -> ariadne::Report<'static, (SourceKey, std::ops::Range<usize>)>;
fn source_key(&self) -> Option<SourceKey>;
fn severity(&self) -> Option<lsp::DiagnosticSeverity>;
fn message(&self) -> Option<&str>;
}