mirror of
https://github.com/joshuadavidthomas/django-language-server.git
synced 2025-09-10 04:16:30 +00:00
add testing
This commit is contained in:
parent
fab360bb60
commit
070a66f161
2 changed files with 151 additions and 4 deletions
|
@ -13,6 +13,10 @@ impl Ast {
|
|||
&self.nodes
|
||||
}
|
||||
|
||||
pub fn line_offsets(&self) -> &LineOffsets {
|
||||
&self.line_offsets
|
||||
}
|
||||
|
||||
pub fn errors(&self) -> &Vec<AstError> {
|
||||
&self.errors
|
||||
}
|
||||
|
@ -42,8 +46,7 @@ pub struct LineOffsets(Vec<u32>);
|
|||
|
||||
impl LineOffsets {
|
||||
pub fn new() -> Self {
|
||||
let mut offsets = Vec::new();
|
||||
offsets.push(0); // First line always starts at 0
|
||||
let offsets = vec![0];
|
||||
Self(offsets)
|
||||
}
|
||||
|
||||
|
@ -51,7 +54,7 @@ impl LineOffsets {
|
|||
self.0.push(offset);
|
||||
}
|
||||
|
||||
fn position_to_line_col(&self, offset: u32) -> (u32, u32) {
|
||||
pub fn position_to_line_col(&self, offset: u32) -> (u32, u32) {
|
||||
let line = match self.0.binary_search(&offset) {
|
||||
Ok(line) => line,
|
||||
Err(line) => line - 1,
|
||||
|
@ -60,11 +63,44 @@ impl LineOffsets {
|
|||
(line as u32, col)
|
||||
}
|
||||
|
||||
fn line_col_to_position(&self, line: u32, col: u32) -> u32 {
|
||||
pub fn line_col_to_position(&self, line: u32, col: u32) -> u32 {
|
||||
self.0[line as usize] + col
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_line_offsets() {
|
||||
let mut offsets = LineOffsets::new();
|
||||
offsets.add_line(10); // Line 1 starts at offset 10
|
||||
offsets.add_line(25); // Line 2 starts at offset 25
|
||||
offsets.add_line(40); // Line 3 starts at offset 40
|
||||
|
||||
// Test position_to_line_col
|
||||
assert_eq!(offsets.position_to_line_col(0), (0, 0)); // Start of first line
|
||||
assert_eq!(offsets.position_to_line_col(5), (0, 5)); // Middle of first line
|
||||
assert_eq!(offsets.position_to_line_col(10), (1, 0)); // Start of second line
|
||||
assert_eq!(offsets.position_to_line_col(15), (1, 5)); // Middle of second line
|
||||
assert_eq!(offsets.position_to_line_col(25), (2, 0)); // Start of third line
|
||||
assert_eq!(offsets.position_to_line_col(35), (2, 10)); // Middle of third line
|
||||
assert_eq!(offsets.position_to_line_col(40), (3, 0)); // Start of fourth line
|
||||
assert_eq!(offsets.position_to_line_col(45), (3, 5)); // Middle of fourth line
|
||||
|
||||
// Test line_col_to_position
|
||||
assert_eq!(offsets.line_col_to_position(0, 0), 0); // Start of first line
|
||||
assert_eq!(offsets.line_col_to_position(0, 5), 5); // Middle of first line
|
||||
assert_eq!(offsets.line_col_to_position(1, 0), 10); // Start of second line
|
||||
assert_eq!(offsets.line_col_to_position(1, 5), 15); // Middle of second line
|
||||
assert_eq!(offsets.line_col_to_position(2, 0), 25); // Start of third line
|
||||
assert_eq!(offsets.line_col_to_position(2, 10), 35); // Middle of third line
|
||||
assert_eq!(offsets.line_col_to_position(3, 0), 40); // Start of fourth line
|
||||
assert_eq!(offsets.line_col_to_position(3, 5), 45); // Middle of fourth line
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize)]
|
||||
pub struct Span {
|
||||
start: u32,
|
||||
|
|
|
@ -741,4 +741,115 @@ mod tests {
|
|||
insta::assert_yaml_snapshot!(ast);
|
||||
}
|
||||
}
|
||||
|
||||
mod span_tracking {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_span_tracking() {
|
||||
let mut tokens = TokenStream::default();
|
||||
// First line: "Hello\n"
|
||||
tokens.add_token(Token::new(TokenType::Text("Hello".to_string()), 0, Some(0)));
|
||||
tokens.add_token(Token::new(TokenType::Newline, 0, Some(5)));
|
||||
// Second line: "{{ name }}\n"
|
||||
tokens.add_token(Token::new(
|
||||
TokenType::DjangoVariable("name".to_string()),
|
||||
1,
|
||||
Some(6),
|
||||
));
|
||||
tokens.add_token(Token::new(TokenType::Newline, 1, Some(16)));
|
||||
// Third line: "{% if condition %}\n"
|
||||
tokens.add_token(Token::new(
|
||||
TokenType::DjangoBlock("if condition".to_string()),
|
||||
2,
|
||||
Some(17),
|
||||
));
|
||||
tokens.add_token(Token::new(TokenType::Newline, 2, Some(34)));
|
||||
// Fourth line: " Content\n"
|
||||
tokens.add_token(Token::new(TokenType::Whitespace(2), 3, Some(35)));
|
||||
tokens.add_token(Token::new(
|
||||
TokenType::Text("Content".to_string()),
|
||||
3,
|
||||
Some(37),
|
||||
));
|
||||
tokens.add_token(Token::new(TokenType::Newline, 3, Some(44)));
|
||||
// Fifth line: "{% endif %}"
|
||||
tokens.add_token(Token::new(
|
||||
TokenType::DjangoBlock("endif".to_string()),
|
||||
4,
|
||||
Some(45),
|
||||
));
|
||||
tokens.finalize(4);
|
||||
|
||||
let mut parser = Parser::new(tokens);
|
||||
let ast = parser.parse().unwrap();
|
||||
|
||||
// Verify line offsets
|
||||
let offsets = ast.line_offsets();
|
||||
assert_eq!(offsets.position_to_line_col(0), (0, 0)); // Start of first line
|
||||
assert_eq!(offsets.position_to_line_col(6), (1, 0)); // Start of second line
|
||||
assert_eq!(offsets.position_to_line_col(17), (2, 0)); // Start of third line
|
||||
assert_eq!(offsets.position_to_line_col(35), (3, 0)); // Start of fourth line
|
||||
assert_eq!(offsets.position_to_line_col(45), (4, 0)); // Start of fifth line
|
||||
|
||||
// Verify node spans
|
||||
let nodes = ast.nodes();
|
||||
|
||||
// First node: Text "Hello"
|
||||
if let Node::Text { content, span } = &nodes[0] {
|
||||
assert_eq!(content, "Hello");
|
||||
assert_eq!(*span.start(), 0);
|
||||
assert_eq!(*span.length(), 5);
|
||||
} else {
|
||||
panic!("Expected Text node");
|
||||
}
|
||||
|
||||
// Second node: Variable "name"
|
||||
if let Node::Variable {
|
||||
bits,
|
||||
filters,
|
||||
span,
|
||||
} = &nodes[1]
|
||||
{
|
||||
assert_eq!(bits[0], "name");
|
||||
assert!(filters.is_empty());
|
||||
assert_eq!(*span.start(), 6);
|
||||
assert_eq!(*span.length(), 4);
|
||||
} else {
|
||||
panic!("Expected Variable node");
|
||||
}
|
||||
|
||||
// Third node: Block "if condition"
|
||||
if let Node::Block {
|
||||
name,
|
||||
bits,
|
||||
children,
|
||||
span,
|
||||
tag_span,
|
||||
..
|
||||
} = &nodes[2]
|
||||
{
|
||||
assert_eq!(name, "if");
|
||||
assert_eq!(bits[1], "condition");
|
||||
assert_eq!(*span.start(), 17);
|
||||
assert_eq!(*tag_span.start(), 17);
|
||||
assert_eq!(*tag_span.length(), 11);
|
||||
|
||||
// Check content node
|
||||
if let Some(child_nodes) = children {
|
||||
if let Node::Text { content, span } = &child_nodes[0] {
|
||||
assert_eq!(content.trim(), "Content");
|
||||
assert_eq!(*span.start(), 37);
|
||||
assert_eq!(*span.length(), 7);
|
||||
} else {
|
||||
panic!("Expected Text node as child");
|
||||
}
|
||||
} else {
|
||||
panic!("Expected children in if block");
|
||||
}
|
||||
} else {
|
||||
panic!("Expected Block node");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue