1 //! Defines token tags we use for syntax highlighting.
2 //! A tag is not unlike a CSS class.
9 use ide_db::SymbolKind;
11 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
12 pub struct Highlight {
17 #[derive(Default, Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
18 pub struct HlMods(u32);
20 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
39 // For things which don't have a specific highlight.
43 // Don't forget to adjust the feature description in crates/ide/src/syntax_highlighting.rs.
44 // And make sure to use the lsp strings used when converting to the protocol in crates\rust-analyzer\src\semantic_tokens.rs, not the names of the variants here.
45 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
48 /// Used for items in traits and impls.
50 /// Used with keywords like `async` and `await`.
52 /// Used to differentiate individual elements within attributes.
54 /// Callable item or value.
56 /// Value that is being consumed in a function call
58 /// Used with keywords like `if` and `break`.
60 /// Used for crate names, like `serde`.
62 /// Used for items from built-in crates (std, core, alloc, test and proc_macro).
64 /// `foo` in `fn foo(x: i32)` is a definition, `foo` in `foo(90 + 2)` is
67 /// Doc-strings like this one.
69 /// Highlighting injection like rust code in doc strings or ra_fixture.
71 /// Used for intra doc links in doc injection.
73 /// Used for items from other crates.
77 /// Used for public items.
79 /// Immutable reference.
81 /// Used for associated functions.
83 /// Used for items in traits and trait impls.
86 /// Used for unsafe functions, unsafe traits, mutable statics, union accesses and unsafe operations.
90 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
108 /// ! (only for macro calls)
114 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
115 pub enum HlOperator {
116 /// |, &, !, ^, |=, &=, ^=
118 /// +, -, *, /, +=, -=, *=, /=
122 /// >, <, ==, >=, <=, !=
129 fn as_str(self) -> &'static str {
131 HlTag::Symbol(symbol) => match symbol {
132 SymbolKind::Attribute => "attribute",
133 SymbolKind::BuiltinAttr => "builtin_attr",
134 SymbolKind::Const => "constant",
135 SymbolKind::ConstParam => "const_param",
136 SymbolKind::Derive => "derive",
137 SymbolKind::DeriveHelper => "derive_helper",
138 SymbolKind::Enum => "enum",
139 SymbolKind::Field => "field",
140 SymbolKind::Function => "function",
141 SymbolKind::Impl => "self_type",
142 SymbolKind::Label => "label",
143 SymbolKind::LifetimeParam => "lifetime",
144 SymbolKind::Local => "variable",
145 SymbolKind::Macro => "macro",
146 SymbolKind::Module => "module",
147 SymbolKind::SelfParam => "self_keyword",
148 SymbolKind::SelfType => "self_type_keyword",
149 SymbolKind::Static => "static",
150 SymbolKind::Struct => "struct",
151 SymbolKind::ToolModule => "tool_module",
152 SymbolKind::Trait => "trait",
153 SymbolKind::TypeAlias => "type_alias",
154 SymbolKind::TypeParam => "type_param",
155 SymbolKind::Union => "union",
156 SymbolKind::ValueParam => "value_param",
157 SymbolKind::Variant => "enum_variant",
159 HlTag::AttributeBracket => "attribute_bracket",
160 HlTag::BoolLiteral => "bool_literal",
161 HlTag::BuiltinType => "builtin_type",
162 HlTag::ByteLiteral => "byte_literal",
163 HlTag::CharLiteral => "char_literal",
164 HlTag::Comment => "comment",
165 HlTag::EscapeSequence => "escape_sequence",
166 HlTag::FormatSpecifier => "format_specifier",
167 HlTag::Keyword => "keyword",
168 HlTag::Punctuation(punct) => match punct {
169 HlPunct::Bracket => "bracket",
170 HlPunct::Brace => "brace",
171 HlPunct::Parenthesis => "parenthesis",
172 HlPunct::Angle => "angle",
173 HlPunct::Comma => "comma",
174 HlPunct::Dot => "dot",
175 HlPunct::Colon => "colon",
176 HlPunct::Semi => "semicolon",
177 HlPunct::MacroBang => "macro_bang",
178 HlPunct::Other => "punctuation",
180 HlTag::NumericLiteral => "numeric_literal",
181 HlTag::Operator(op) => match op {
182 HlOperator::Bitwise => "bitwise",
183 HlOperator::Arithmetic => "arithmetic",
184 HlOperator::Logical => "logical",
185 HlOperator::Comparison => "comparison",
186 HlOperator::Other => "operator",
188 HlTag::StringLiteral => "string_literal",
189 HlTag::UnresolvedReference => "unresolved_reference",
190 HlTag::None => "none",
195 impl fmt::Display for HlTag {
196 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
197 fmt::Display::fmt(self.as_str(), f)
202 const ALL: &'static [HlMod; HlMod::Unsafe as u8 as usize + 1] = &[
210 HlMod::DefaultLibrary,
212 HlMod::Documentation,
224 fn as_str(self) -> &'static str {
226 HlMod::Associated => "associated",
227 HlMod::Async => "async",
228 HlMod::Attribute => "attribute",
229 HlMod::Callable => "callable",
230 HlMod::Consuming => "consuming",
231 HlMod::ControlFlow => "control",
232 HlMod::CrateRoot => "crate_root",
233 HlMod::DefaultLibrary => "default_library",
234 HlMod::Definition => "declaration",
235 HlMod::Documentation => "documentation",
236 HlMod::Injected => "injected",
237 HlMod::IntraDocLink => "intra_doc_link",
238 HlMod::Library => "library",
239 HlMod::Mutable => "mutable",
240 HlMod::Public => "public",
241 HlMod::Reference => "reference",
242 HlMod::Static => "static",
243 HlMod::Trait => "trait",
244 HlMod::Unsafe => "unsafe",
248 fn mask(self) -> u32 {
253 impl fmt::Display for HlMod {
254 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
255 fmt::Display::fmt(self.as_str(), f)
259 impl fmt::Display for Highlight {
260 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
262 for modifier in self.mods.iter() {
270 impl From<HlTag> for Highlight {
271 fn from(tag: HlTag) -> Highlight {
276 impl From<HlOperator> for Highlight {
277 fn from(op: HlOperator) -> Highlight {
278 Highlight::new(HlTag::Operator(op))
282 impl From<HlPunct> for Highlight {
283 fn from(punct: HlPunct) -> Highlight {
284 Highlight::new(HlTag::Punctuation(punct))
288 impl From<SymbolKind> for Highlight {
289 fn from(sym: SymbolKind) -> Highlight {
290 Highlight::new(HlTag::Symbol(sym))
295 pub(crate) fn new(tag: HlTag) -> Highlight {
296 Highlight { tag, mods: HlMods::default() }
298 pub fn is_empty(&self) -> bool {
299 self.tag == HlTag::None && self.mods == HlMods::default()
303 impl ops::BitOr<HlMod> for HlTag {
304 type Output = Highlight;
306 fn bitor(self, rhs: HlMod) -> Highlight {
307 Highlight::new(self) | rhs
311 impl ops::BitOrAssign<HlMod> for HlMods {
312 fn bitor_assign(&mut self, rhs: HlMod) {
313 self.0 |= rhs.mask();
317 impl ops::BitOrAssign<HlMod> for Highlight {
318 fn bitor_assign(&mut self, rhs: HlMod) {
323 impl ops::BitOr<HlMod> for Highlight {
324 type Output = Highlight;
326 fn bitor(mut self, rhs: HlMod) -> Highlight {
333 pub fn contains(self, m: HlMod) -> bool {
334 self.0 & m.mask() == m.mask()
337 pub fn iter(self) -> impl Iterator<Item = HlMod> {
338 HlMod::ALL.iter().copied().filter(move |it| self.0 & it.mask() == it.mask())