1use std::{
5 fmt::{self, Write},
6 ops,
7};
8
9use ide_db::SymbolKind;
10
11#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
12pub struct Highlight {
13 pub tag: HlTag,
14 pub mods: HlMods,
15}
16
17#[derive(Default, Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
18pub struct HlMods(u32);
19
20#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
21pub enum HlTag {
22 Symbol(SymbolKind),
23
24 AttributeBracket,
25 BoolLiteral,
26 BuiltinType,
27 ByteLiteral,
28 CharLiteral,
29 Comment,
30 EscapeSequence,
31 FormatSpecifier,
32 InvalidEscapeSequence,
33 Keyword,
34 NumericLiteral,
35 Operator(HlOperator),
36 Punctuation(HlPunct),
37 StringLiteral,
38 UnresolvedReference,
39
40 None,
42}
43
44#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
47#[repr(u8)]
48pub enum HlMod {
49 Associated = 0,
51 Async,
53 Attribute,
55 Callable,
57 Const,
59 Consuming,
61 ControlFlow,
63 CrateRoot,
65 DefaultLibrary,
67 Definition,
70 Deprecated,
72 Documentation,
74 Injected,
76 IntraDocLink,
78 Library,
80 Macro,
82 ProcMacro,
84 Mutable,
86 Public,
88 Reference,
90 Static,
92 Trait,
94 Unsafe,
97}
98
99#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
100pub enum HlPunct {
101 Bracket,
103 Brace,
105 Parenthesis,
107 Angle,
109 Comma,
111 Dot,
113 Colon,
115 Semi,
117 MacroBang,
119 Other,
121}
122
123#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
124pub enum HlOperator {
125 Bitwise,
127 Arithmetic,
129 Logical,
131 Negation,
133 Comparison,
135 Other,
137}
138
139impl HlTag {
140 fn as_str(self) -> &'static str {
141 match self {
142 HlTag::Symbol(symbol) => match symbol {
143 SymbolKind::Attribute => "attribute",
144 SymbolKind::BuiltinAttr => "builtin_attr",
145 SymbolKind::Const => "constant",
146 SymbolKind::ConstParam => "const_param",
147 SymbolKind::CrateRoot => "crate_root",
148 SymbolKind::Derive => "derive",
149 SymbolKind::DeriveHelper => "derive_helper",
150 SymbolKind::Enum => "enum",
151 SymbolKind::Field => "field",
152 SymbolKind::Function => "function",
153 SymbolKind::Impl => "self_type",
154 SymbolKind::InlineAsmRegOrRegClass => "reg",
155 SymbolKind::Label => "label",
156 SymbolKind::LifetimeParam => "lifetime",
157 SymbolKind::Local => "variable",
158 SymbolKind::Macro => "macro",
159 SymbolKind::Method => "method",
160 SymbolKind::ProcMacro => "proc_macro",
161 SymbolKind::Module => "module",
162 SymbolKind::SelfParam => "self_keyword",
163 SymbolKind::SelfType => "self_type_keyword",
164 SymbolKind::Static => "static",
165 SymbolKind::Struct => "struct",
166 SymbolKind::ToolModule => "tool_module",
167 SymbolKind::Trait => "trait",
168 SymbolKind::TypeAlias => "type_alias",
169 SymbolKind::TypeParam => "type_param",
170 SymbolKind::Union => "union",
171 SymbolKind::ValueParam => "value_param",
172 SymbolKind::Variant => "enum_variant",
173 },
174 HlTag::AttributeBracket => "attribute_bracket",
175 HlTag::BoolLiteral => "bool_literal",
176 HlTag::BuiltinType => "builtin_type",
177 HlTag::ByteLiteral => "byte_literal",
178 HlTag::CharLiteral => "char_literal",
179 HlTag::Comment => "comment",
180 HlTag::EscapeSequence => "escape_sequence",
181 HlTag::InvalidEscapeSequence => "invalid_escape_sequence",
182 HlTag::FormatSpecifier => "format_specifier",
183 HlTag::Keyword => "keyword",
184 HlTag::Punctuation(punct) => match punct {
185 HlPunct::Bracket => "bracket",
186 HlPunct::Brace => "brace",
187 HlPunct::Parenthesis => "parenthesis",
188 HlPunct::Angle => "angle",
189 HlPunct::Comma => "comma",
190 HlPunct::Dot => "dot",
191 HlPunct::Colon => "colon",
192 HlPunct::Semi => "semicolon",
193 HlPunct::MacroBang => "macro_bang",
194 HlPunct::Other => "punctuation",
195 },
196 HlTag::NumericLiteral => "numeric_literal",
197 HlTag::Operator(op) => match op {
198 HlOperator::Bitwise => "bitwise",
199 HlOperator::Arithmetic => "arithmetic",
200 HlOperator::Logical => "logical",
201 HlOperator::Comparison => "comparison",
202 HlOperator::Negation => "negation",
203 HlOperator::Other => "operator",
204 },
205 HlTag::StringLiteral => "string_literal",
206 HlTag::UnresolvedReference => "unresolved_reference",
207 HlTag::None => "none",
208 }
209 }
210}
211
212impl fmt::Display for HlTag {
213 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
214 fmt::Display::fmt(self.as_str(), f)
215 }
216}
217
218impl HlMod {
219 const ALL: &'static [HlMod; HlMod::Unsafe as usize + 1] = &[
220 HlMod::Associated,
221 HlMod::Async,
222 HlMod::Attribute,
223 HlMod::Callable,
224 HlMod::Const,
225 HlMod::Consuming,
226 HlMod::ControlFlow,
227 HlMod::CrateRoot,
228 HlMod::DefaultLibrary,
229 HlMod::Definition,
230 HlMod::Deprecated,
231 HlMod::Documentation,
232 HlMod::Injected,
233 HlMod::IntraDocLink,
234 HlMod::Library,
235 HlMod::Macro,
236 HlMod::Mutable,
237 HlMod::ProcMacro,
238 HlMod::Public,
239 HlMod::Reference,
240 HlMod::Static,
241 HlMod::Trait,
242 HlMod::Unsafe,
243 ];
244
245 fn as_str(self) -> &'static str {
246 match self {
247 HlMod::Associated => "associated",
248 HlMod::Async => "async",
249 HlMod::Attribute => "attribute",
250 HlMod::Callable => "callable",
251 HlMod::Consuming => "consuming",
252 HlMod::Const => "const",
253 HlMod::ControlFlow => "control",
254 HlMod::CrateRoot => "crate_root",
255 HlMod::DefaultLibrary => "default_library",
256 HlMod::Definition => "declaration",
257 HlMod::Deprecated => "deprecated",
258 HlMod::Documentation => "documentation",
259 HlMod::Injected => "injected",
260 HlMod::IntraDocLink => "intra_doc_link",
261 HlMod::Library => "library",
262 HlMod::Macro => "macro",
263 HlMod::ProcMacro => "proc_macro",
264 HlMod::Mutable => "mutable",
265 HlMod::Public => "public",
266 HlMod::Reference => "reference",
267 HlMod::Static => "static",
268 HlMod::Trait => "trait",
269 HlMod::Unsafe => "unsafe",
270 }
271 }
272
273 fn mask(self) -> u32 {
274 debug_assert!(Self::ALL.len() <= 32, "HlMod::mask is not enough to cover all variants");
275 1 << (self as u32)
276 }
277}
278
279impl fmt::Display for HlMod {
280 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
281 fmt::Display::fmt(self.as_str(), f)
282 }
283}
284
285impl fmt::Display for Highlight {
286 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
287 self.tag.fmt(f)?;
288 for modifier in self.mods.iter() {
289 f.write_char('.')?;
290 modifier.fmt(f)?;
291 }
292 Ok(())
293 }
294}
295
296impl From<HlTag> for Highlight {
297 fn from(tag: HlTag) -> Highlight {
298 Highlight::new(tag)
299 }
300}
301
302impl From<HlOperator> for Highlight {
303 fn from(op: HlOperator) -> Highlight {
304 Highlight::new(HlTag::Operator(op))
305 }
306}
307
308impl From<HlPunct> for Highlight {
309 fn from(punct: HlPunct) -> Highlight {
310 Highlight::new(HlTag::Punctuation(punct))
311 }
312}
313
314impl From<SymbolKind> for Highlight {
315 fn from(sym: SymbolKind) -> Highlight {
316 Highlight::new(HlTag::Symbol(sym))
317 }
318}
319
320impl Highlight {
321 pub(crate) fn new(tag: HlTag) -> Highlight {
322 Highlight { tag, mods: HlMods::default() }
323 }
324 pub fn is_empty(&self) -> bool {
325 self.tag == HlTag::None && self.mods.is_empty()
326 }
327}
328
329impl ops::BitOr<HlMod> for HlTag {
330 type Output = Highlight;
331
332 fn bitor(self, rhs: HlMod) -> Highlight {
333 Highlight::new(self) | rhs
334 }
335}
336
337impl ops::BitOrAssign<HlMod> for HlMods {
338 fn bitor_assign(&mut self, rhs: HlMod) {
339 self.0 |= rhs.mask();
340 }
341}
342
343impl ops::BitOrAssign<HlMod> for Highlight {
344 fn bitor_assign(&mut self, rhs: HlMod) {
345 self.mods |= rhs;
346 }
347}
348
349impl ops::BitOr<HlMod> for Highlight {
350 type Output = Highlight;
351
352 fn bitor(mut self, rhs: HlMod) -> Highlight {
353 self |= rhs;
354 self
355 }
356}
357
358impl HlMods {
359 pub fn is_empty(&self) -> bool {
360 self.0 == 0
361 }
362
363 pub fn contains(self, m: HlMod) -> bool {
364 self.0 & m.mask() == m.mask()
365 }
366
367 pub fn iter(self) -> impl Iterator<Item = HlMod> {
368 HlMod::ALL.iter().copied().filter(move |it| self.0 & it.mask() == it.mask())
369 }
370}