Skip to content

Commit c51d462

Browse files
fix errors
1 parent f22e776 commit c51d462

File tree

3 files changed

+69
-51
lines changed

3 files changed

+69
-51
lines changed

crates/djls-template-ast/src/ast.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1+
use crate::tokens::{Token, TokenType};
12
use serde::Serialize;
23
use thiserror::Error;
34

4-
use crate::tokens::{Token, TokenType};
5-
65
#[derive(Clone, Debug, Default, Serialize)]
76
pub struct Ast {
87
nodes: Vec<Node>,
@@ -271,13 +270,15 @@ mod tests {
271270

272271
mod spans_and_positions {
273272
use super::*;
273+
use crate::tagspecs::TagSpecs;
274274

275275
#[test]
276276
fn test_variable_spans() {
277277
let template = "Hello\n{{ user.name }}\nWorld";
278278
let tokens = Lexer::new(template).tokenize().unwrap();
279279
println!("Tokens: {:#?}", tokens); // Add debug print
280-
let mut parser = Parser::new(tokens);
280+
let tags = TagSpecs::load_builtin_specs().unwrap();
281+
let mut parser = Parser::new(tokens, tags);
281282
let (ast, errors) = parser.parse().unwrap();
282283
assert!(errors.is_empty());
283284

@@ -336,7 +337,8 @@ mod tests {
336337
fn test_multiline_template() {
337338
let template = "{% if user.active %}\n Welcome!\n{% endif %}";
338339
let tokens = Lexer::new(template).tokenize().unwrap();
339-
let mut parser = Parser::new(tokens);
340+
let tags = TagSpecs::load_builtin_specs().unwrap();
341+
let mut parser = Parser::new(tokens, tags);
340342
let (ast, errors) = parser.parse().unwrap();
341343
assert!(errors.is_empty());
342344

crates/djls-template-ast/src/lib.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,8 @@ mod tagspecs;
55
mod tokens;
66

77
pub use ast::Ast;
8-
pub use parser::{Parser, ParserError};
98
use lexer::Lexer;
10-
use parser::Parser;
9+
pub use parser::{Parser, ParserError};
1110
use tagspecs::TagSpecs;
1211

1312
/// Parses a Django template and returns the AST and any parsing errors.
@@ -21,16 +20,13 @@ pub fn parse_template(
2120
source: &str,
2221
tag_specs: Option<&TagSpecs>,
2322
) -> Result<(Ast, Vec<ParserError>), ParserError> {
24-
// Tokenize the source using the Lexer
2523
let tokens = Lexer::new(source).tokenize()?;
2624

27-
// Use provided TagSpecs or load builtin ones
2825
let tag_specs = match tag_specs {
2926
Some(specs) => specs.clone(),
3027
None => TagSpecs::load_builtin_specs()?,
3128
};
3229

33-
// Parse the tokens into an AST using the Parser
3430
let mut parser = Parser::new(tokens, tag_specs);
3531
parser.parse()
3632
}

crates/djls-template-ast/src/parser.rs

Lines changed: 62 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::ast::{Ast, AstError, Block, DjangoFilter, LineOffsets, Node, Span, Tag};
2+
use crate::lexer::LexerError;
23
use crate::tagspecs::{TagSpec, TagSpecs, TagType};
34
use crate::tokens::{Token, TokenStream, TokenType};
45
use thiserror::Error;
@@ -7,26 +8,16 @@ pub struct Parser {
78
tokens: TokenStream,
89
current: usize,
910
errors: Vec<ParserError>,
10-
tag_specs: TagSpecs, // Add TagSpecs field
11+
tags: TagSpecs,
1112
}
1213

1314
impl Parser {
14-
// Modify the constructor to accept TagSpecs
15-
pub fn new(tokens: TokenStream, tag_specs: TagSpecs) -> Self {
16-
Self {
17-
tokens,
18-
current: 0,
19-
errors: Vec::new(),
20-
tag_specs,
21-
}
22-
}
23-
24-
impl Parser {
25-
pub fn new(tokens: TokenStream) -> Self {
15+
pub fn new(tokens: TokenStream, tags: TagSpecs) -> Self {
2616
Self {
2717
tokens,
2818
current: 0,
2919
errors: Vec::new(),
20+
tags,
3021
}
3122
}
3223

@@ -127,11 +118,11 @@ impl Parser {
127118
assignment,
128119
};
129120

130-
let spec = self.tag_specs.get(&tag_name);
121+
let spec = self.tags.get(&tag_name).cloned();
131122

132123
match spec {
133124
Some(spec) => match spec.tag_type {
134-
TagType::Container => self.parse_block_tag(tag, spec),
125+
TagType::Container => self.parse_block_tag(tag, &spec),
135126
TagType::Single => Ok(Node::Block(Block::Single { tag })),
136127
TagType::Inclusion => {
137128
let template_name = tag.bits.get(1).cloned().unwrap_or_default();
@@ -395,6 +386,8 @@ pub enum ParserError {
395386
Other(#[from] anyhow::Error),
396387
#[error("empty tag")]
397388
EmptyTag,
389+
#[error("{0}")]
390+
Lexer(#[from] LexerError),
398391
}
399392

400393
impl ParserError {
@@ -414,7 +407,8 @@ mod tests {
414407
fn test_parse_html_doctype() {
415408
let source = "<!DOCTYPE html>";
416409
let tokens = Lexer::new(source).tokenize().unwrap();
417-
let mut parser = Parser::new(tokens);
410+
let tags = TagSpecs::load_builtin_specs().unwrap();
411+
let mut parser = Parser::new(tokens, tags);
418412
let (ast, errors) = parser.parse().unwrap();
419413
insta::assert_yaml_snapshot!(ast);
420414
assert!(errors.is_empty());
@@ -424,7 +418,8 @@ mod tests {
424418
fn test_parse_html_tag() {
425419
let source = "<div class=\"container\">Hello</div>";
426420
let tokens = Lexer::new(source).tokenize().unwrap();
427-
let mut parser = Parser::new(tokens);
421+
let tags = TagSpecs::load_builtin_specs().unwrap();
422+
let mut parser = Parser::new(tokens, tags);
428423
let (ast, errors) = parser.parse().unwrap();
429424
insta::assert_yaml_snapshot!(ast);
430425
assert!(errors.is_empty());
@@ -434,7 +429,8 @@ mod tests {
434429
fn test_parse_html_void() {
435430
let source = "<input type=\"text\" />";
436431
let tokens = Lexer::new(source).tokenize().unwrap();
437-
let mut parser = Parser::new(tokens);
432+
let tags = TagSpecs::load_builtin_specs().unwrap();
433+
let mut parser = Parser::new(tokens, tags);
438434
let (ast, errors) = parser.parse().unwrap();
439435
insta::assert_yaml_snapshot!(ast);
440436
assert!(errors.is_empty());
@@ -448,7 +444,8 @@ mod tests {
448444
fn test_parse_django_variable() {
449445
let source = "{{ user.name }}";
450446
let tokens = Lexer::new(source).tokenize().unwrap();
451-
let mut parser = Parser::new(tokens);
447+
let tags = TagSpecs::load_builtin_specs().unwrap();
448+
let mut parser = Parser::new(tokens, tags);
452449
let (ast, errors) = parser.parse().unwrap();
453450
insta::assert_yaml_snapshot!(ast);
454451
assert!(errors.is_empty());
@@ -458,7 +455,8 @@ mod tests {
458455
fn test_parse_django_variable_with_filter() {
459456
let source = "{{ user.name|title }}";
460457
let tokens = Lexer::new(source).tokenize().unwrap();
461-
let mut parser = Parser::new(tokens);
458+
let tags = TagSpecs::load_builtin_specs().unwrap();
459+
let mut parser = Parser::new(tokens, tags);
462460
let (ast, errors) = parser.parse().unwrap();
463461
insta::assert_yaml_snapshot!(ast);
464462
assert!(errors.is_empty());
@@ -468,7 +466,8 @@ mod tests {
468466
fn test_parse_filter_chains() {
469467
let source = "{{ value|default:'nothing'|title|upper }}";
470468
let tokens = Lexer::new(source).tokenize().unwrap();
471-
let mut parser = Parser::new(tokens);
469+
let tags = TagSpecs::load_builtin_specs().unwrap();
470+
let mut parser = Parser::new(tokens, tags);
472471
let (ast, errors) = parser.parse().unwrap();
473472
insta::assert_yaml_snapshot!(ast);
474473
assert!(errors.is_empty());
@@ -478,7 +477,8 @@ mod tests {
478477
fn test_parse_django_if_block() {
479478
let source = "{% if user.is_authenticated %}Welcome{% endif %}";
480479
let tokens = Lexer::new(source).tokenize().unwrap();
481-
let mut parser = Parser::new(tokens);
480+
let tags = TagSpecs::load_builtin_specs().unwrap();
481+
let mut parser = Parser::new(tokens, tags);
482482
let (ast, errors) = parser.parse().unwrap();
483483
insta::assert_yaml_snapshot!(ast);
484484
assert!(errors.is_empty());
@@ -488,7 +488,8 @@ mod tests {
488488
fn test_parse_django_for_block() {
489489
let source = "{% for item in items %}{{ item }}{% empty %}No items{% endfor %}";
490490
let tokens = Lexer::new(source).tokenize().unwrap();
491-
let mut parser = Parser::new(tokens);
491+
let tags = TagSpecs::load_builtin_specs().unwrap();
492+
let mut parser = Parser::new(tokens, tags);
492493
let (ast, errors) = parser.parse().unwrap();
493494
insta::assert_yaml_snapshot!(ast);
494495
assert!(errors.is_empty());
@@ -498,7 +499,8 @@ mod tests {
498499
fn test_parse_complex_if_elif() {
499500
let source = "{% if x > 0 %}Positive{% elif x < 0 %}Negative{% else %}Zero{% endif %}";
500501
let tokens = Lexer::new(source).tokenize().unwrap();
501-
let mut parser = Parser::new(tokens);
502+
let tags = TagSpecs::load_builtin_specs().unwrap();
503+
let mut parser = Parser::new(tokens, tags);
502504
let (ast, errors) = parser.parse().unwrap();
503505
insta::assert_yaml_snapshot!(ast);
504506
assert!(errors.is_empty());
@@ -508,7 +510,8 @@ mod tests {
508510
fn test_parse_django_tag_assignment() {
509511
let source = "{% url 'view-name' as view %}";
510512
let tokens = Lexer::new(source).tokenize().unwrap();
511-
let mut parser = Parser::new(tokens);
513+
let tags = TagSpecs::load_builtin_specs().unwrap();
514+
let mut parser = Parser::new(tokens, tags);
512515
let (ast, errors) = parser.parse().unwrap();
513516
insta::assert_yaml_snapshot!(ast);
514517
assert!(errors.is_empty());
@@ -519,7 +522,8 @@ mod tests {
519522
let source =
520523
"{% for item in items %}{% if item.active %}{{ item.name }}{% endif %}{% endfor %}";
521524
let tokens = Lexer::new(source).tokenize().unwrap();
522-
let mut parser = Parser::new(tokens);
525+
let tags = TagSpecs::load_builtin_specs().unwrap();
526+
let mut parser = Parser::new(tokens, tags);
523527
let (ast, errors) = parser.parse().unwrap();
524528
insta::assert_yaml_snapshot!(ast);
525529
assert!(errors.is_empty());
@@ -541,7 +545,8 @@ mod tests {
541545
Guest
542546
{% endif %}!";
543547
let tokens = Lexer::new(source).tokenize().unwrap();
544-
let mut parser = Parser::new(tokens);
548+
let tags = TagSpecs::load_builtin_specs().unwrap();
549+
let mut parser = Parser::new(tokens, tags);
545550
let (ast, errors) = parser.parse().unwrap();
546551
insta::assert_yaml_snapshot!(ast);
547552
assert!(errors.is_empty());
@@ -561,7 +566,8 @@ mod tests {
561566
console.log(x);
562567
</script>"#;
563568
let tokens = Lexer::new(source).tokenize().unwrap();
564-
let mut parser = Parser::new(tokens);
569+
let tags = TagSpecs::load_builtin_specs().unwrap();
570+
let mut parser = Parser::new(tokens, tags);
565571
let (ast, errors) = parser.parse().unwrap();
566572
insta::assert_yaml_snapshot!(ast);
567573
assert!(errors.is_empty());
@@ -580,7 +586,8 @@ mod tests {
580586
}
581587
</style>"#;
582588
let tokens = Lexer::new(source).tokenize().unwrap();
583-
let mut parser = Parser::new(tokens);
589+
let tags = TagSpecs::load_builtin_specs().unwrap();
590+
let mut parser = Parser::new(tokens, tags);
584591
let (ast, errors) = parser.parse().unwrap();
585592
insta::assert_yaml_snapshot!(ast);
586593
assert!(errors.is_empty());
@@ -594,7 +601,8 @@ mod tests {
594601
fn test_parse_comments() {
595602
let source = "<!-- HTML comment -->{# Django comment #}";
596603
let tokens = Lexer::new(source).tokenize().unwrap();
597-
let mut parser = Parser::new(tokens);
604+
let tags = TagSpecs::load_builtin_specs().unwrap();
605+
let mut parser = Parser::new(tokens, tags);
598606
let (ast, errors) = parser.parse().unwrap();
599607
insta::assert_yaml_snapshot!(ast);
600608
assert!(errors.is_empty());
@@ -608,7 +616,8 @@ mod tests {
608616
fn test_parse_with_leading_whitespace() {
609617
let source = " hello";
610618
let tokens = Lexer::new(source).tokenize().unwrap();
611-
let mut parser = Parser::new(tokens);
619+
let tags = TagSpecs::load_builtin_specs().unwrap();
620+
let mut parser = Parser::new(tokens, tags);
612621
let (ast, errors) = parser.parse().unwrap();
613622
insta::assert_yaml_snapshot!(ast);
614623
assert!(errors.is_empty());
@@ -618,7 +627,8 @@ mod tests {
618627
fn test_parse_with_leading_whitespace_newline() {
619628
let source = "\n hello";
620629
let tokens = Lexer::new(source).tokenize().unwrap();
621-
let mut parser = Parser::new(tokens);
630+
let tags = TagSpecs::load_builtin_specs().unwrap();
631+
let mut parser = Parser::new(tokens, tags);
622632
let (ast, errors) = parser.parse().unwrap();
623633
insta::assert_yaml_snapshot!(ast);
624634
assert!(errors.is_empty());
@@ -628,7 +638,8 @@ mod tests {
628638
fn test_parse_with_trailing_whitespace() {
629639
let source = "hello ";
630640
let tokens = Lexer::new(source).tokenize().unwrap();
631-
let mut parser = Parser::new(tokens);
641+
let tags = TagSpecs::load_builtin_specs().unwrap();
642+
let mut parser = Parser::new(tokens, tags);
632643
let (ast, errors) = parser.parse().unwrap();
633644
insta::assert_yaml_snapshot!(ast);
634645
assert!(errors.is_empty());
@@ -638,7 +649,8 @@ mod tests {
638649
fn test_parse_with_trailing_whitespace_newline() {
639650
let source = "hello \n";
640651
let tokens = Lexer::new(source).tokenize().unwrap();
641-
let mut parser = Parser::new(tokens);
652+
let tags = TagSpecs::load_builtin_specs().unwrap();
653+
let mut parser = Parser::new(tokens, tags);
642654
let (ast, errors) = parser.parse().unwrap();
643655
insta::assert_yaml_snapshot!(ast);
644656
assert!(errors.is_empty());
@@ -652,7 +664,8 @@ mod tests {
652664
fn test_parse_unclosed_html_tag() {
653665
let source = "<div>";
654666
let tokens = Lexer::new(source).tokenize().unwrap();
655-
let mut parser = Parser::new(tokens);
667+
let tags = TagSpecs::load_builtin_specs().unwrap();
668+
let mut parser = Parser::new(tokens, tags);
656669
let (ast, errors) = parser.parse().unwrap();
657670
insta::assert_yaml_snapshot!(ast);
658671
assert!(errors.is_empty());
@@ -662,7 +675,8 @@ mod tests {
662675
fn test_parse_unclosed_django_if() {
663676
let source = "{% if user.is_authenticated %}Welcome";
664677
let tokens = Lexer::new(source).tokenize().unwrap();
665-
let mut parser = Parser::new(tokens);
678+
let tags = TagSpecs::load_builtin_specs().unwrap();
679+
let mut parser = Parser::new(tokens, tags);
666680
let (ast, errors) = parser.parse().unwrap();
667681
insta::assert_yaml_snapshot!(ast);
668682
assert_eq!(errors.len(), 1);
@@ -675,7 +689,8 @@ mod tests {
675689
fn test_parse_unclosed_django_for() {
676690
let source = "{% for item in items %}{{ item.name }}";
677691
let tokens = Lexer::new(source).tokenize().unwrap();
678-
let mut parser = Parser::new(tokens);
692+
let tags = TagSpecs::load_builtin_specs().unwrap();
693+
let mut parser = Parser::new(tokens, tags);
679694
let (ast, errors) = parser.parse().unwrap();
680695
insta::assert_yaml_snapshot!(ast);
681696
assert_eq!(errors.len(), 1);
@@ -688,7 +703,8 @@ mod tests {
688703
fn test_parse_unclosed_script() {
689704
let source = "<script>console.log('test');";
690705
let tokens = Lexer::new(source).tokenize().unwrap();
691-
let mut parser = Parser::new(tokens);
706+
let tags = TagSpecs::load_builtin_specs().unwrap();
707+
let mut parser = Parser::new(tokens, tags);
692708
let (ast, errors) = parser.parse().unwrap();
693709
insta::assert_yaml_snapshot!(ast);
694710
assert!(errors.is_empty());
@@ -698,7 +714,8 @@ mod tests {
698714
fn test_parse_unclosed_style() {
699715
let source = "<style>body { color: blue; ";
700716
let tokens = Lexer::new(source).tokenize().unwrap();
701-
let mut parser = Parser::new(tokens);
717+
let tags = TagSpecs::load_builtin_specs().unwrap();
718+
let mut parser = Parser::new(tokens, tags);
702719
let (ast, errors) = parser.parse().unwrap();
703720
insta::assert_yaml_snapshot!(ast);
704721
assert!(errors.is_empty());
@@ -719,7 +736,8 @@ mod tests {
719736
<footer>Page Footer</footer>
720737
</div>"#;
721738
let tokens = Lexer::new(source).tokenize().unwrap();
722-
let mut parser = Parser::new(tokens);
739+
let tags = TagSpecs::load_builtin_specs().unwrap();
740+
let mut parser = Parser::new(tokens, tags);
723741
let (ast, errors) = parser.parse().unwrap();
724742
insta::assert_yaml_snapshot!(ast);
725743
assert_eq!(errors.len(), 1);
@@ -765,7 +783,8 @@ mod tests {
765783
</body>
766784
</html>"#;
767785
let tokens = Lexer::new(source).tokenize().unwrap();
768-
let mut parser = Parser::new(tokens);
786+
let tags = TagSpecs::load_builtin_specs().unwrap();
787+
let mut parser = Parser::new(tokens, tags);
769788
let (ast, errors) = parser.parse().unwrap();
770789
insta::assert_yaml_snapshot!(ast);
771790
assert!(errors.is_empty());
@@ -779,7 +798,8 @@ mod tests {
779798
fn test_parser_tracks_line_offsets() {
780799
let source = "line1\nline2";
781800
let tokens = Lexer::new(source).tokenize().unwrap();
782-
let mut parser = Parser::new(tokens);
801+
let tags = TagSpecs::load_builtin_specs().unwrap();
802+
let mut parser = Parser::new(tokens, tags);
783803
let (ast, errors) = parser.parse().unwrap();
784804

785805
let offsets = ast.line_offsets();

0 commit comments

Comments
 (0)