]> git.lizzy.rs Git - rust.git/blob - crates/ide/src/syntax_highlighting/tags.rs
Shorten frequent names
[rust.git] / crates / ide / src / syntax_highlighting / tags.rs
1 //! Defines token tags we use for syntax highlighting.
2 //! A tag is not unlike a CSS class.
3
4 use std::{fmt, ops};
5
6 use crate::SymbolKind;
7
8 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
9 pub struct Highlight {
10     pub tag: HlTag,
11     pub mods: HlMods,
12 }
13
14 #[derive(Default, Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
15 pub struct HlMods(u32);
16
17 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
18 pub enum HlTag {
19     Symbol(SymbolKind),
20
21     BoolLiteral,
22     BuiltinType,
23     ByteLiteral,
24     CharLiteral,
25     NumericLiteral,
26     StringLiteral,
27     Attribute,
28     Comment,
29     EscapeSequence,
30     FormatSpecifier,
31     Keyword,
32     Punctuation,
33     Operator,
34     UnresolvedReference,
35
36     // For things which don't have a specific highlight.
37     None,
38 }
39
40 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
41 #[repr(u8)]
42 pub enum HlMod {
43     /// Used to differentiate individual elements within attributes.
44     Attribute = 0,
45     /// Used with keywords like `if` and `break`.
46     ControlFlow,
47     /// `foo` in `fn foo(x: i32)` is a definition, `foo` in `foo(90 + 2)` is
48     /// not.
49     Definition,
50     Documentation,
51     Injected,
52     Mutable,
53     Consuming,
54     Callable,
55     /// Used for associated functions
56     Static,
57     /// Used for items in impls&traits.
58     Associated,
59
60     /// Keep this last!
61     Unsafe,
62 }
63
64 impl HlTag {
65     fn as_str(self) -> &'static str {
66         match self {
67             HlTag::Symbol(symbol) => match symbol {
68                 SymbolKind::Const => "constant",
69                 SymbolKind::Static => "static",
70                 SymbolKind::Enum => "enum",
71                 SymbolKind::Variant => "enum_variant",
72                 SymbolKind::Struct => "struct",
73                 SymbolKind::Union => "union",
74                 SymbolKind::Field => "field",
75                 SymbolKind::Module => "module",
76                 SymbolKind::Trait => "trait",
77                 SymbolKind::Function => "function",
78                 SymbolKind::TypeAlias => "type_alias",
79                 SymbolKind::TypeParam => "type_param",
80                 SymbolKind::ConstParam => "const_param",
81                 SymbolKind::LifetimeParam => "lifetime",
82                 SymbolKind::Macro => "macro",
83                 SymbolKind::Local => "variable",
84                 SymbolKind::Label => "label",
85                 SymbolKind::ValueParam => "value_param",
86                 SymbolKind::SelfParam => "self_keyword",
87                 SymbolKind::Impl => "self_type",
88             },
89             HlTag::Attribute => "attribute",
90             HlTag::BoolLiteral => "bool_literal",
91             HlTag::BuiltinType => "builtin_type",
92             HlTag::ByteLiteral => "byte_literal",
93             HlTag::CharLiteral => "char_literal",
94             HlTag::Comment => "comment",
95             HlTag::EscapeSequence => "escape_sequence",
96             HlTag::FormatSpecifier => "format_specifier",
97             HlTag::Keyword => "keyword",
98             HlTag::Punctuation => "punctuation",
99             HlTag::NumericLiteral => "numeric_literal",
100             HlTag::Operator => "operator",
101             HlTag::StringLiteral => "string_literal",
102             HlTag::UnresolvedReference => "unresolved_reference",
103             HlTag::None => "none",
104         }
105     }
106 }
107
108 impl fmt::Display for HlTag {
109     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
110         fmt::Display::fmt(self.as_str(), f)
111     }
112 }
113
114 impl HlMod {
115     const ALL: &'static [HlMod; HlMod::Unsafe as u8 as usize + 1] = &[
116         HlMod::Attribute,
117         HlMod::ControlFlow,
118         HlMod::Definition,
119         HlMod::Documentation,
120         HlMod::Injected,
121         HlMod::Mutable,
122         HlMod::Consuming,
123         HlMod::Callable,
124         HlMod::Static,
125         HlMod::Associated,
126         HlMod::Unsafe,
127     ];
128
129     fn as_str(self) -> &'static str {
130         match self {
131             HlMod::Attribute => "attribute",
132             HlMod::ControlFlow => "control",
133             HlMod::Definition => "declaration",
134             HlMod::Documentation => "documentation",
135             HlMod::Injected => "injected",
136             HlMod::Mutable => "mutable",
137             HlMod::Consuming => "consuming",
138             HlMod::Unsafe => "unsafe",
139             HlMod::Callable => "callable",
140             HlMod::Static => "static",
141             HlMod::Associated => "associated",
142         }
143     }
144
145     fn mask(self) -> u32 {
146         1 << (self as u32)
147     }
148 }
149
150 impl fmt::Display for HlMod {
151     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
152         fmt::Display::fmt(self.as_str(), f)
153     }
154 }
155
156 impl fmt::Display for Highlight {
157     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
158         write!(f, "{}", self.tag)?;
159         for modifier in self.mods.iter() {
160             write!(f, ".{}", modifier)?
161         }
162         Ok(())
163     }
164 }
165
166 impl From<HlTag> for Highlight {
167     fn from(tag: HlTag) -> Highlight {
168         Highlight::new(tag)
169     }
170 }
171
172 impl Highlight {
173     pub(crate) fn new(tag: HlTag) -> Highlight {
174         Highlight { tag, mods: HlMods::default() }
175     }
176     pub fn is_empty(&self) -> bool {
177         self.tag == HlTag::None && self.mods == HlMods::default()
178     }
179 }
180
181 impl ops::BitOr<HlMod> for HlTag {
182     type Output = Highlight;
183
184     fn bitor(self, rhs: HlMod) -> Highlight {
185         Highlight::new(self) | rhs
186     }
187 }
188
189 impl ops::BitOrAssign<HlMod> for HlMods {
190     fn bitor_assign(&mut self, rhs: HlMod) {
191         self.0 |= rhs.mask();
192     }
193 }
194
195 impl ops::BitOrAssign<HlMod> for Highlight {
196     fn bitor_assign(&mut self, rhs: HlMod) {
197         self.mods |= rhs;
198     }
199 }
200
201 impl ops::BitOr<HlMod> for Highlight {
202     type Output = Highlight;
203
204     fn bitor(mut self, rhs: HlMod) -> Highlight {
205         self |= rhs;
206         self
207     }
208 }
209
210 impl HlMods {
211     pub fn contains(self, m: HlMod) -> bool {
212         self.0 & m.mask() == m.mask()
213     }
214
215     pub fn iter(self) -> impl Iterator<Item = HlMod> {
216         HlMod::ALL.iter().copied().filter(move |it| self.0 & it.mask() == it.mask())
217     }
218 }