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