1use std::ops;
4
5use lsp_types::{
6 Range, SemanticToken, SemanticTokenModifier, SemanticTokenType, SemanticTokens,
7 SemanticTokensEdit,
8};
9
10macro_rules! define_semantic_token_types {
11 (
12 standard {
13 $($standard:ident),*$(,)?
14 }
15 custom {
16 $(($custom:ident, $string:literal) $(=> $fallback:ident)?),*$(,)?
17 }
18
19 ) => {
20 pub(crate) mod types {
21 use super::SemanticTokenType;
22 $(pub(crate) const $standard: SemanticTokenType = SemanticTokenType::$standard;)*
23 $(pub(crate) const $custom: SemanticTokenType = SemanticTokenType::new($string);)*
24 }
25
26 pub(crate) const SUPPORTED_TYPES: &[SemanticTokenType] = &[
27 $(self::types::$standard,)*
28 $(self::types::$custom),*
29 ];
30
31 pub(crate) fn standard_fallback_type(token: SemanticTokenType) -> Option<SemanticTokenType> {
32 use self::types::*;
33 $(
34 if token == $custom {
35 None $(.or(Some(self::types::$fallback)))?
36 } else
37 )*
38 { Some(token )}
39 }
40 };
41}
42
43define_semantic_token_types![
44 standard {
45 COMMENT,
46 DECORATOR,
47 ENUM_MEMBER,
48 ENUM,
49 FUNCTION,
50 INTERFACE,
51 KEYWORD,
52 MACRO,
53 METHOD,
54 NAMESPACE,
55 NUMBER,
56 OPERATOR,
57 PARAMETER,
58 PROPERTY,
59 STRING,
60 STRUCT,
61 TYPE_PARAMETER,
62 VARIABLE,
63 TYPE,
64 }
65
66 custom {
67 (ANGLE, "angle"),
68 (ARITHMETIC, "arithmetic") => OPERATOR,
69 (ATTRIBUTE_BRACKET, "attributeBracket") => DECORATOR,
70 (ATTRIBUTE, "attribute") => DECORATOR,
71 (BITWISE, "bitwise") => OPERATOR,
72 (BOOLEAN, "boolean"),
73 (BRACE, "brace"),
74 (BRACKET, "bracket"),
75 (BUILTIN_ATTRIBUTE, "builtinAttribute") => DECORATOR,
76 (BUILTIN_TYPE, "builtinType") => TYPE,
77 (CHAR, "character") => STRING,
78 (COLON, "colon"),
79 (COMMA, "comma"),
80 (COMPARISON, "comparison") => OPERATOR,
81 (CONST_PARAMETER, "constParameter"),
82 (CONST, "const") => VARIABLE,
83 (DERIVE_HELPER, "deriveHelper") => DECORATOR,
84 (DERIVE, "derive") => DECORATOR,
85 (DOT, "dot"),
86 (ESCAPE_SEQUENCE, "escapeSequence") => STRING,
87 (FORMAT_SPECIFIER, "formatSpecifier") => STRING,
88 (GENERIC, "generic") => TYPE_PARAMETER,
89 (INVALID_ESCAPE_SEQUENCE, "invalidEscapeSequence") => STRING,
90 (LABEL, "label"),
91 (LIFETIME, "lifetime"),
92 (LOGICAL, "logical") => OPERATOR,
93 (MACRO_BANG, "macroBang") => MACRO,
94 (PARENTHESIS, "parenthesis"),
95 (PROC_MACRO, "procMacro") => MACRO,
96 (PUNCTUATION, "punctuation"),
97 (SELF_KEYWORD, "selfKeyword") => KEYWORD,
98 (SELF_TYPE_KEYWORD, "selfTypeKeyword") => KEYWORD,
99 (SEMICOLON, "semicolon"),
100 (STATIC, "static") => VARIABLE,
101 (TOOL_MODULE, "toolModule") => DECORATOR,
102 (TYPE_ALIAS, "typeAlias") => TYPE,
103 (UNION, "union") => TYPE,
104 (UNRESOLVED_REFERENCE, "unresolvedReference"),
105 }
106];
107
108macro_rules! count_tts {
109 () => {0usize};
110 ($_head:tt $($tail:tt)*) => {1usize + count_tts!($($tail)*)};
111}
112macro_rules! define_semantic_token_modifiers {
113 (
114 standard {
115 $($standard:ident),*$(,)?
116 }
117 custom {
118 $(($custom:ident, $string:literal)),*$(,)?
119 }
120
121 ) => {
122 pub(crate) mod modifiers {
123 use super::SemanticTokenModifier;
124
125 $(pub(crate) const $standard: SemanticTokenModifier = SemanticTokenModifier::$standard;)*
126 $(pub(crate) const $custom: SemanticTokenModifier = SemanticTokenModifier::new($string);)*
127 }
128
129 pub(crate) const SUPPORTED_MODIFIERS: &[SemanticTokenModifier] = &[
130 $(SemanticTokenModifier::$standard,)*
131 $(self::modifiers::$custom),*
132 ];
133
134 const LAST_STANDARD_MOD: usize = count_tts!($($standard)*);
135 };
136}
137
138define_semantic_token_modifiers![
139 standard {
140 ASYNC,
141 DOCUMENTATION,
142 DECLARATION,
143 STATIC,
144 DEFAULT_LIBRARY,
145 }
146 custom {
147 (ASSOCIATED, "associated"),
148 (ATTRIBUTE_MODIFIER, "attribute"),
149 (CALLABLE, "callable"),
150 (CONSTANT, "constant"),
151 (CONSUMING, "consuming"),
152 (CONTROL_FLOW, "controlFlow"),
153 (CRATE_ROOT, "crateRoot"),
154 (INJECTED, "injected"),
155 (INTRA_DOC_LINK, "intraDocLink"),
156 (LIBRARY, "library"),
157 (MACRO_MODIFIER, "macro"),
158 (MUTABLE, "mutable"),
159 (PROC_MACRO_MODIFIER, "procMacro"),
160 (PUBLIC, "public"),
161 (REFERENCE, "reference"),
162 (TRAIT_MODIFIER, "trait"),
163 (UNSAFE, "unsafe"),
164 }
165];
166
167#[derive(Default)]
168pub(crate) struct ModifierSet(pub(crate) u32);
169
170impl ModifierSet {
171 pub(crate) fn standard_fallback(&mut self) {
172 self.0 &= !(!0u32 << LAST_STANDARD_MOD)
174 }
175}
176
177impl ops::BitOrAssign<SemanticTokenModifier> for ModifierSet {
178 fn bitor_assign(&mut self, rhs: SemanticTokenModifier) {
179 let idx = SUPPORTED_MODIFIERS.iter().position(|it| it == &rhs).unwrap();
180 self.0 |= 1 << idx;
181 }
182}
183
184pub(crate) struct SemanticTokensBuilder {
188 id: String,
189 prev_line: u32,
190 prev_char: u32,
191 data: Vec<SemanticToken>,
192}
193
194impl SemanticTokensBuilder {
195 pub(crate) fn new(id: String) -> Self {
196 SemanticTokensBuilder { id, prev_line: 0, prev_char: 0, data: Default::default() }
197 }
198
199 pub(crate) fn push(&mut self, range: Range, token_index: u32, modifier_bitset: u32) {
201 let mut push_line = range.start.line;
202 let mut push_char = range.start.character;
203
204 if !self.data.is_empty() {
205 push_line -= self.prev_line;
206 if push_line == 0 {
207 push_char -= self.prev_char;
208 }
209 }
210
211 let token_len = range.end.character - range.start.character;
213
214 let token = SemanticToken {
215 delta_line: push_line,
216 delta_start: push_char,
217 length: token_len,
218 token_type: token_index,
219 token_modifiers_bitset: modifier_bitset,
220 };
221
222 self.data.push(token);
223
224 self.prev_line = range.start.line;
225 self.prev_char = range.start.character;
226 }
227
228 pub(crate) fn build(self) -> SemanticTokens {
229 SemanticTokens { result_id: Some(self.id), data: self.data }
230 }
231}
232
233pub(crate) fn diff_tokens(old: &[SemanticToken], new: &[SemanticToken]) -> Vec<SemanticTokensEdit> {
234 let offset = new.iter().zip(old.iter()).take_while(|&(n, p)| n == p).count();
235
236 let (_, old) = old.split_at(offset);
237 let (_, new) = new.split_at(offset);
238
239 let offset_from_end =
240 new.iter().rev().zip(old.iter().rev()).take_while(|&(n, p)| n == p).count();
241
242 let (old, _) = old.split_at(old.len() - offset_from_end);
243 let (new, _) = new.split_at(new.len() - offset_from_end);
244
245 if old.is_empty() && new.is_empty() {
246 vec![]
247 } else {
248 vec![SemanticTokensEdit {
252 start: 5 * offset as u32,
253 delete_count: 5 * old.len() as u32,
254 data: Some(new.into()),
255 }]
256 }
257}
258
259pub(crate) fn type_index(ty: SemanticTokenType) -> u32 {
260 SUPPORTED_TYPES.iter().position(|it| *it == ty).unwrap() as u32
261}
262
263#[cfg(test)]
264mod tests {
265 use super::*;
266
267 fn from(t: (u32, u32, u32, u32, u32)) -> SemanticToken {
268 SemanticToken {
269 delta_line: t.0,
270 delta_start: t.1,
271 length: t.2,
272 token_type: t.3,
273 token_modifiers_bitset: t.4,
274 }
275 }
276
277 #[test]
278 fn test_diff_insert_at_end() {
279 let before = [from((1, 2, 3, 4, 5)), from((6, 7, 8, 9, 10))];
280 let after = [from((1, 2, 3, 4, 5)), from((6, 7, 8, 9, 10)), from((11, 12, 13, 14, 15))];
281
282 let edits = diff_tokens(&before, &after);
283 assert_eq!(
284 edits[0],
285 SemanticTokensEdit {
286 start: 10,
287 delete_count: 0,
288 data: Some(vec![from((11, 12, 13, 14, 15))])
289 }
290 );
291 }
292
293 #[test]
294 fn test_diff_insert_at_beginning() {
295 let before = [from((1, 2, 3, 4, 5)), from((6, 7, 8, 9, 10))];
296 let after = [from((11, 12, 13, 14, 15)), from((1, 2, 3, 4, 5)), from((6, 7, 8, 9, 10))];
297
298 let edits = diff_tokens(&before, &after);
299 assert_eq!(
300 edits[0],
301 SemanticTokensEdit {
302 start: 0,
303 delete_count: 0,
304 data: Some(vec![from((11, 12, 13, 14, 15))])
305 }
306 );
307 }
308
309 #[test]
310 fn test_diff_insert_in_middle() {
311 let before = [from((1, 2, 3, 4, 5)), from((6, 7, 8, 9, 10))];
312 let after = [
313 from((1, 2, 3, 4, 5)),
314 from((10, 20, 30, 40, 50)),
315 from((60, 70, 80, 90, 100)),
316 from((6, 7, 8, 9, 10)),
317 ];
318
319 let edits = diff_tokens(&before, &after);
320 assert_eq!(
321 edits[0],
322 SemanticTokensEdit {
323 start: 5,
324 delete_count: 0,
325 data: Some(vec![from((10, 20, 30, 40, 50)), from((60, 70, 80, 90, 100))])
326 }
327 );
328 }
329
330 #[test]
331 fn test_diff_remove_from_end() {
332 let before = [from((1, 2, 3, 4, 5)), from((6, 7, 8, 9, 10)), from((11, 12, 13, 14, 15))];
333 let after = [from((1, 2, 3, 4, 5)), from((6, 7, 8, 9, 10))];
334
335 let edits = diff_tokens(&before, &after);
336 assert_eq!(edits[0], SemanticTokensEdit { start: 10, delete_count: 5, data: Some(vec![]) });
337 }
338
339 #[test]
340 fn test_diff_remove_from_beginning() {
341 let before = [from((11, 12, 13, 14, 15)), from((1, 2, 3, 4, 5)), from((6, 7, 8, 9, 10))];
342 let after = [from((1, 2, 3, 4, 5)), from((6, 7, 8, 9, 10))];
343
344 let edits = diff_tokens(&before, &after);
345 assert_eq!(edits[0], SemanticTokensEdit { start: 0, delete_count: 5, data: Some(vec![]) });
346 }
347
348 #[test]
349 fn test_diff_remove_from_middle() {
350 let before = [
351 from((1, 2, 3, 4, 5)),
352 from((10, 20, 30, 40, 50)),
353 from((60, 70, 80, 90, 100)),
354 from((6, 7, 8, 9, 10)),
355 ];
356 let after = [from((1, 2, 3, 4, 5)), from((6, 7, 8, 9, 10))];
357
358 let edits = diff_tokens(&before, &after);
359 assert_eq!(edits[0], SemanticTokensEdit { start: 5, delete_count: 10, data: Some(vec![]) });
360 }
361}