use std::borrow::Cow;
use vize_carton::i18n::{t, t_fmt, Locale};
#[derive(Debug, Clone)]
pub struct TypeDiagnostic {
pub code: TypeErrorCode,
pub message: String,
pub severity: TypeSeverity,
pub start: u32,
pub end: u32,
pub related: Vec<RelatedInfo>,
}
impl TypeDiagnostic {
pub fn error(code: TypeErrorCode, message: impl Into<String>, start: u32, end: u32) -> Self {
Self {
code,
message: message.into(),
severity: TypeSeverity::Error,
start,
end,
related: Vec::new(),
}
}
pub fn warning(code: TypeErrorCode, message: impl Into<String>, start: u32, end: u32) -> Self {
Self {
code,
message: message.into(),
severity: TypeSeverity::Warning,
start,
end,
related: Vec::new(),
}
}
pub fn with_related(mut self, info: RelatedInfo) -> Self {
self.related.push(info);
self
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TypeSeverity {
Error,
Warning,
}
#[derive(Debug, Clone)]
pub struct RelatedInfo {
pub message: String,
pub start: u32,
pub end: u32,
}
impl RelatedInfo {
pub fn new(message: impl Into<String>, start: u32, end: u32) -> Self {
Self {
message: message.into(),
start,
end,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u32)]
pub enum TypeErrorCode {
UnknownIdentifier = 2304,
PropertyNotFound = 2339,
ArgumentTypeMismatch = 2345,
TypeNotAssignable = 2322,
NotCallable = 2349,
MissingProperty = 2741,
ImplicitAny = 7006,
ModuleNotFound = 2307,
ExpectedArguments = 2554,
TooManyArguments = 2555,
TypeConstraint = 2344,
PossiblyUndefined = 2532,
PossiblyNull = 2531,
NotConstructable = 2351,
DuplicateIdentifier = 2300,
CannotRedeclare = 2451,
InvalidPropType = 9001,
InvalidEmit = 9002,
UnknownComponent = 9003,
InvalidSlot = 9004,
InvalidDirective = 9005,
ReactivityIssue = 9006,
}
impl TypeErrorCode {
#[inline]
pub const fn code(&self) -> u32 {
*self as u32
}
#[inline]
pub const fn name(&self) -> &'static str {
match self {
Self::UnknownIdentifier => "unknown-identifier",
Self::PropertyNotFound => "property-not-found",
Self::ArgumentTypeMismatch => "argument-type-mismatch",
Self::TypeNotAssignable => "type-not-assignable",
Self::NotCallable => "not-callable",
Self::MissingProperty => "missing-property",
Self::ImplicitAny => "implicit-any",
Self::ModuleNotFound => "module-not-found",
Self::ExpectedArguments => "expected-arguments",
Self::TooManyArguments => "too-many-arguments",
Self::TypeConstraint => "type-constraint",
Self::PossiblyUndefined => "possibly-undefined",
Self::PossiblyNull => "possibly-null",
Self::NotConstructable => "not-constructable",
Self::DuplicateIdentifier => "duplicate-identifier",
Self::CannotRedeclare => "cannot-redeclare",
Self::InvalidPropType => "invalid-prop-type",
Self::InvalidEmit => "invalid-emit",
Self::UnknownComponent => "unknown-component",
Self::InvalidSlot => "invalid-slot",
Self::InvalidDirective => "invalid-directive",
Self::ReactivityIssue => "reactivity-issue",
}
}
#[inline]
pub const fn help_key(&self) -> &'static str {
match self {
Self::UnknownIdentifier => "ts/2304.help",
Self::PropertyNotFound => "ts/2339.help",
Self::ArgumentTypeMismatch => "ts/2345.help",
Self::TypeNotAssignable => "ts/2322.help",
Self::NotCallable => "ts/2349.help",
Self::MissingProperty => "ts/2741.help",
Self::ImplicitAny => "ts/7006.help",
Self::ModuleNotFound => "ts/2307.help",
Self::ExpectedArguments => "ts/2554.help",
Self::TooManyArguments => "ts/2555.help",
Self::TypeConstraint => "ts/2344.help",
Self::PossiblyUndefined => "ts/2532.help",
Self::PossiblyNull => "ts/2531.help",
Self::NotConstructable => "ts/2351.help",
Self::DuplicateIdentifier => "ts/2300.help",
Self::CannotRedeclare => "ts/2451.help",
Self::InvalidPropType => "ts/vue/9001.help",
Self::InvalidEmit => "ts/vue/9002.help",
Self::UnknownComponent => "ts/vue/9003.help",
Self::InvalidSlot => "ts/vue/9004.help",
Self::InvalidDirective => "ts/vue/9005.help",
Self::ReactivityIssue => "ts/vue/9006.help",
}
}
#[inline]
pub fn help(&self, locale: Locale, vars: &[(&str, &str)]) -> String {
t_fmt(locale, self.help_key(), vars)
}
#[inline]
pub fn help_simple(&self, locale: Locale) -> Cow<'static, str> {
t(locale, self.help_key())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_diagnostic_creation() {
let diag = TypeDiagnostic::error(
TypeErrorCode::UnknownIdentifier,
"Cannot find name 'foo'",
0,
3,
);
assert_eq!(diag.severity, TypeSeverity::Error);
assert_eq!(diag.code, TypeErrorCode::UnknownIdentifier);
}
#[test]
fn test_error_code() {
assert_eq!(TypeErrorCode::UnknownIdentifier.code(), 2304);
assert_eq!(
TypeErrorCode::UnknownIdentifier.name(),
"unknown-identifier"
);
}
}