]> git.lizzy.rs Git - rust.git/blob - crates/ra_ide/src/syntax_highlighting/tags.rs
Merge #4161
[rust.git] / crates / ra_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 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
7 pub struct Highlight {
8     pub tag: HighlightTag,
9     pub modifiers: HighlightModifiers,
10 }
11
12 #[derive(Default, Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
13 pub struct HighlightModifiers(u32);
14
15 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
16 pub enum HighlightTag {
17     Attribute,
18     BuiltinType,
19     ByteLiteral,
20     CharLiteral,
21     Comment,
22     Constant,
23     Enum,
24     EnumVariant,
25     Field,
26     Function,
27     Keyword,
28     Lifetime,
29     Macro,
30     Module,
31     NumericLiteral,
32     SelfType,
33     Static,
34     StringLiteral,
35     Struct,
36     Trait,
37     TypeAlias,
38     TypeParam,
39     Union,
40     Local,
41     UnresolvedReference,
42     FormatSpecifier,
43 }
44
45 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
46 #[repr(u8)]
47 pub enum HighlightModifier {
48     /// Used with keywords like `if` and `break`.
49     ControlFlow = 0,
50     /// `foo` in `fn foo(x: i32)` is a definition, `foo` in `foo(90 + 2)` is
51     /// not.
52     Definition,
53     Mutable,
54     Unsafe,
55 }
56
57 impl HighlightTag {
58     fn as_str(self) -> &'static str {
59         match self {
60             HighlightTag::Attribute => "attribute",
61             HighlightTag::BuiltinType => "builtin_type",
62             HighlightTag::ByteLiteral => "byte_literal",
63             HighlightTag::CharLiteral => "char_literal",
64             HighlightTag::Comment => "comment",
65             HighlightTag::Constant => "constant",
66             HighlightTag::Enum => "enum",
67             HighlightTag::EnumVariant => "enum_variant",
68             HighlightTag::Field => "field",
69             HighlightTag::Function => "function",
70             HighlightTag::Keyword => "keyword",
71             HighlightTag::Lifetime => "lifetime",
72             HighlightTag::Macro => "macro",
73             HighlightTag::Module => "module",
74             HighlightTag::NumericLiteral => "numeric_literal",
75             HighlightTag::SelfType => "self_type",
76             HighlightTag::Static => "static",
77             HighlightTag::StringLiteral => "string_literal",
78             HighlightTag::Struct => "struct",
79             HighlightTag::Trait => "trait",
80             HighlightTag::TypeAlias => "type_alias",
81             HighlightTag::TypeParam => "type_param",
82             HighlightTag::Union => "union",
83             HighlightTag::Local => "variable",
84             HighlightTag::UnresolvedReference => "unresolved_reference",
85             HighlightTag::FormatSpecifier => "format_specifier",
86         }
87     }
88 }
89
90 impl fmt::Display for HighlightTag {
91     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
92         fmt::Display::fmt(self.as_str(), f)
93     }
94 }
95
96 impl HighlightModifier {
97     const ALL: &'static [HighlightModifier] = &[
98         HighlightModifier::ControlFlow,
99         HighlightModifier::Definition,
100         HighlightModifier::Mutable,
101         HighlightModifier::Unsafe,
102     ];
103
104     fn as_str(self) -> &'static str {
105         match self {
106             HighlightModifier::ControlFlow => "control",
107             HighlightModifier::Definition => "declaration",
108             HighlightModifier::Mutable => "mutable",
109             HighlightModifier::Unsafe => "unsafe",
110         }
111     }
112
113     fn mask(self) -> u32 {
114         1 << (self as u32)
115     }
116 }
117
118 impl fmt::Display for HighlightModifier {
119     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
120         fmt::Display::fmt(self.as_str(), f)
121     }
122 }
123
124 impl fmt::Display for Highlight {
125     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
126         write!(f, "{}", self.tag)?;
127         for modifier in self.modifiers.iter() {
128             write!(f, ".{}", modifier)?
129         }
130         Ok(())
131     }
132 }
133
134 impl From<HighlightTag> for Highlight {
135     fn from(tag: HighlightTag) -> Highlight {
136         Highlight::new(tag)
137     }
138 }
139
140 impl Highlight {
141     pub(crate) fn new(tag: HighlightTag) -> Highlight {
142         Highlight { tag, modifiers: HighlightModifiers::default() }
143     }
144 }
145
146 impl ops::BitOr<HighlightModifier> for HighlightTag {
147     type Output = Highlight;
148
149     fn bitor(self, rhs: HighlightModifier) -> Highlight {
150         Highlight::new(self) | rhs
151     }
152 }
153
154 impl ops::BitOrAssign<HighlightModifier> for HighlightModifiers {
155     fn bitor_assign(&mut self, rhs: HighlightModifier) {
156         self.0 |= rhs.mask();
157     }
158 }
159
160 impl ops::BitOrAssign<HighlightModifier> for Highlight {
161     fn bitor_assign(&mut self, rhs: HighlightModifier) {
162         self.modifiers |= rhs;
163     }
164 }
165
166 impl ops::BitOr<HighlightModifier> for Highlight {
167     type Output = Highlight;
168
169     fn bitor(mut self, rhs: HighlightModifier) -> Highlight {
170         self |= rhs;
171         self
172     }
173 }
174
175 impl HighlightModifiers {
176     pub fn iter(self) -> impl Iterator<Item = HighlightModifier> {
177         HighlightModifier::ALL.iter().copied().filter(move |it| self.0 & it.mask() == it.mask())
178     }
179 }