mirror of
https://github.com/joshuadavidthomas/django-language-server.git
synced 2025-09-11 21:06:31 +00:00
simplify Span struct and remove salsa tracking (#205)
Some checks are pending
lint / pre-commit (push) Waiting to run
lint / rustfmt (push) Waiting to run
lint / clippy (push) Waiting to run
lint / cargo-check (push) Waiting to run
release / build (push) Waiting to run
release / test (push) Waiting to run
release / release (push) Blocked by required conditions
test / generate-matrix (push) Waiting to run
test / Python , Django () (push) Blocked by required conditions
test / tests (push) Blocked by required conditions
zizmor 🌈 / zizmor latest via PyPI (push) Waiting to run
Some checks are pending
lint / pre-commit (push) Waiting to run
lint / rustfmt (push) Waiting to run
lint / clippy (push) Waiting to run
lint / cargo-check (push) Waiting to run
release / build (push) Waiting to run
release / test (push) Waiting to run
release / release (push) Blocked by required conditions
test / generate-matrix (push) Waiting to run
test / Python , Django () (push) Blocked by required conditions
test / tests (push) Blocked by required conditions
zizmor 🌈 / zizmor latest via PyPI (push) Waiting to run
This commit is contained in:
parent
333e939c3f
commit
03f18d2211
4 changed files with 68 additions and 134 deletions
|
@ -57,8 +57,8 @@ impl Default for LineOffsets {
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, salsa::Update)]
|
#[derive(Clone, Debug, PartialEq, Eq, salsa::Update)]
|
||||||
pub enum Node<'db> {
|
pub enum Node<'db> {
|
||||||
Tag(TagNode<'db>),
|
Tag(TagNode<'db>),
|
||||||
Comment(CommentNode<'db>),
|
Comment(CommentNode),
|
||||||
Text(TextNode<'db>),
|
Text(TextNode),
|
||||||
Variable(VariableNode<'db>),
|
Variable(VariableNode<'db>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ pub enum Node<'db> {
|
||||||
pub struct TagNode<'db> {
|
pub struct TagNode<'db> {
|
||||||
pub name: TagName<'db>,
|
pub name: TagName<'db>,
|
||||||
pub bits: Vec<String>,
|
pub bits: Vec<String>,
|
||||||
pub span: Span<'db>,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[salsa::interned(debug)]
|
#[salsa::interned(debug)]
|
||||||
|
@ -75,22 +75,22 @@ pub struct TagName<'db> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, salsa::Update)]
|
#[derive(Debug, Clone, PartialEq, Eq, salsa::Update)]
|
||||||
pub struct CommentNode<'db> {
|
pub struct CommentNode {
|
||||||
pub content: String,
|
pub content: String,
|
||||||
pub span: Span<'db>,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, salsa::Update)]
|
#[derive(Debug, Clone, PartialEq, Eq, salsa::Update)]
|
||||||
pub struct TextNode<'db> {
|
pub struct TextNode {
|
||||||
pub content: String,
|
pub content: String,
|
||||||
pub span: Span<'db>,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, salsa::Update)]
|
#[derive(Debug, Clone, PartialEq, Eq, salsa::Update)]
|
||||||
pub struct VariableNode<'db> {
|
pub struct VariableNode<'db> {
|
||||||
pub var: VariableName<'db>,
|
pub var: VariableName<'db>,
|
||||||
pub filters: Vec<FilterName<'db>>,
|
pub filters: Vec<FilterName<'db>>,
|
||||||
pub span: Span<'db>,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[salsa::interned(debug)]
|
#[salsa::interned(debug)]
|
||||||
|
@ -103,29 +103,29 @@ pub struct FilterName<'db> {
|
||||||
pub text: String,
|
pub text: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[salsa::tracked(debug)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize)]
|
||||||
pub struct Span<'db> {
|
pub struct Span {
|
||||||
#[tracked]
|
|
||||||
pub start: u32,
|
pub start: u32,
|
||||||
#[tracked]
|
|
||||||
pub length: u32,
|
pub length: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'db> Span<'db> {
|
impl Span {
|
||||||
pub fn from_token(db: &'db dyn crate::db::Db, token: &Token) -> Self {
|
#[must_use]
|
||||||
let start = token.start().unwrap_or(0);
|
pub fn new(start: u32, length: u32) -> Self {
|
||||||
let length = u32::try_from(token.lexeme().len()).unwrap_or(0);
|
Self { start, length }
|
||||||
Span::new(db, start, length)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn to_lsp_range(
|
pub fn from_token(token: &Token) -> Self {
|
||||||
&self,
|
let start = token.start().unwrap_or(0);
|
||||||
db: &'db dyn crate::db::Db,
|
let length = u32::try_from(token.lexeme().len()).unwrap_or(0);
|
||||||
line_offsets: &LineOffsets,
|
Self { start, length }
|
||||||
) -> 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;
|
#[must_use]
|
||||||
|
pub fn to_lsp_range(&self, line_offsets: &LineOffsets) -> tower_lsp_server::lsp_types::Range {
|
||||||
|
let start_pos = self.start as usize;
|
||||||
|
let end_pos = (self.start + self.length) as usize;
|
||||||
|
|
||||||
let (start_line, start_char) = line_offsets.position_to_line_col(start_pos);
|
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);
|
let (end_line, end_char) = line_offsets.position_to_line_col(end_pos);
|
||||||
|
@ -151,58 +151,35 @@ pub enum AstError {
|
||||||
InvalidTagStructure {
|
InvalidTagStructure {
|
||||||
tag: String,
|
tag: String,
|
||||||
reason: String,
|
reason: String,
|
||||||
span_start: u32,
|
span: Span,
|
||||||
span_length: u32,
|
|
||||||
},
|
},
|
||||||
#[error("Unbalanced structure: '{opening_tag}' missing closing '{expected_closing}'")]
|
#[error("Unbalanced structure: '{opening_tag}' missing closing '{expected_closing}'")]
|
||||||
UnbalancedStructure {
|
UnbalancedStructure {
|
||||||
opening_tag: String,
|
opening_tag: String,
|
||||||
expected_closing: String,
|
expected_closing: String,
|
||||||
opening_span_start: u32,
|
opening_span: Span,
|
||||||
opening_span_length: u32,
|
closing_span: Option<Span>,
|
||||||
closing_span_start: Option<u32>,
|
|
||||||
closing_span_length: Option<u32>,
|
|
||||||
},
|
},
|
||||||
#[error("Invalid {node_type} node: {reason}")]
|
#[error("Invalid {node_type} node: {reason}")]
|
||||||
InvalidNode {
|
InvalidNode {
|
||||||
node_type: String,
|
node_type: String,
|
||||||
reason: String,
|
reason: String,
|
||||||
span_start: u32,
|
span: Span,
|
||||||
span_length: u32,
|
|
||||||
},
|
},
|
||||||
#[error("Unclosed tag: {tag}")]
|
#[error("Unclosed tag: {tag}")]
|
||||||
UnclosedTag {
|
UnclosedTag { tag: String, span: Span },
|
||||||
tag: String,
|
|
||||||
span_start: u32,
|
|
||||||
span_length: u32,
|
|
||||||
},
|
|
||||||
#[error("Orphaned tag '{tag}' - {context}")]
|
#[error("Orphaned tag '{tag}' - {context}")]
|
||||||
OrphanedTag {
|
OrphanedTag {
|
||||||
tag: String,
|
tag: String,
|
||||||
context: String,
|
context: String,
|
||||||
span_start: u32,
|
span: Span,
|
||||||
span_length: u32,
|
|
||||||
},
|
},
|
||||||
#[error("endblock '{name}' does not match any open block")]
|
#[error("endblock '{name}' does not match any open block")]
|
||||||
UnmatchedBlockName {
|
UnmatchedBlockName { name: String, span: Span },
|
||||||
name: String,
|
|
||||||
span_start: u32,
|
|
||||||
span_length: u32,
|
|
||||||
},
|
|
||||||
#[error("Tag '{tag}' requires at least {min} argument{}", if *.min == 1 { "" } else { "s" })]
|
#[error("Tag '{tag}' requires at least {min} argument{}", if *.min == 1 { "" } else { "s" })]
|
||||||
MissingRequiredArguments {
|
MissingRequiredArguments { tag: String, min: usize, span: Span },
|
||||||
tag: String,
|
|
||||||
min: usize,
|
|
||||||
span_start: u32,
|
|
||||||
span_length: u32,
|
|
||||||
},
|
|
||||||
#[error("Tag '{tag}' accepts at most {max} argument{}", if *.max == 1 { "" } else { "s" })]
|
#[error("Tag '{tag}' accepts at most {max} argument{}", if *.max == 1 { "" } else { "s" })]
|
||||||
TooManyArguments {
|
TooManyArguments { tag: String, max: usize, span: Span },
|
||||||
tag: String,
|
|
||||||
max: usize,
|
|
||||||
span_start: u32,
|
|
||||||
span_length: u32,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AstError {
|
impl AstError {
|
||||||
|
@ -210,46 +187,16 @@ impl AstError {
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn span(&self) -> Option<(u32, u32)> {
|
pub fn span(&self) -> Option<(u32, u32)> {
|
||||||
match self {
|
match self {
|
||||||
AstError::UnbalancedStructure {
|
AstError::UnbalancedStructure { opening_span, .. } => {
|
||||||
opening_span_start,
|
Some((opening_span.start, opening_span.length))
|
||||||
opening_span_length,
|
|
||||||
..
|
|
||||||
} => Some((*opening_span_start, *opening_span_length)),
|
|
||||||
AstError::InvalidTagStructure {
|
|
||||||
span_start,
|
|
||||||
span_length,
|
|
||||||
..
|
|
||||||
}
|
}
|
||||||
| AstError::InvalidNode {
|
AstError::InvalidTagStructure { span, .. }
|
||||||
span_start,
|
| AstError::InvalidNode { span, .. }
|
||||||
span_length,
|
| AstError::UnclosedTag { span, .. }
|
||||||
..
|
| AstError::OrphanedTag { span, .. }
|
||||||
}
|
| AstError::UnmatchedBlockName { span, .. }
|
||||||
| AstError::UnclosedTag {
|
| AstError::MissingRequiredArguments { span, .. }
|
||||||
span_start,
|
| AstError::TooManyArguments { span, .. } => Some((span.start, span.length)),
|
||||||
span_length,
|
|
||||||
..
|
|
||||||
}
|
|
||||||
| AstError::OrphanedTag {
|
|
||||||
span_start,
|
|
||||||
span_length,
|
|
||||||
..
|
|
||||||
}
|
|
||||||
| AstError::UnmatchedBlockName {
|
|
||||||
span_start,
|
|
||||||
span_length,
|
|
||||||
..
|
|
||||||
}
|
|
||||||
| AstError::MissingRequiredArguments {
|
|
||||||
span_start,
|
|
||||||
span_length,
|
|
||||||
..
|
|
||||||
}
|
|
||||||
| AstError::TooManyArguments {
|
|
||||||
span_start,
|
|
||||||
span_length,
|
|
||||||
..
|
|
||||||
} => Some((*span_start, *span_length)),
|
|
||||||
AstError::EmptyAst => None,
|
AstError::EmptyAst => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -163,8 +163,8 @@ fn accumulate_error(db: &dyn Db, error: &TemplateError, line_offsets: &LineOffse
|
||||||
let range = error
|
let range = error
|
||||||
.span()
|
.span()
|
||||||
.map(|(start, length)| {
|
.map(|(start, length)| {
|
||||||
let span = crate::ast::Span::new(db, start, length);
|
let span = crate::ast::Span::new(start, length);
|
||||||
span.to_lsp_range(db, line_offsets)
|
span.to_lsp_range(line_offsets)
|
||||||
})
|
})
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
|
|
@ -101,7 +101,7 @@ impl<'db> Parser<'db> {
|
||||||
|
|
||||||
Ok(Node::Comment(CommentNode {
|
Ok(Node::Comment(CommentNode {
|
||||||
content: token.content(),
|
content: token.content(),
|
||||||
span: Span::from_token(self.db, &token),
|
span: Span::from_token(&token),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,7 +116,7 @@ impl<'db> Parser<'db> {
|
||||||
let name_str = args.first().ok_or(ParserError::EmptyTag)?.clone();
|
let name_str = args.first().ok_or(ParserError::EmptyTag)?.clone();
|
||||||
let name = TagName::new(self.db, name_str); // Intern the tag name
|
let name = TagName::new(self.db, name_str); // Intern the tag name
|
||||||
let bits = args.into_iter().skip(1).collect();
|
let bits = args.into_iter().skip(1).collect();
|
||||||
let span = Span::from_token(self.db, &token);
|
let span = Span::from_token(&token);
|
||||||
|
|
||||||
Ok(Node::Tag(TagNode { name, bits, span }))
|
Ok(Node::Tag(TagNode { name, bits, span }))
|
||||||
}
|
}
|
||||||
|
@ -137,7 +137,7 @@ impl<'db> Parser<'db> {
|
||||||
.skip(1)
|
.skip(1)
|
||||||
.map(|s| FilterName::new(self.db, s.trim().to_string())) // Intern filter names
|
.map(|s| FilterName::new(self.db, s.trim().to_string())) // Intern filter names
|
||||||
.collect();
|
.collect();
|
||||||
let span = Span::from_token(self.db, &token);
|
let span = Span::from_token(&token);
|
||||||
|
|
||||||
Ok(Node::Variable(VariableNode { var, filters, span }))
|
Ok(Node::Variable(VariableNode { var, filters, span }))
|
||||||
}
|
}
|
||||||
|
@ -175,7 +175,7 @@ impl<'db> Parser<'db> {
|
||||||
let offset = u32::try_from(text.find(content.as_str()).unwrap_or(0))
|
let offset = u32::try_from(text.find(content.as_str()).unwrap_or(0))
|
||||||
.expect("Offset should fit in u32");
|
.expect("Offset should fit in u32");
|
||||||
let length = u32::try_from(content.len()).expect("Content length should fit in u32");
|
let length = u32::try_from(content.len()).expect("Content length should fit in u32");
|
||||||
let span = Span::new(self.db, start + offset, length);
|
let span = Span::new(start + offset, length);
|
||||||
|
|
||||||
Ok(Node::Text(TextNode { content, span }))
|
Ok(Node::Text(TextNode { content, span }))
|
||||||
}
|
}
|
||||||
|
@ -404,20 +404,20 @@ mod tests {
|
||||||
Node::Tag(TagNode { name, bits, span }) => TestNode::Tag {
|
Node::Tag(TagNode { name, bits, span }) => TestNode::Tag {
|
||||||
name: name.text(db).to_string(),
|
name: name.text(db).to_string(),
|
||||||
bits: bits.clone(),
|
bits: bits.clone(),
|
||||||
span: (span.start(db), span.length(db)),
|
span: (span.start, span.length),
|
||||||
},
|
},
|
||||||
Node::Comment(CommentNode { content, span }) => TestNode::Comment {
|
Node::Comment(CommentNode { content, span }) => TestNode::Comment {
|
||||||
content: content.clone(),
|
content: content.clone(),
|
||||||
span: (span.start(db), span.length(db)),
|
span: (span.start, span.length),
|
||||||
},
|
},
|
||||||
Node::Text(TextNode { content, span }) => TestNode::Text {
|
Node::Text(TextNode { content, span }) => TestNode::Text {
|
||||||
content: content.clone(),
|
content: content.clone(),
|
||||||
span: (span.start(db), span.length(db)),
|
span: (span.start, span.length),
|
||||||
},
|
},
|
||||||
Node::Variable(VariableNode { var, filters, span }) => TestNode::Variable {
|
Node::Variable(VariableNode { var, filters, span }) => TestNode::Variable {
|
||||||
var: var.text(db).to_string(),
|
var: var.text(db).to_string(),
|
||||||
filters: filters.iter().map(|f| f.text(db).to_string()).collect(),
|
filters: filters.iter().map(|f| f.text(db).to_string()).collect(),
|
||||||
span: (span.start(db), span.length(db)),
|
span: (span.start, span.length),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,8 +92,7 @@ impl<'db> TagValidator<'db> {
|
||||||
while let Some(tag) = self.stack.pop() {
|
while let Some(tag) = self.stack.pop() {
|
||||||
self.errors.push(AstError::UnclosedTag {
|
self.errors.push(AstError::UnclosedTag {
|
||||||
tag: tag.name.text(self.db),
|
tag: tag.name.text(self.db),
|
||||||
span_start: tag.span.start(self.db),
|
span: tag.span,
|
||||||
span_length: tag.span.length(self.db),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,7 +103,7 @@ impl<'db> TagValidator<'db> {
|
||||||
&mut self,
|
&mut self,
|
||||||
name: &str,
|
name: &str,
|
||||||
bits: &[String],
|
bits: &[String],
|
||||||
span: Span<'db>,
|
span: Span,
|
||||||
arg_spec: Option<&ArgSpec>,
|
arg_spec: Option<&ArgSpec>,
|
||||||
) {
|
) {
|
||||||
let Some(arg_spec) = arg_spec else {
|
let Some(arg_spec) = arg_spec else {
|
||||||
|
@ -116,8 +115,7 @@ impl<'db> TagValidator<'db> {
|
||||||
self.errors.push(AstError::MissingRequiredArguments {
|
self.errors.push(AstError::MissingRequiredArguments {
|
||||||
tag: name.to_string(),
|
tag: name.to_string(),
|
||||||
min,
|
min,
|
||||||
span_start: span.start(self.db),
|
span,
|
||||||
span_length: span.length(self.db),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -127,14 +125,13 @@ impl<'db> TagValidator<'db> {
|
||||||
self.errors.push(AstError::TooManyArguments {
|
self.errors.push(AstError::TooManyArguments {
|
||||||
tag: name.to_string(),
|
tag: name.to_string(),
|
||||||
max,
|
max,
|
||||||
span_start: span.start(self.db),
|
span,
|
||||||
span_length: span.length(self.db),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_intermediate(&mut self, name: &str, span: Span<'db>) {
|
fn handle_intermediate(&mut self, name: &str, span: Span) {
|
||||||
// Check if this intermediate tag has the required parent
|
// Check if this intermediate tag has the required parent
|
||||||
let parent_tags = self.db.tag_specs().get_parent_tags_for_intermediate(name);
|
let parent_tags = self.db.tag_specs().get_parent_tags_for_intermediate(name);
|
||||||
if parent_tags.is_empty() {
|
if parent_tags.is_empty() {
|
||||||
|
@ -159,13 +156,12 @@ impl<'db> TagValidator<'db> {
|
||||||
self.errors.push(AstError::OrphanedTag {
|
self.errors.push(AstError::OrphanedTag {
|
||||||
tag: name.to_string(),
|
tag: name.to_string(),
|
||||||
context,
|
context,
|
||||||
span_start: span.start(self.db),
|
span,
|
||||||
span_length: span.length(self.db),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_closer(&mut self, name: TagName<'db>, bits: &[String], span: Span<'db>) {
|
fn handle_closer(&mut self, name: TagName<'db>, bits: &[String], span: Span) {
|
||||||
let name_str = name.text(self.db);
|
let name_str = name.text(self.db);
|
||||||
|
|
||||||
if self.stack.is_empty() {
|
if self.stack.is_empty() {
|
||||||
|
@ -173,10 +169,8 @@ impl<'db> TagValidator<'db> {
|
||||||
self.errors.push(AstError::UnbalancedStructure {
|
self.errors.push(AstError::UnbalancedStructure {
|
||||||
opening_tag: name_str.to_string(),
|
opening_tag: name_str.to_string(),
|
||||||
expected_closing: String::new(),
|
expected_closing: String::new(),
|
||||||
opening_span_start: span.start(self.db),
|
opening_span: span,
|
||||||
opening_span_length: span.length(self.db),
|
closing_span: None,
|
||||||
closing_span_start: None,
|
|
||||||
closing_span_length: None,
|
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -188,10 +182,8 @@ impl<'db> TagValidator<'db> {
|
||||||
self.errors.push(AstError::UnbalancedStructure {
|
self.errors.push(AstError::UnbalancedStructure {
|
||||||
opening_tag: name_str.to_string(),
|
opening_tag: name_str.to_string(),
|
||||||
expected_closing: String::new(),
|
expected_closing: String::new(),
|
||||||
opening_span_start: span.start(self.db),
|
opening_span: span,
|
||||||
opening_span_length: span.length(self.db),
|
closing_span: None,
|
||||||
closing_span_start: None,
|
|
||||||
closing_span_length: None,
|
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
@ -234,8 +226,7 @@ impl<'db> TagValidator<'db> {
|
||||||
// Report the mismatch
|
// Report the mismatch
|
||||||
self.errors.push(AstError::UnmatchedBlockName {
|
self.errors.push(AstError::UnmatchedBlockName {
|
||||||
name: bits[0].clone(),
|
name: bits[0].clone(),
|
||||||
span_start: span.start(self.db),
|
span,
|
||||||
span_length: span.length(self.db),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Find the nearest block to close (and report it as unclosed)
|
// Find the nearest block to close (and report it as unclosed)
|
||||||
|
@ -249,8 +240,7 @@ impl<'db> TagValidator<'db> {
|
||||||
// Report that we're closing the wrong block
|
// Report that we're closing the wrong block
|
||||||
self.errors.push(AstError::UnclosedTag {
|
self.errors.push(AstError::UnclosedTag {
|
||||||
tag: nearest_block.name.text(self.db),
|
tag: nearest_block.name.text(self.db),
|
||||||
span_start: nearest_block.span.start(self.db),
|
span: nearest_block.span,
|
||||||
span_length: nearest_block.span.length(self.db),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Pop everything after as unclosed
|
// Pop everything after as unclosed
|
||||||
|
@ -264,10 +254,8 @@ impl<'db> TagValidator<'db> {
|
||||||
self.errors.push(AstError::UnbalancedStructure {
|
self.errors.push(AstError::UnbalancedStructure {
|
||||||
opening_tag: opener_name,
|
opening_tag: opener_name,
|
||||||
expected_closing: name_str.to_string(),
|
expected_closing: name_str.to_string(),
|
||||||
opening_span_start: span.start(self.db),
|
opening_span: span,
|
||||||
opening_span_length: span.length(self.db),
|
closing_span: None,
|
||||||
closing_span_start: None,
|
|
||||||
closing_span_length: None,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -277,8 +265,7 @@ impl<'db> TagValidator<'db> {
|
||||||
if let Some(unclosed) = self.stack.pop() {
|
if let Some(unclosed) = self.stack.pop() {
|
||||||
self.errors.push(AstError::UnclosedTag {
|
self.errors.push(AstError::UnclosedTag {
|
||||||
tag: unclosed.name.text(self.db),
|
tag: unclosed.name.text(self.db),
|
||||||
span_start: unclosed.span.start(self.db),
|
span: unclosed.span,
|
||||||
span_length: unclosed.span.length(self.db),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue