tawasuyu/llimphi
Sovereign retained-mode GPU UI framework in Rust (wgpu+vello+taffy+parley), Elm loop, 40+ widgets.
chore: refresco desde el monorepo — vello 0.9 / wgpu 29, 120 miembros
1//! Diagnósticos del editor — espejo minimal del shape de `lsp-types`
2//! sin depender del crate. Pensado para que un client LSP (rust-analyzer,
3//! pylsp, etc.) lo poble desde fuera; el render del editor los pinta
4//! como subrayado bajo el rango.
5//!
6//! El client real vive aparte (proceso + JSON-RPC) — este módulo sólo
7//! define el shape de los datos y el helper para renderizarlos.
8
9use alloc::string::String;
10
11use crate::cursor::Pos;
12
13/// Severidad — mismos valores y orden que en LSP (1 = Error es el más alto).
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15pub enum Severity {
16 Error,
17 Warning,
18 Information,
19 Hint,
20}
21
22/// Rango cerrado de un diagnostic. `end` exclusivo en `col`.
23#[derive(Debug, Clone, Copy, PartialEq, Eq)]
24pub struct DiagnosticRange {
25 pub start: Pos,
26 pub end: Pos,
27}
28
29#[derive(Debug, Clone, PartialEq, Eq)]
30pub struct Diagnostic {
31 pub range: DiagnosticRange,
32 pub severity: Severity,
33 /// Mensaje humano corto — el render lo trunca para mostrar al hover/
34 /// en una mini popup futura. En esta versión solo se usa el rango.
35 pub message: String,
36 /// Source del diagnostic — "rust-analyzer", "pylsp", "clippy", etc.
37 /// `None` si no se conoce.
38 pub source: Option<String>,
39}
40
41impl Diagnostic {
42 pub fn error(line_start: usize, col_start: usize, line_end: usize, col_end: usize, message: impl Into<String>) -> Self {
43 Self {
44 range: DiagnosticRange {
45 start: Pos::new(line_start, col_start),
46 end: Pos::new(line_end, col_end),
47 },
48 severity: Severity::Error,
49 message: message.into(),
50 source: None,
51 }
52 }
53 pub fn warning(line_start: usize, col_start: usize, line_end: usize, col_end: usize, message: impl Into<String>) -> Self {
54 Self {
55 range: DiagnosticRange {
56 start: Pos::new(line_start, col_start),
57 end: Pos::new(line_end, col_end),
58 },
59 severity: Severity::Warning,
60 message: message.into(),
61 source: None,
62 }
63 }
64}
65
66#[cfg(test)]
67mod tests {
68 use super::*;
69
70 #[test]
71 fn constructors_funcionan() {
72 let e = Diagnostic::error(1, 2, 1, 5, "boom");
73 assert_eq!(e.severity, Severity::Error);
74 assert_eq!(e.range.start, Pos::new(1, 2));
75 assert_eq!(e.range.end, Pos::new(1, 5));
76
77 let w = Diagnostic::warning(0, 0, 0, 10, "ojo");
78 assert_eq!(w.severity, Severity::Warning);
79 }
80}