mirror of
https://github.com/joshuadavidthomas/django-language-server.git
synced 2025-09-11 21:06:31 +00:00
add more
This commit is contained in:
parent
a0915f4206
commit
3ebf698a07
3 changed files with 83 additions and 15 deletions
|
@ -57,6 +57,20 @@ pub struct Span {
|
||||||
length: u16,
|
length: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Span {
|
||||||
|
pub fn new(start: u32, length: u16) -> Self {
|
||||||
|
Self { start, length }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn start(&self) -> &u32 {
|
||||||
|
&self.start
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn length(&self) -> &u16 {
|
||||||
|
&self.length
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize)]
|
#[derive(Clone, Debug, Serialize)]
|
||||||
pub enum Node {
|
pub enum Node {
|
||||||
Text {
|
Text {
|
||||||
|
@ -97,8 +111,12 @@ pub struct DjangoFilter {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DjangoFilter {
|
impl DjangoFilter {
|
||||||
pub fn new(name: String, arguments: Vec<String>) -> Self {
|
pub fn new(name: String, arguments: Vec<String>, span: Span) -> Self {
|
||||||
Self { name, arguments }
|
Self {
|
||||||
|
name,
|
||||||
|
arguments,
|
||||||
|
span,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::ast::{Ast, AstError, BlockType, DjangoFilter, Node};
|
use crate::ast::{Ast, AstError, BlockType, DjangoFilter, Node, Span};
|
||||||
use crate::tagspecs::TagSpec;
|
use crate::tagspecs::TagSpec;
|
||||||
use crate::tokens::{Token, TokenStream, TokenType};
|
use crate::tokens::{Token, TokenStream, TokenType};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
@ -101,18 +101,21 @@ impl Parser {
|
||||||
start: &str,
|
start: &str,
|
||||||
end: Option<&str>,
|
end: Option<&str>,
|
||||||
) -> Result<Node, ParserError> {
|
) -> Result<Node, ParserError> {
|
||||||
match start {
|
let start_token = self.peek_previous()?;
|
||||||
"{#" => Ok(Node::Comment(content.to_string())),
|
let start_pos = start_token.start().unwrap_or(0) as u32;
|
||||||
_ => Ok(Node::Text(format!(
|
let total_length = content.len() + start.len() + end.map_or(0, |e| e.len());
|
||||||
"{}{}{}",
|
let span = Span::new(start_pos, total_length as u16);
|
||||||
start,
|
Ok(Node::Comment {
|
||||||
content,
|
content: content.to_string(),
|
||||||
end.unwrap_or("")
|
span,
|
||||||
))),
|
})
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_django_block(&mut self, s: &str) -> Result<Node, ParserError> {
|
fn parse_django_block(&mut self, s: &str) -> Result<Node, ParserError> {
|
||||||
|
let start_token = self.peek_previous()?;
|
||||||
|
let start_pos = start_token.start().unwrap_or(0) as u32;
|
||||||
|
let tag_span = Span::new(start_pos, s.len() as u16);
|
||||||
|
|
||||||
let bits: Vec<String> = s.split_whitespace().map(String::from).collect();
|
let bits: Vec<String> = s.split_whitespace().map(String::from).collect();
|
||||||
let tag_name = bits.first().ok_or(AstError::EmptyTag)?.clone();
|
let tag_name = bits.first().ok_or(AstError::EmptyTag)?.clone();
|
||||||
|
|
||||||
|
@ -135,6 +138,7 @@ impl Parser {
|
||||||
let mut children = Vec::new();
|
let mut children = Vec::new();
|
||||||
let mut current_branch: Option<(String, Vec<String>, Vec<Node>)> = None;
|
let mut current_branch: Option<(String, Vec<String>, Vec<Node>)> = None;
|
||||||
let mut found_closing_tag = false;
|
let mut found_closing_tag = false;
|
||||||
|
let mut total_length = s.len();
|
||||||
|
|
||||||
while !self.is_at_end() {
|
while !self.is_at_end() {
|
||||||
match self.next_node() {
|
match self.next_node() {
|
||||||
|
@ -151,18 +155,34 @@ impl Parser {
|
||||||
if spec.closing.as_deref() == Some(&tag) {
|
if spec.closing.as_deref() == Some(&tag) {
|
||||||
// If we have a current branch, add it to children
|
// If we have a current branch, add it to children
|
||||||
if let Some((name, bits, branch_children)) = current_branch {
|
if let Some((name, bits, branch_children)) = current_branch {
|
||||||
|
let branch_span = Span::new(start_pos, total_length as u16);
|
||||||
children.push(Node::Block {
|
children.push(Node::Block {
|
||||||
block_type: BlockType::Branch,
|
block_type: BlockType::Branch,
|
||||||
name,
|
name,
|
||||||
bits,
|
bits,
|
||||||
children: Some(branch_children),
|
children: Some(branch_children),
|
||||||
|
span: branch_span,
|
||||||
|
tag_span: tag_span.clone(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
let closing_token = self.peek_previous()?;
|
||||||
|
let closing_content = match closing_token.token_type() {
|
||||||
|
TokenType::DjangoBlock(content) => content.len(),
|
||||||
|
_ => 0,
|
||||||
|
};
|
||||||
|
total_length = (closing_token.start().unwrap_or(0) + closing_content)
|
||||||
|
as usize
|
||||||
|
- start_pos as usize;
|
||||||
children.push(Node::Block {
|
children.push(Node::Block {
|
||||||
block_type: BlockType::Closing,
|
block_type: BlockType::Closing,
|
||||||
name: tag,
|
name: tag,
|
||||||
bits: vec![],
|
bits: vec![],
|
||||||
children: None,
|
children: None,
|
||||||
|
span: Span::new(
|
||||||
|
closing_token.start().unwrap_or(0) as u32,
|
||||||
|
closing_content as u16,
|
||||||
|
),
|
||||||
|
tag_span: tag_span.clone(),
|
||||||
});
|
});
|
||||||
found_closing_tag = true;
|
found_closing_tag = true;
|
||||||
break;
|
break;
|
||||||
|
@ -172,11 +192,14 @@ impl Parser {
|
||||||
if let Some(branch) = branches.iter().find(|i| i.name == tag) {
|
if let Some(branch) = branches.iter().find(|i| i.name == tag) {
|
||||||
// If we have a current branch, add it to children
|
// If we have a current branch, add it to children
|
||||||
if let Some((name, bits, branch_children)) = current_branch {
|
if let Some((name, bits, branch_children)) = current_branch {
|
||||||
|
let branch_span = Span::new(start_pos, total_length as u16);
|
||||||
children.push(Node::Block {
|
children.push(Node::Block {
|
||||||
block_type: BlockType::Branch,
|
block_type: BlockType::Branch,
|
||||||
name,
|
name,
|
||||||
bits,
|
bits,
|
||||||
children: Some(branch_children),
|
children: Some(branch_children),
|
||||||
|
span: branch_span,
|
||||||
|
tag_span: tag_span.clone(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// Create new branch node
|
// Create new branch node
|
||||||
|
@ -203,6 +226,8 @@ impl Parser {
|
||||||
name: tag_name.clone(),
|
name: tag_name.clone(),
|
||||||
bits: bits.clone(),
|
bits: bits.clone(),
|
||||||
children: Some(children.clone()),
|
children: Some(children.clone()),
|
||||||
|
span: Span::new(start_pos, total_length as u16),
|
||||||
|
tag_span: tag_span.clone(),
|
||||||
};
|
};
|
||||||
return Err(ParserError::Ast(AstError::UnexpectedTag(tag), Some(node)));
|
return Err(ParserError::Ast(AstError::UnexpectedTag(tag), Some(node)));
|
||||||
}
|
}
|
||||||
|
@ -213,11 +238,15 @@ impl Parser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let span = Span::new(start_pos, total_length as u16);
|
||||||
|
|
||||||
let node = Node::Block {
|
let node = Node::Block {
|
||||||
block_type: BlockType::Standard,
|
block_type: BlockType::Standard,
|
||||||
name: tag_name.clone(),
|
name: tag_name.clone(),
|
||||||
bits,
|
bits,
|
||||||
children: Some(children),
|
children: Some(children),
|
||||||
|
span,
|
||||||
|
tag_span,
|
||||||
};
|
};
|
||||||
|
|
||||||
if !found_closing_tag {
|
if !found_closing_tag {
|
||||||
|
@ -231,8 +260,12 @@ impl Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_django_variable(&mut self, s: &str) -> Result<Node, ParserError> {
|
fn parse_django_variable(&mut self, s: &str) -> Result<Node, ParserError> {
|
||||||
let parts: Vec<&str> = s.split('|').collect();
|
let start_token = self.peek_previous()?;
|
||||||
|
let start_pos = start_token.start().unwrap_or(0) as u32;
|
||||||
|
let length = s.len() as u16;
|
||||||
|
let span = Span::new(start_pos, length);
|
||||||
|
|
||||||
|
let parts: Vec<&str> = s.split('|').collect();
|
||||||
let bits: Vec<String> = parts[0].trim().split('.').map(String::from).collect();
|
let bits: Vec<String> = parts[0].trim().split('.').map(String::from).collect();
|
||||||
|
|
||||||
let filters: Vec<DjangoFilter> = parts[1..]
|
let filters: Vec<DjangoFilter> = parts[1..]
|
||||||
|
@ -255,11 +288,18 @@ impl Parser {
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
Ok(Node::Variable { bits, filters })
|
Ok(Node::Variable {
|
||||||
|
bits,
|
||||||
|
filters,
|
||||||
|
span,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_text(&mut self) -> Result<Node, ParserError> {
|
fn parse_text(&mut self) -> Result<Node, ParserError> {
|
||||||
|
let start_token = self.peek()?;
|
||||||
|
let start_pos = start_token.start().unwrap_or(0) as u32;
|
||||||
let mut text = String::new();
|
let mut text = String::new();
|
||||||
|
|
||||||
while let Ok(token) = self.peek() {
|
while let Ok(token) = self.peek() {
|
||||||
match token.token_type() {
|
match token.token_type() {
|
||||||
TokenType::DjangoBlock(_)
|
TokenType::DjangoBlock(_)
|
||||||
|
@ -290,7 +330,13 @@ impl Parser {
|
||||||
TokenType::Eof => break,
|
TokenType::Eof => break,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(Node::Text(text))
|
|
||||||
|
let length = text.len() as u16;
|
||||||
|
let span = Span::new(start_pos, length);
|
||||||
|
Ok(Node::Text {
|
||||||
|
content: text,
|
||||||
|
span,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn peek(&self) -> Result<Token, ParserError> {
|
fn peek(&self) -> Result<Token, ParserError> {
|
||||||
|
|
|
@ -119,6 +119,10 @@ impl Token {
|
||||||
&self.token_type
|
&self.token_type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn start(&self) -> &Option<usize> {
|
||||||
|
&self.start
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_token_type(&self, token_type: &TokenType) -> bool {
|
pub fn is_token_type(&self, token_type: &TokenType) -> bool {
|
||||||
&self.token_type == token_type
|
&self.token_type == token_type
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue