1use oak_core::{Token, TokenType, UniversalTokenRole};
2use serde::{Deserialize, Serialize};
3
4pub type DjangoToken = Token<DjangoSyntaxKind>;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
8pub enum DjangoSyntaxKind {
9 Identifier,
11 Number,
12 String,
13 Whitespace,
14 Newline,
15
16 VariableStart, VariableEnd, TagStart, TagEnd, CommentStart, CommentEnd, If,
26 Elif,
27 Else,
28 Endif,
29 For,
30 Empty,
31 Endfor,
32 Block,
33 Endblock,
34 Extends,
35 Include,
36 Load,
37 With,
38 Endwith,
39 Autoescape,
40 Endautoescape,
41 Csrf,
42 Url,
43 Static,
44 Now,
45 Cycle,
46 Filter,
47 Endfilter,
48 Spaceless,
49 Endspaceless,
50 Verbatim,
51 Endverbatim,
52
53 Pipe, Colon, Dot, Comma, Equal, Plus, Minus, Star, Slash, Percent, EqualEqual, NotEqual, Less, LessEqual, Greater, GreaterEqual, And,
75 Or,
76 Not,
77 In,
78
79 LeftParen, RightParen, LeftBracket, RightBracket, Semicolon, HtmlText,
88 HtmlTag,
89
90 Comment,
92
93 Variable,
95 Tag,
96
97 Root,
99 Error,
100 Eof,
101}
102
103impl DjangoSyntaxKind {
104 pub fn is_keyword(&self) -> bool {
105 matches!(
106 self,
107 Self::If
108 | Self::Elif
109 | Self::Else
110 | Self::Endif
111 | Self::For
112 | Self::Empty
113 | Self::Endfor
114 | Self::Block
115 | Self::Endblock
116 | Self::Extends
117 | Self::Include
118 | Self::Load
119 | Self::With
120 | Self::Endwith
121 | Self::Autoescape
122 | Self::Endautoescape
123 | Self::Csrf
124 | Self::Url
125 | Self::Static
126 | Self::Now
127 | Self::Cycle
128 | Self::Filter
129 | Self::Endfilter
130 | Self::Spaceless
131 | Self::Endspaceless
132 | Self::Verbatim
133 | Self::Endverbatim
134 | Self::And
135 | Self::Or
136 | Self::Not
137 | Self::In
138 )
139 }
140
141 pub fn is_trivia(&self) -> bool {
142 matches!(self, Self::Whitespace | Self::Newline | Self::Comment)
143 }
144}
145
146impl TokenType for DjangoSyntaxKind {
147 type Role = UniversalTokenRole;
148 const END_OF_STREAM: Self = Self::Eof;
149
150 fn role(&self) -> Self::Role {
151 if self.is_keyword() {
152 return UniversalTokenRole::Keyword;
153 }
154
155 match self {
156 Self::Identifier => UniversalTokenRole::Name,
157 Self::Number | Self::String => UniversalTokenRole::Literal,
158 Self::Whitespace | Self::Newline => UniversalTokenRole::Whitespace,
159 Self::Comment => UniversalTokenRole::Comment,
160 Self::VariableStart | Self::VariableEnd | Self::TagStart | Self::TagEnd | Self::CommentStart | Self::CommentEnd => UniversalTokenRole::Punctuation,
161 Self::Pipe | Self::Colon | Self::Dot | Self::Comma | Self::Equal | Self::Plus | Self::Minus | Self::Star | Self::Slash | Self::Percent | Self::EqualEqual | Self::NotEqual | Self::Less | Self::LessEqual | Self::Greater | Self::GreaterEqual => {
162 UniversalTokenRole::Operator
163 }
164 Self::LeftParen | Self::RightParen | Self::LeftBracket | Self::RightBracket | Self::Semicolon => UniversalTokenRole::Punctuation,
165 Self::HtmlText | Self::HtmlTag => UniversalTokenRole::None,
166 Self::Error => UniversalTokenRole::Error,
167 _ => UniversalTokenRole::None,
168 }
169 }
170
171 fn is_ignored(&self) -> bool {
172 matches!(self, Self::Whitespace | Self::Newline | Self::Comment)
173 }
174
175 fn is_comment(&self) -> bool {
176 matches!(self, Self::Comment)
177 }
178
179 fn is_whitespace(&self) -> bool {
180 matches!(self, Self::Whitespace | Self::Newline)
181 }
182}
183
184impl oak_core::ElementType for DjangoSyntaxKind {
185 type Role = oak_core::UniversalElementRole;
186
187 fn role(&self) -> Self::Role {
188 match self {
189 Self::Root => oak_core::UniversalElementRole::Root,
190 Self::Variable | Self::Tag => oak_core::UniversalElementRole::Statement,
191 Self::Error => oak_core::UniversalElementRole::Error,
192 _ => oak_core::UniversalElementRole::None,
193 }
194 }
195
196 fn is_error(&self) -> bool {
197 matches!(self, Self::Error)
198 }
199}