1#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
15#[allow(non_camel_case_types)]
16pub enum SyntaxKind {
17 WHITESPACE = 0,
20 NEWLINE,
22 COMMENT,
24 IDENT,
26 ARGUMENT,
28 DOUBLE_QUOTED_STRING,
30 SINGLE_QUOTED_STRING,
32 VARIABLE,
34 SEMICOLON,
36 L_BRACE,
38 R_BRACE,
40 RAW_CONTENT,
42 ERROR,
44
45 ROOT,
48 DIRECTIVE,
50 BLOCK,
52 BLANK_LINE,
54}
55
56impl SyntaxKind {
57 pub fn is_trivia(self) -> bool {
59 matches!(self, Self::WHITESPACE | Self::NEWLINE | Self::COMMENT)
60 }
61
62 fn to_raw(self) -> u16 {
64 match self {
65 Self::WHITESPACE => 0,
66 Self::NEWLINE => 1,
67 Self::COMMENT => 2,
68 Self::IDENT => 3,
69 Self::ARGUMENT => 4,
70 Self::DOUBLE_QUOTED_STRING => 5,
71 Self::SINGLE_QUOTED_STRING => 6,
72 Self::VARIABLE => 7,
73 Self::SEMICOLON => 8,
74 Self::L_BRACE => 9,
75 Self::R_BRACE => 10,
76 Self::RAW_CONTENT => 11,
77 Self::ERROR => 12,
78 Self::ROOT => 13,
79 Self::DIRECTIVE => 14,
80 Self::BLOCK => 15,
81 Self::BLANK_LINE => 16,
82 }
83 }
84}
85
86impl From<SyntaxKind> for rowan::SyntaxKind {
88 fn from(kind: SyntaxKind) -> Self {
89 Self(kind.to_raw())
90 }
91}
92
93#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
95pub enum NginxLanguage {}
96
97impl SyntaxKind {
98 fn from_raw(raw: u16) -> Self {
102 match raw {
103 0 => Self::WHITESPACE,
104 1 => Self::NEWLINE,
105 2 => Self::COMMENT,
106 3 => Self::IDENT,
107 4 => Self::ARGUMENT,
108 5 => Self::DOUBLE_QUOTED_STRING,
109 6 => Self::SINGLE_QUOTED_STRING,
110 7 => Self::VARIABLE,
111 8 => Self::SEMICOLON,
112 9 => Self::L_BRACE,
113 10 => Self::R_BRACE,
114 11 => Self::RAW_CONTENT,
115 12 => Self::ERROR,
116 13 => Self::ROOT,
117 14 => Self::DIRECTIVE,
118 15 => Self::BLOCK,
119 16 => Self::BLANK_LINE,
120 _ => panic!("invalid SyntaxKind raw value: {raw}"),
121 }
122 }
123}
124
125impl rowan::Language for NginxLanguage {
126 type Kind = SyntaxKind;
127
128 fn kind_from_raw(raw: rowan::SyntaxKind) -> Self::Kind {
129 SyntaxKind::from_raw(raw.0)
130 }
131
132 fn kind_to_raw(kind: Self::Kind) -> rowan::SyntaxKind {
133 kind.into()
134 }
135}
136
137pub type SyntaxNode = rowan::SyntaxNode<NginxLanguage>;
139pub type SyntaxToken = rowan::SyntaxToken<NginxLanguage>;
141pub type SyntaxElement = rowan::SyntaxElement<NginxLanguage>;
143
144#[cfg(test)]
145mod tests {
146 use super::*;
147 use rowan::Language;
148
149 const ALL_KINDS: &[SyntaxKind] = &[
151 SyntaxKind::WHITESPACE,
152 SyntaxKind::NEWLINE,
153 SyntaxKind::COMMENT,
154 SyntaxKind::IDENT,
155 SyntaxKind::ARGUMENT,
156 SyntaxKind::DOUBLE_QUOTED_STRING,
157 SyntaxKind::SINGLE_QUOTED_STRING,
158 SyntaxKind::VARIABLE,
159 SyntaxKind::SEMICOLON,
160 SyntaxKind::L_BRACE,
161 SyntaxKind::R_BRACE,
162 SyntaxKind::RAW_CONTENT,
163 SyntaxKind::ERROR,
164 SyntaxKind::ROOT,
165 SyntaxKind::DIRECTIVE,
166 SyntaxKind::BLOCK,
167 SyntaxKind::BLANK_LINE,
168 ];
169
170 #[test]
171 fn kind_round_trip() {
172 for (raw, &expected) in ALL_KINDS.iter().enumerate() {
173 let kind = SyntaxKind::from_raw(raw as u16);
174 assert_eq!(kind, expected);
175 let rowan_kind: rowan::SyntaxKind = kind.into();
176 assert_eq!(rowan_kind.0, raw as u16);
177 let back = NginxLanguage::kind_from_raw(rowan_kind);
178 assert_eq!(back, kind);
179 }
180 }
181
182 #[test]
183 fn trivia_classification() {
184 assert!(SyntaxKind::WHITESPACE.is_trivia());
185 assert!(SyntaxKind::NEWLINE.is_trivia());
186 assert!(SyntaxKind::COMMENT.is_trivia());
187 assert!(!SyntaxKind::IDENT.is_trivia());
188 assert!(!SyntaxKind::SEMICOLON.is_trivia());
189 }
190}