From 6389f7ed7be8469b2989bb7d1190069de7b61220 Mon Sep 17 00:00:00 2001 From: Josh Thomas Date: Mon, 8 Sep 2025 21:30:39 -0500 Subject: [PATCH] remove duplication in validation and span conversion (#203) --- crates/djls-templates/src/ast.rs | 96 +++++++++++--------------------- crates/djls-templates/src/lib.rs | 5 +- 2 files changed, 37 insertions(+), 64 deletions(-) diff --git a/crates/djls-templates/src/ast.rs b/crates/djls-templates/src/ast.rs index 893d0cf..7ad4e52 100644 --- a/crates/djls-templates/src/ast.rs +++ b/crates/djls-templates/src/ast.rs @@ -131,6 +131,30 @@ impl<'db> Span<'db> { let length = u32::try_from(token.lexeme().len()).unwrap_or(0); Span::new(db, start, length) } + + #[must_use] + pub fn to_lsp_range( + &self, + db: &'db dyn crate::db::Db, + line_offsets: &LineOffsets, + ) -> tower_lsp_server::lsp_types::Range { + let start_pos = self.start(db) as usize; + let end_pos = (self.start(db) + self.length(db)) as usize; + + let (start_line, start_char) = line_offsets.position_to_line_col(start_pos); + let (end_line, end_char) = line_offsets.position_to_line_col(end_pos); + + tower_lsp_server::lsp_types::Range { + start: tower_lsp_server::lsp_types::Position { + line: u32::try_from(start_line - 1).unwrap_or(u32::MAX), // LSP is 0-based, LineOffsets is 1-based + character: u32::try_from(start_char).unwrap_or(u32::MAX), + }, + end: tower_lsp_server::lsp_types::Position { + line: u32::try_from(end_line - 1).unwrap_or(u32::MAX), + character: u32::try_from(end_char).unwrap_or(u32::MAX), + }, + } + } } #[derive(Clone, Debug, Error, PartialEq, Eq, Serialize)] @@ -248,73 +272,19 @@ impl AstError { #[must_use] pub fn diagnostic_code(&self) -> &'static str { match self { - AstError::EmptyAst => "DTL-001", - AstError::InvalidTagStructure { .. } => "DTL-002", - AstError::UnbalancedStructure { .. } => "DTL-003", - AstError::InvalidNode { .. } => "DTL-004", - AstError::UnclosedTag { .. } => "DTL-005", - AstError::OrphanedTag { .. } => "DTL-006", - AstError::UnmatchedBlockName { .. } => "DTL-007", - AstError::MissingRequiredArguments { .. } => "DTL-008", - AstError::TooManyArguments { .. } => "DTL-009", + AstError::EmptyAst => "T001", + AstError::InvalidTagStructure { .. } => "T002", + AstError::UnbalancedStructure { .. } => "T003", + AstError::InvalidNode { .. } => "T004", + AstError::UnclosedTag { .. } => "T005", + AstError::OrphanedTag { .. } => "T006", + AstError::UnmatchedBlockName { .. } => "T007", + AstError::MissingRequiredArguments { .. } => "T008", + AstError::TooManyArguments { .. } => "T009", } } } -impl<'db> Span<'db> { - /// Convert this span to an LSP Range using the provided line offsets - #[must_use] - pub fn to_lsp_range( - &self, - db: &'db dyn crate::db::Db, - line_offsets: &LineOffsets, - ) -> tower_lsp_server::lsp_types::Range { - let start_pos = self.start(db) as usize; - let end_pos = (self.start(db) + self.length(db)) as usize; - - let (start_line, start_char) = line_offsets.position_to_line_col(start_pos); - let (end_line, end_char) = line_offsets.position_to_line_col(end_pos); - - #[allow(clippy::cast_possible_truncation)] - tower_lsp_server::lsp_types::Range { - start: tower_lsp_server::lsp_types::Position { - line: (start_line - 1) as u32, // LSP is 0-based, LineOffsets is 1-based - character: start_char as u32, - }, - end: tower_lsp_server::lsp_types::Position { - line: (end_line - 1) as u32, - character: end_char as u32, - }, - } - } -} - -/// Helper function to create an LSP Range from raw span data -#[must_use] -pub fn span_to_lsp_range( - start: u32, - length: u32, - line_offsets: &LineOffsets, -) -> tower_lsp_server::lsp_types::Range { - let start_pos = start as usize; - let end_pos = (start + length) as usize; - - let (start_line, start_char) = line_offsets.position_to_line_col(start_pos); - let (end_line, end_char) = line_offsets.position_to_line_col(end_pos); - - #[allow(clippy::cast_possible_truncation)] - tower_lsp_server::lsp_types::Range { - start: tower_lsp_server::lsp_types::Position { - line: (start_line - 1) as u32, // LSP is 0-based, LineOffsets is 1-based - character: start_char as u32, - }, - end: tower_lsp_server::lsp_types::Position { - line: (end_line - 1) as u32, - character: end_char as u32, - }, - } -} - #[cfg(test)] mod tests { use super::*; diff --git a/crates/djls-templates/src/lib.rs b/crates/djls-templates/src/lib.rs index d190c86..ab4d055 100644 --- a/crates/djls-templates/src/lib.rs +++ b/crates/djls-templates/src/lib.rs @@ -162,7 +162,10 @@ fn accumulate_error(db: &dyn Db, error: &TemplateError, line_offsets: &LineOffse let code = error.diagnostic_code(); let range = error .span() - .map(|(start, length)| crate::ast::span_to_lsp_range(start, length, line_offsets)) + .map(|(start, length)| { + let span = crate::ast::Span::new(db, start, length); + span.to_lsp_range(db, line_offsets) + }) .unwrap_or_default(); let diagnostic = tower_lsp_server::lsp_types::Diagnostic {