11use serde:: Serialize ;
22use thiserror:: Error ;
33
4+ use crate :: db:: Db as TemplateDb ;
45use crate :: tokens:: Token ;
56
67#[ salsa:: tracked( debug) ]
@@ -56,43 +57,78 @@ impl Default for LineOffsets {
5657
5758#[ derive( Clone , Debug , PartialEq , Eq , salsa:: Update ) ]
5859pub enum Node < ' db > {
59- Tag ( TagNode < ' db > ) ,
60- Comment ( CommentNode ) ,
61- Text ( TextNode ) ,
62- Variable ( VariableNode < ' db > ) ,
60+ Tag {
61+ name : TagName < ' db > ,
62+ bits : Vec < String > ,
63+ span : Span ,
64+ } ,
65+ Comment {
66+ content : String ,
67+ span : Span ,
68+ } ,
69+ Text {
70+ span : Span ,
71+ } ,
72+ Variable {
73+ var : VariableName < ' db > ,
74+ filters : Vec < FilterName < ' db > > ,
75+ span : Span ,
76+ } ,
6377}
6478
65- #[ derive( Debug , Clone , PartialEq , Eq , salsa:: Update ) ]
66- pub struct TagNode < ' db > {
67- pub name : TagName < ' db > ,
68- pub bits : Vec < String > ,
69- pub span : Span ,
79+ impl < ' db > Node < ' db > {
80+ #[ must_use]
81+ pub fn span ( & self ) -> Span {
82+ match self {
83+ Node :: Tag { span, .. }
84+ | Node :: Variable { span, .. }
85+ | Node :: Comment { span, .. }
86+ | Node :: Text { span } => * span,
87+ }
88+ }
89+
90+ #[ must_use]
91+ pub fn full_span ( & self ) -> Span {
92+ match self {
93+ // account for delimiters
94+ Node :: Variable { span, .. } | Node :: Comment { span, .. } | Node :: Tag { span, .. } => {
95+ Span {
96+ start : span. start . saturating_sub ( 3 ) ,
97+ length : span. length + 6 ,
98+ }
99+ }
100+ Node :: Text { span } => * span,
101+ }
102+ }
103+
104+ pub fn identifier_span ( & self , db : & ' db dyn TemplateDb ) -> Option < Span > {
105+ match self {
106+ Node :: Tag { name, span, .. } => {
107+ // Just the tag name (e.g., "if" in "{% if user.is_authenticated %}")
108+ let name_len = name. text ( db) . len ( ) ;
109+ Some ( Span {
110+ start : span. start ,
111+ length : u32:: try_from ( name_len) . unwrap_or ( 0 ) ,
112+ } )
113+ }
114+ Node :: Variable { var, span, .. } => {
115+ // Just the variable name (e.g., "user" in "{{ user.name|title }}")
116+ let var_len = var. text ( db) . len ( ) ;
117+ Some ( Span {
118+ start : span. start ,
119+ length : u32:: try_from ( var_len) . unwrap_or ( 0 ) ,
120+ } )
121+ }
122+ Node :: Comment { .. } | Node :: Text { .. } => None ,
123+ }
124+ }
70125}
71126
72127#[ salsa:: interned( debug) ]
73128pub struct TagName < ' db > {
74129 pub text : String ,
75130}
76131
77- #[ derive( Debug , Clone , PartialEq , Eq , salsa:: Update ) ]
78- pub struct CommentNode {
79- pub content : String ,
80- pub span : Span ,
81- }
82-
83- #[ derive( Debug , Clone , PartialEq , Eq , salsa:: Update ) ]
84- pub struct TextNode {
85- pub content : String ,
86- pub span : Span ,
87- }
88-
89- #[ derive( Debug , Clone , PartialEq , Eq , salsa:: Update ) ]
90- pub struct VariableNode < ' db > {
91- pub var : VariableName < ' db > ,
92- pub filters : Vec < FilterName < ' db > > ,
93- pub span : Span ,
94- }
95-
96132#[ salsa:: interned( debug) ]
97133pub struct VariableName < ' db > {
98134 pub text : String ,
@@ -116,10 +152,10 @@ impl Span {
116152 }
117153
118154 #[ must_use]
119- pub fn from_token ( token : & Token ) -> Self {
155+ pub fn from_token ( token : & Token < ' _ > , db : & dyn TemplateDb ) -> Self {
120156 let start = token. start ( ) . unwrap_or ( 0 ) ;
121- let length = u32 :: try_from ( token. lexeme ( ) . len ( ) ) . unwrap_or ( 0 ) ;
122- Self { start, length }
157+ let length = token. length ( db ) ;
158+ Span :: new ( start, length)
123159 }
124160
125161 #[ must_use]
0 commit comments