aboutsummaryrefslogtreecommitdiff
path: root/crates/ide/src/syntax_highlighting/highlight.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide/src/syntax_highlighting/highlight.rs')
-rw-r--r--crates/ide/src/syntax_highlighting/highlight.rs191
1 files changed, 85 insertions, 106 deletions
diff --git a/crates/ide/src/syntax_highlighting/highlight.rs b/crates/ide/src/syntax_highlighting/highlight.rs
index 18552459b..b586dcc17 100644
--- a/crates/ide/src/syntax_highlighting/highlight.rs
+++ b/crates/ide/src/syntax_highlighting/highlight.rs
@@ -1,6 +1,6 @@
1//! Computes color for a single element. 1//! Computes color for a single element.
2 2
3use hir::{AsAssocItem, AssocItemContainer, Semantics, VariantDef}; 3use hir::{AsAssocItem, Semantics};
4use ide_db::{ 4use ide_db::{
5 defs::{Definition, NameClass, NameRefClass}, 5 defs::{Definition, NameClass, NameRefClass},
6 RootDatabase, SymbolKind, 6 RootDatabase, SymbolKind,
@@ -45,28 +45,26 @@ pub(super) fn element(
45 }; 45 };
46 46
47 match name_kind { 47 match name_kind {
48 Some(NameClass::ExternCrate(_)) => HlTag::Symbol(SymbolKind::Module).into(), 48 Some(NameClass::ExternCrate(_)) => SymbolKind::Module.into(),
49 Some(NameClass::Definition(def)) => highlight_def(db, def) | HlMod::Definition, 49 Some(NameClass::Definition(def)) => highlight_def(db, def) | HlMod::Definition,
50 Some(NameClass::ConstReference(def)) => highlight_def(db, def), 50 Some(NameClass::ConstReference(def)) => highlight_def(db, def),
51 Some(NameClass::PatFieldShorthand { field_ref, .. }) => { 51 Some(NameClass::PatFieldShorthand { field_ref, .. }) => {
52 let mut h = HlTag::Symbol(SymbolKind::Field).into(); 52 let mut h = HlTag::Symbol(SymbolKind::Field).into();
53 if let Definition::Field(field) = field_ref { 53 if let Definition::Field(field) = field_ref {
54 if let VariantDef::Union(_) = field.parent_def(db) { 54 if let hir::VariantDef::Union(_) = field.parent_def(db) {
55 h |= HlMod::Unsafe; 55 h |= HlMod::Unsafe;
56 } 56 }
57 } 57 }
58
59 h 58 h
60 } 59 }
61 None => highlight_name_by_syntax(name) | HlMod::Definition, 60 None => highlight_name_by_syntax(name) | HlMod::Definition,
62 } 61 }
63 } 62 }
64
65 // Highlight references like the definitions they resolve to 63 // Highlight references like the definitions they resolve to
66 NAME_REF if element.ancestors().any(|it| it.kind() == ATTR) => { 64 NAME_REF if element.ancestors().any(|it| it.kind() == ATTR) => {
67 // even though we track whether we are in an attribute or not we still need this special case 65 // even though we track whether we are in an attribute or not we still need this special case
68 // as otherwise we would emit unresolved references for name refs inside attributes 66 // as otherwise we would emit unresolved references for name refs inside attributes
69 Highlight::from(HlTag::Symbol(SymbolKind::Function)) 67 SymbolKind::Function.into()
70 } 68 }
71 NAME_REF => { 69 NAME_REF => {
72 let name_ref = element.into_node().and_then(ast::NameRef::cast).unwrap(); 70 let name_ref = element.into_node().and_then(ast::NameRef::cast).unwrap();
@@ -74,7 +72,7 @@ pub(super) fn element(
74 let is_self = name_ref.self_token().is_some(); 72 let is_self = name_ref.self_token().is_some();
75 let h = match NameRefClass::classify(sema, &name_ref) { 73 let h = match NameRefClass::classify(sema, &name_ref) {
76 Some(name_kind) => match name_kind { 74 Some(name_kind) => match name_kind {
77 NameRefClass::ExternCrate(_) => HlTag::Symbol(SymbolKind::Module).into(), 75 NameRefClass::ExternCrate(_) => SymbolKind::Module.into(),
78 NameRefClass::Definition(def) => { 76 NameRefClass::Definition(def) => {
79 if let Definition::Local(local) = &def { 77 if let Definition::Local(local) = &def {
80 if let Some(name) = local.name(db) { 78 if let Some(name) = local.name(db) {
@@ -95,7 +93,7 @@ pub(super) fn element(
95 if let Some(parent) = name_ref.syntax().parent() { 93 if let Some(parent) = name_ref.syntax().parent() {
96 if matches!(parent.kind(), FIELD_EXPR | RECORD_PAT_FIELD) { 94 if matches!(parent.kind(), FIELD_EXPR | RECORD_PAT_FIELD) {
97 if let Definition::Field(field) = def { 95 if let Definition::Field(field) = def {
98 if let VariantDef::Union(_) = field.parent_def(db) { 96 if let hir::VariantDef::Union(_) = field.parent_def(db) {
99 h |= HlMod::Unsafe; 97 h |= HlMod::Unsafe;
100 } 98 }
101 } 99 }
@@ -104,9 +102,7 @@ pub(super) fn element(
104 102
105 h 103 h
106 } 104 }
107 NameRefClass::FieldShorthand { .. } => { 105 NameRefClass::FieldShorthand { .. } => SymbolKind::Field.into(),
108 HlTag::Symbol(SymbolKind::Field).into()
109 }
110 }, 106 },
111 None if syntactic_name_ref_highlighting => { 107 None if syntactic_name_ref_highlighting => {
112 highlight_name_ref_by_syntax(name_ref, sema) 108 highlight_name_ref_by_syntax(name_ref, sema)
@@ -114,7 +110,7 @@ pub(super) fn element(
114 None => HlTag::UnresolvedReference.into(), 110 None => HlTag::UnresolvedReference.into(),
115 }; 111 };
116 if h.tag == HlTag::Symbol(SymbolKind::Module) && is_self { 112 if h.tag == HlTag::Symbol(SymbolKind::Module) && is_self {
117 HlTag::Symbol(SymbolKind::SelfParam).into() 113 SymbolKind::SelfParam.into()
118 } else { 114 } else {
119 h 115 h
120 } 116 }
@@ -135,7 +131,7 @@ pub(super) fn element(
135 INT_NUMBER | FLOAT_NUMBER => HlTag::NumericLiteral.into(), 131 INT_NUMBER | FLOAT_NUMBER => HlTag::NumericLiteral.into(),
136 BYTE => HlTag::ByteLiteral.into(), 132 BYTE => HlTag::ByteLiteral.into(),
137 CHAR => HlTag::CharLiteral.into(), 133 CHAR => HlTag::CharLiteral.into(),
138 QUESTION => Highlight::new(HlTag::Operator(HlOperator::Other)) | HlMod::ControlFlow, 134 QUESTION => HlTag::Operator(HlOperator::Other) | HlMod::ControlFlow,
139 LIFETIME => { 135 LIFETIME => {
140 let lifetime = element.into_node().and_then(ast::Lifetime::cast).unwrap(); 136 let lifetime = element.into_node().and_then(ast::Lifetime::cast).unwrap();
141 137
@@ -143,44 +139,31 @@ pub(super) fn element(
143 Some(NameClass::Definition(def)) => highlight_def(db, def) | HlMod::Definition, 139 Some(NameClass::Definition(def)) => highlight_def(db, def) | HlMod::Definition,
144 None => match NameRefClass::classify_lifetime(sema, &lifetime) { 140 None => match NameRefClass::classify_lifetime(sema, &lifetime) {
145 Some(NameRefClass::Definition(def)) => highlight_def(db, def), 141 Some(NameRefClass::Definition(def)) => highlight_def(db, def),
146 _ => Highlight::new(HlTag::Symbol(SymbolKind::LifetimeParam)), 142 _ => SymbolKind::LifetimeParam.into(),
147 }, 143 },
148 _ => Highlight::new(HlTag::Symbol(SymbolKind::LifetimeParam)) | HlMod::Definition, 144 _ => Highlight::from(SymbolKind::LifetimeParam) | HlMod::Definition,
149 } 145 }
150 } 146 }
151 p if p.is_punct() => match p { 147 p if p.is_punct() => match p {
152 T![&] if element.parent().and_then(ast::BinExpr::cast).is_some() => { 148 T![&] if parent_matches::<ast::BinExpr>(&element) => HlOperator::Bitwise.into(),
153 HlTag::Operator(HlOperator::Bitwise).into()
154 }
155 T![&] => { 149 T![&] => {
156 let h = HlTag::Operator(HlOperator::Other).into(); 150 let h = HlTag::Operator(HlOperator::Other).into();
157 let is_unsafe = element 151 let is_unsafe = element
158 .parent() 152 .parent()
159 .and_then(ast::RefExpr::cast) 153 .and_then(ast::RefExpr::cast)
160 .map(|ref_expr| sema.is_unsafe_ref_expr(&ref_expr)) 154 .map_or(false, |ref_expr| sema.is_unsafe_ref_expr(&ref_expr));
161 .unwrap_or(false);
162 if is_unsafe { 155 if is_unsafe {
163 h | HlMod::Unsafe 156 h | HlMod::Unsafe
164 } else { 157 } else {
165 h 158 h
166 } 159 }
167 } 160 }
168 T![::] | T![->] | T![=>] | T![..] | T![=] | T![@] | T![.] => { 161 T![::] | T![->] | T![=>] | T![..] | T![=] | T![@] | T![.] => HlOperator::Other.into(),
169 HlTag::Operator(HlOperator::Other).into() 162 T![!] if parent_matches::<ast::MacroCall>(&element) => SymbolKind::Macro.into(),
170 } 163 T![!] if parent_matches::<ast::NeverType>(&element) => HlTag::BuiltinType.into(),
171 T![!] if element.parent().and_then(ast::MacroCall::cast).is_some() => { 164 T![!] if parent_matches::<ast::PrefixExpr>(&element) => HlOperator::Logical.into(),
172 HlTag::Symbol(SymbolKind::Macro).into() 165 T![*] if parent_matches::<ast::PtrType>(&element) => HlTag::Keyword.into(),
173 } 166 T![*] if parent_matches::<ast::PrefixExpr>(&element) => {
174 T![!] if element.parent().and_then(ast::NeverType::cast).is_some() => {
175 HlTag::BuiltinType.into()
176 }
177 T![!] if element.parent().and_then(ast::PrefixExpr::cast).is_some() => {
178 HlTag::Operator(HlOperator::Logical).into()
179 }
180 T![*] if element.parent().and_then(ast::PtrType::cast).is_some() => {
181 HlTag::Keyword.into()
182 }
183 T![*] if element.parent().and_then(ast::PrefixExpr::cast).is_some() => {
184 let prefix_expr = element.parent().and_then(ast::PrefixExpr::cast)?; 167 let prefix_expr = element.parent().and_then(ast::PrefixExpr::cast)?;
185 168
186 let expr = prefix_expr.expr()?; 169 let expr = prefix_expr.expr()?;
@@ -188,12 +171,12 @@ pub(super) fn element(
188 if ty.is_raw_ptr() { 171 if ty.is_raw_ptr() {
189 HlTag::Operator(HlOperator::Other) | HlMod::Unsafe 172 HlTag::Operator(HlOperator::Other) | HlMod::Unsafe
190 } else if let Some(ast::PrefixOp::Deref) = prefix_expr.op_kind() { 173 } else if let Some(ast::PrefixOp::Deref) = prefix_expr.op_kind() {
191 HlTag::Operator(HlOperator::Other).into() 174 HlOperator::Other.into()
192 } else { 175 } else {
193 HlTag::Punctuation(HlPunct::Other).into() 176 HlPunct::Other.into()
194 } 177 }
195 } 178 }
196 T![-] if element.parent().and_then(ast::PrefixExpr::cast).is_some() => { 179 T![-] if parent_matches::<ast::PrefixExpr>(&element) => {
197 let prefix_expr = element.parent().and_then(ast::PrefixExpr::cast)?; 180 let prefix_expr = element.parent().and_then(ast::PrefixExpr::cast)?;
198 181
199 let expr = prefix_expr.expr()?; 182 let expr = prefix_expr.expr()?;
@@ -203,41 +186,31 @@ pub(super) fn element(
203 } 186 }
204 .into() 187 .into()
205 } 188 }
206 _ if element.parent().and_then(ast::PrefixExpr::cast).is_some() => { 189 _ if parent_matches::<ast::PrefixExpr>(&element) => HlOperator::Other.into(),
207 HlTag::Operator(HlOperator::Other).into()
208 }
209 T![+] | T![-] | T![*] | T![/] | T![+=] | T![-=] | T![*=] | T![/=] 190 T![+] | T![-] | T![*] | T![/] | T![+=] | T![-=] | T![*=] | T![/=]
210 if element.parent().and_then(ast::BinExpr::cast).is_some() => 191 if parent_matches::<ast::BinExpr>(&element) =>
211 { 192 {
212 HlTag::Operator(HlOperator::Arithmetic).into() 193 HlOperator::Arithmetic.into()
213 } 194 }
214 T![|] | T![&] | T![!] | T![^] | T![|=] | T![&=] | T![^=] 195 T![|] | T![&] | T![!] | T![^] | T![|=] | T![&=] | T![^=]
215 if element.parent().and_then(ast::BinExpr::cast).is_some() => 196 if parent_matches::<ast::BinExpr>(&element) =>
216 { 197 {
217 HlTag::Operator(HlOperator::Bitwise).into() 198 HlOperator::Bitwise.into()
218 } 199 }
219 T![&&] | T![||] if element.parent().and_then(ast::BinExpr::cast).is_some() => { 200 T![&&] | T![||] if parent_matches::<ast::BinExpr>(&element) => {
220 HlTag::Operator(HlOperator::Logical).into() 201 HlOperator::Logical.into()
221 } 202 }
222 T![>] | T![<] | T![==] | T![>=] | T![<=] | T![!=] 203 T![>] | T![<] | T![==] | T![>=] | T![<=] | T![!=]
223 if element.parent().and_then(ast::BinExpr::cast).is_some() => 204 if parent_matches::<ast::BinExpr>(&element) =>
224 { 205 {
225 HlTag::Operator(HlOperator::Comparison).into() 206 HlOperator::Comparison.into()
226 }
227 _ if element.parent().and_then(ast::BinExpr::cast).is_some() => {
228 HlTag::Operator(HlOperator::Other).into()
229 }
230 _ if element.parent().and_then(ast::RangeExpr::cast).is_some() => {
231 HlTag::Operator(HlOperator::Other).into()
232 } 207 }
233 _ if element.parent().and_then(ast::RangePat::cast).is_some() => { 208 _ if parent_matches::<ast::BinExpr>(&element) => HlOperator::Other.into(),
234 HlTag::Operator(HlOperator::Other).into() 209 _ if parent_matches::<ast::RangeExpr>(&element) => HlOperator::Other.into(),
235 } 210 _ if parent_matches::<ast::RangePat>(&element) => HlOperator::Other.into(),
236 _ if element.parent().and_then(ast::RestPat::cast).is_some() => { 211 _ if parent_matches::<ast::RestPat>(&element) => HlOperator::Other.into(),
237 HlTag::Operator(HlOperator::Other).into() 212 _ if parent_matches::<ast::Attr>(&element) => HlTag::Attribute.into(),
238 } 213 kind => match kind {
239 _ if element.parent().and_then(ast::Attr::cast).is_some() => HlTag::Attribute.into(),
240 kind => HlTag::Punctuation(match kind {
241 T!['['] | T![']'] => HlPunct::Bracket, 214 T!['['] | T![']'] => HlPunct::Bracket,
242 T!['{'] | T!['}'] => HlPunct::Brace, 215 T!['{'] | T!['}'] => HlPunct::Brace,
243 T!['('] | T![')'] => HlPunct::Parenthesis, 216 T!['('] | T![')'] => HlPunct::Parenthesis,
@@ -247,22 +220,24 @@ pub(super) fn element(
247 T![;] => HlPunct::Semi, 220 T![;] => HlPunct::Semi,
248 T![.] => HlPunct::Dot, 221 T![.] => HlPunct::Dot,
249 _ => HlPunct::Other, 222 _ => HlPunct::Other,
250 }) 223 }
251 .into(), 224 .into(),
252 }, 225 },
253 226
254 k if k.is_keyword() => { 227 k if k.is_keyword() => {
255 let h = Highlight::new(HlTag::Keyword); 228 let h = Highlight::new(HlTag::Keyword);
256 match k { 229 match k {
257 T![break] 230 T![await]
231 | T![break]
258 | T![continue] 232 | T![continue]
259 | T![else] 233 | T![else]
260 | T![if] 234 | T![if]
235 | T![in]
261 | T![loop] 236 | T![loop]
262 | T![match] 237 | T![match]
263 | T![return] 238 | T![return]
264 | T![while] 239 | T![while]
265 | T![in] => h | HlMod::ControlFlow, 240 | T![yield] => h | HlMod::ControlFlow,
266 T![for] if !is_child_of_impl(&element) => h | HlMod::ControlFlow, 241 T![for] if !is_child_of_impl(&element) => h | HlMod::ControlFlow,
267 T![unsafe] => h | HlMod::Unsafe, 242 T![unsafe] => h | HlMod::Unsafe,
268 T![true] | T![false] => HlTag::BoolLiteral.into(), 243 T![true] | T![false] => HlTag::BoolLiteral.into(),
@@ -301,7 +276,6 @@ pub(super) fn element(
301 hash((name, shadow_count)) 276 hash((name, shadow_count))
302 } 277 }
303} 278}
304
305fn highlight_def(db: &RootDatabase, def: Definition) -> Highlight { 279fn highlight_def(db: &RootDatabase, def: Definition) -> Highlight {
306 match def { 280 match def {
307 Definition::Macro(_) => HlTag::Symbol(SymbolKind::Macro), 281 Definition::Macro(_) => HlTag::Symbol(SymbolKind::Macro),
@@ -312,17 +286,22 @@ fn highlight_def(db: &RootDatabase, def: Definition) -> Highlight {
312 let mut h = Highlight::new(HlTag::Symbol(SymbolKind::Function)); 286 let mut h = Highlight::new(HlTag::Symbol(SymbolKind::Function));
313 if let Some(item) = func.as_assoc_item(db) { 287 if let Some(item) = func.as_assoc_item(db) {
314 h |= HlMod::Associated; 288 h |= HlMod::Associated;
315 if func.self_param(db).is_none() { 289 match func.self_param(db) {
316 h |= HlMod::Static 290 Some(sp) => {
291 if let hir::Access::Exclusive = sp.access(db) {
292 h |= HlMod::Mutable;
293 }
294 }
295 None => h |= HlMod::Static,
317 } 296 }
318 297
319 match item.container(db) { 298 match item.container(db) {
320 AssocItemContainer::Impl(i) => { 299 hir::AssocItemContainer::Impl(i) => {
321 if i.trait_(db).is_some() { 300 if i.trait_(db).is_some() {
322 h |= HlMod::Trait; 301 h |= HlMod::Trait;
323 } 302 }
324 } 303 }
325 AssocItemContainer::Trait(_t) => { 304 hir::AssocItemContainer::Trait(_t) => {
326 h |= HlMod::Trait; 305 h |= HlMod::Trait;
327 } 306 }
328 } 307 }
@@ -342,12 +321,12 @@ fn highlight_def(db: &RootDatabase, def: Definition) -> Highlight {
342 if let Some(item) = konst.as_assoc_item(db) { 321 if let Some(item) = konst.as_assoc_item(db) {
343 h |= HlMod::Associated; 322 h |= HlMod::Associated;
344 match item.container(db) { 323 match item.container(db) {
345 AssocItemContainer::Impl(i) => { 324 hir::AssocItemContainer::Impl(i) => {
346 if i.trait_(db).is_some() { 325 if i.trait_(db).is_some() {
347 h |= HlMod::Trait; 326 h |= HlMod::Trait;
348 } 327 }
349 } 328 }
350 AssocItemContainer::Trait(_t) => { 329 hir::AssocItemContainer::Trait(_t) => {
351 h |= HlMod::Trait; 330 h |= HlMod::Trait;
352 } 331 }
353 } 332 }
@@ -361,12 +340,12 @@ fn highlight_def(db: &RootDatabase, def: Definition) -> Highlight {
361 if let Some(item) = type_.as_assoc_item(db) { 340 if let Some(item) = type_.as_assoc_item(db) {
362 h |= HlMod::Associated; 341 h |= HlMod::Associated;
363 match item.container(db) { 342 match item.container(db) {
364 AssocItemContainer::Impl(i) => { 343 hir::AssocItemContainer::Impl(i) => {
365 if i.trait_(db).is_some() { 344 if i.trait_(db).is_some() {
366 h |= HlMod::Trait; 345 h |= HlMod::Trait;
367 } 346 }
368 } 347 }
369 AssocItemContainer::Trait(_t) => { 348 hir::AssocItemContainer::Trait(_t) => {
370 h |= HlMod::Trait; 349 h |= HlMod::Trait;
371 } 350 }
372 } 351 }
@@ -425,7 +404,7 @@ fn highlight_method_call(
425 method_call: &ast::MethodCallExpr, 404 method_call: &ast::MethodCallExpr,
426) -> Option<Highlight> { 405) -> Option<Highlight> {
427 let func = sema.resolve_method_call(&method_call)?; 406 let func = sema.resolve_method_call(&method_call)?;
428 let mut h = HlTag::Symbol(SymbolKind::Function).into(); 407 let mut h = SymbolKind::Function.into();
429 h |= HlMod::Associated; 408 h |= HlMod::Associated;
430 if func.is_unsafe(sema.db) || sema.is_unsafe_method_call(&method_call) { 409 if func.is_unsafe(sema.db) || sema.is_unsafe_method_call(&method_call) {
431 h |= HlMod::Unsafe; 410 h |= HlMod::Unsafe;
@@ -461,20 +440,20 @@ fn highlight_name_by_syntax(name: ast::Name) -> Highlight {
461 }; 440 };
462 441
463 let tag = match parent.kind() { 442 let tag = match parent.kind() {
464 STRUCT => HlTag::Symbol(SymbolKind::Struct), 443 STRUCT => SymbolKind::Struct,
465 ENUM => HlTag::Symbol(SymbolKind::Enum), 444 ENUM => SymbolKind::Enum,
466 VARIANT => HlTag::Symbol(SymbolKind::Variant), 445 VARIANT => SymbolKind::Variant,
467 UNION => HlTag::Symbol(SymbolKind::Union), 446 UNION => SymbolKind::Union,
468 TRAIT => HlTag::Symbol(SymbolKind::Trait), 447 TRAIT => SymbolKind::Trait,
469 TYPE_ALIAS => HlTag::Symbol(SymbolKind::TypeAlias), 448 TYPE_ALIAS => SymbolKind::TypeAlias,
470 TYPE_PARAM => HlTag::Symbol(SymbolKind::TypeParam), 449 TYPE_PARAM => SymbolKind::TypeParam,
471 RECORD_FIELD => HlTag::Symbol(SymbolKind::Field), 450 RECORD_FIELD => SymbolKind::Field,
472 MODULE => HlTag::Symbol(SymbolKind::Module), 451 MODULE => SymbolKind::Module,
473 FN => HlTag::Symbol(SymbolKind::Function), 452 FN => SymbolKind::Function,
474 CONST => HlTag::Symbol(SymbolKind::Const), 453 CONST => SymbolKind::Const,
475 STATIC => HlTag::Symbol(SymbolKind::Static), 454 STATIC => SymbolKind::Static,
476 IDENT_PAT => HlTag::Symbol(SymbolKind::Local), 455 IDENT_PAT => SymbolKind::Local,
477 _ => default, 456 _ => return default.into(),
478 }; 457 };
479 458
480 tag.into() 459 tag.into()
@@ -492,20 +471,15 @@ fn highlight_name_ref_by_syntax(name: ast::NameRef, sema: &Semantics<RootDatabas
492 METHOD_CALL_EXPR => { 471 METHOD_CALL_EXPR => {
493 return ast::MethodCallExpr::cast(parent) 472 return ast::MethodCallExpr::cast(parent)
494 .and_then(|it| highlight_method_call(sema, &it)) 473 .and_then(|it| highlight_method_call(sema, &it))
495 .unwrap_or_else(|| HlTag::Symbol(SymbolKind::Function).into()); 474 .unwrap_or_else(|| SymbolKind::Function.into());
496 } 475 }
497 FIELD_EXPR => { 476 FIELD_EXPR => {
498 let h = HlTag::Symbol(SymbolKind::Field); 477 let h = HlTag::Symbol(SymbolKind::Field);
499 let is_union = ast::FieldExpr::cast(parent) 478 let is_union = ast::FieldExpr::cast(parent)
500 .and_then(|field_expr| { 479 .and_then(|field_expr| sema.resolve_field(&field_expr))
501 let field = sema.resolve_field(&field_expr)?; 480 .map_or(false, |field| {
502 Some(if let VariantDef::Union(_) = field.parent_def(sema.db) { 481 matches!(field.parent_def(sema.db), hir::VariantDef::Union(_))
503 true 482 });
504 } else {
505 false
506 })
507 })
508 .unwrap_or(false);
509 if is_union { 483 if is_union {
510 h | HlMod::Unsafe 484 h | HlMod::Unsafe
511 } else { 485 } else {
@@ -522,9 +496,9 @@ fn highlight_name_ref_by_syntax(name: ast::NameRef, sema: &Semantics<RootDatabas
522 _ => { 496 _ => {
523 // within path, decide whether it is module or adt by checking for uppercase name 497 // within path, decide whether it is module or adt by checking for uppercase name
524 return if name.text().chars().next().unwrap_or_default().is_uppercase() { 498 return if name.text().chars().next().unwrap_or_default().is_uppercase() {
525 HlTag::Symbol(SymbolKind::Struct) 499 SymbolKind::Struct
526 } else { 500 } else {
527 HlTag::Symbol(SymbolKind::Module) 501 SymbolKind::Module
528 } 502 }
529 .into(); 503 .into();
530 } 504 }
@@ -535,11 +509,11 @@ fn highlight_name_ref_by_syntax(name: ast::NameRef, sema: &Semantics<RootDatabas
535 }; 509 };
536 510
537 match parent.kind() { 511 match parent.kind() {
538 CALL_EXPR => HlTag::Symbol(SymbolKind::Function).into(), 512 CALL_EXPR => SymbolKind::Function.into(),
539 _ => if name.text().chars().next().unwrap_or_default().is_uppercase() { 513 _ => if name.text().chars().next().unwrap_or_default().is_uppercase() {
540 HlTag::Symbol(SymbolKind::Struct) 514 SymbolKind::Struct
541 } else { 515 } else {
542 HlTag::Symbol(SymbolKind::Const) 516 SymbolKind::Const
543 } 517 }
544 .into(), 518 .into(),
545 } 519 }
@@ -574,6 +548,11 @@ fn parents_match(mut node: NodeOrToken<SyntaxNode, SyntaxToken>, mut kinds: &[Sy
574 kinds.len() == 0 548 kinds.len() == 0
575} 549}
576 550
551#[inline]
552fn parent_matches<N: AstNode>(element: &SyntaxElement) -> bool {
553 element.parent().map_or(false, |it| N::can_cast(it.kind()))
554}
555
577fn is_child_of_impl(element: &SyntaxElement) -> bool { 556fn is_child_of_impl(element: &SyntaxElement) -> bool {
578 match element.parent() { 557 match element.parent() {
579 Some(e) => e.kind() == IMPL, 558 Some(e) => e.kind() == IMPL,