diff options
Diffstat (limited to 'crates/ra_ide/src/syntax_highlighting.rs')
-rw-r--r-- | crates/ra_ide/src/syntax_highlighting.rs | 66 |
1 files changed, 56 insertions, 10 deletions
diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs index ec442bcd8..6b7874460 100644 --- a/crates/ra_ide/src/syntax_highlighting.rs +++ b/crates/ra_ide/src/syntax_highlighting.rs | |||
@@ -4,7 +4,7 @@ mod injection; | |||
4 | #[cfg(test)] | 4 | #[cfg(test)] |
5 | mod tests; | 5 | mod tests; |
6 | 6 | ||
7 | use hir::{Name, Semantics}; | 7 | use hir::{Name, Semantics, VariantDef}; |
8 | use ra_ide_db::{ | 8 | use ra_ide_db::{ |
9 | defs::{classify_name, classify_name_ref, Definition, NameClass, NameRefClass}, | 9 | defs::{classify_name, classify_name_ref, Definition, NameClass, NameRefClass}, |
10 | RootDatabase, | 10 | RootDatabase, |
@@ -455,6 +455,18 @@ fn macro_call_range(macro_call: &ast::MacroCall) -> Option<TextRange> { | |||
455 | Some(TextRange::new(range_start, range_end)) | 455 | Some(TextRange::new(range_start, range_end)) |
456 | } | 456 | } |
457 | 457 | ||
458 | fn is_possibly_unsafe(name_ref: &ast::NameRef) -> bool { | ||
459 | name_ref | ||
460 | .syntax() | ||
461 | .parent() | ||
462 | .and_then(|parent| { | ||
463 | ast::FieldExpr::cast(parent.clone()) | ||
464 | .map(|_| true) | ||
465 | .or_else(|| ast::RecordPatField::cast(parent).map(|_| true)) | ||
466 | }) | ||
467 | .unwrap_or(false) | ||
468 | } | ||
469 | |||
458 | fn highlight_element( | 470 | fn highlight_element( |
459 | sema: &Semantics<RootDatabase>, | 471 | sema: &Semantics<RootDatabase>, |
460 | bindings_shadow_count: &mut FxHashMap<Name, u32>, | 472 | bindings_shadow_count: &mut FxHashMap<Name, u32>, |
@@ -485,10 +497,19 @@ fn highlight_element( | |||
485 | match name_kind { | 497 | match name_kind { |
486 | Some(NameClass::ExternCrate(_)) => HighlightTag::Module.into(), | 498 | Some(NameClass::ExternCrate(_)) => HighlightTag::Module.into(), |
487 | Some(NameClass::Definition(def)) => { | 499 | Some(NameClass::Definition(def)) => { |
488 | highlight_name(db, def) | HighlightModifier::Definition | 500 | highlight_name(db, def, false) | HighlightModifier::Definition |
501 | } | ||
502 | Some(NameClass::ConstReference(def)) => highlight_name(db, def, false), | ||
503 | Some(NameClass::FieldShorthand { field, .. }) => { | ||
504 | let mut h = HighlightTag::Field.into(); | ||
505 | if let Definition::Field(field) = field { | ||
506 | if let VariantDef::Union(_) = field.parent_def(db) { | ||
507 | h |= HighlightModifier::Unsafe; | ||
508 | } | ||
509 | } | ||
510 | |||
511 | h | ||
489 | } | 512 | } |
490 | Some(NameClass::ConstReference(def)) => highlight_name(db, def), | ||
491 | Some(NameClass::FieldShorthand { .. }) => HighlightTag::Field.into(), | ||
492 | None => highlight_name_by_syntax(name) | HighlightModifier::Definition, | 513 | None => highlight_name_by_syntax(name) | HighlightModifier::Definition, |
493 | } | 514 | } |
494 | } | 515 | } |
@@ -499,6 +520,7 @@ fn highlight_element( | |||
499 | } | 520 | } |
500 | NAME_REF => { | 521 | NAME_REF => { |
501 | let name_ref = element.into_node().and_then(ast::NameRef::cast).unwrap(); | 522 | let name_ref = element.into_node().and_then(ast::NameRef::cast).unwrap(); |
523 | let possibly_unsafe = is_possibly_unsafe(&name_ref); | ||
502 | match classify_name_ref(sema, &name_ref) { | 524 | match classify_name_ref(sema, &name_ref) { |
503 | Some(name_kind) => match name_kind { | 525 | Some(name_kind) => match name_kind { |
504 | NameRefClass::ExternCrate(_) => HighlightTag::Module.into(), | 526 | NameRefClass::ExternCrate(_) => HighlightTag::Module.into(), |
@@ -510,11 +532,13 @@ fn highlight_element( | |||
510 | binding_hash = Some(calc_binding_hash(&name, *shadow_count)) | 532 | binding_hash = Some(calc_binding_hash(&name, *shadow_count)) |
511 | } | 533 | } |
512 | }; | 534 | }; |
513 | highlight_name(db, def) | 535 | highlight_name(db, def, possibly_unsafe) |
514 | } | 536 | } |
515 | NameRefClass::FieldShorthand { .. } => HighlightTag::Field.into(), | 537 | NameRefClass::FieldShorthand { .. } => HighlightTag::Field.into(), |
516 | }, | 538 | }, |
517 | None if syntactic_name_ref_highlighting => highlight_name_ref_by_syntax(name_ref), | 539 | None if syntactic_name_ref_highlighting => { |
540 | highlight_name_ref_by_syntax(name_ref, sema) | ||
541 | } | ||
518 | None => HighlightTag::UnresolvedReference.into(), | 542 | None => HighlightTag::UnresolvedReference.into(), |
519 | } | 543 | } |
520 | } | 544 | } |
@@ -654,10 +678,19 @@ fn is_child_of_impl(element: &SyntaxElement) -> bool { | |||
654 | } | 678 | } |
655 | } | 679 | } |
656 | 680 | ||
657 | fn highlight_name(db: &RootDatabase, def: Definition) -> Highlight { | 681 | fn highlight_name(db: &RootDatabase, def: Definition, possibly_unsafe: bool) -> Highlight { |
658 | match def { | 682 | match def { |
659 | Definition::Macro(_) => HighlightTag::Macro, | 683 | Definition::Macro(_) => HighlightTag::Macro, |
660 | Definition::Field(_) => HighlightTag::Field, | 684 | Definition::Field(field) => { |
685 | let mut h = HighlightTag::Field.into(); | ||
686 | if possibly_unsafe { | ||
687 | if let VariantDef::Union(_) = field.parent_def(db) { | ||
688 | h |= HighlightModifier::Unsafe; | ||
689 | } | ||
690 | } | ||
691 | |||
692 | return h; | ||
693 | } | ||
661 | Definition::ModuleDef(def) => match def { | 694 | Definition::ModuleDef(def) => match def { |
662 | hir::ModuleDef::Module(_) => HighlightTag::Module, | 695 | hir::ModuleDef::Module(_) => HighlightTag::Module, |
663 | hir::ModuleDef::Function(func) => { | 696 | hir::ModuleDef::Function(func) => { |
@@ -727,7 +760,7 @@ fn highlight_name_by_syntax(name: ast::Name) -> Highlight { | |||
727 | tag.into() | 760 | tag.into() |
728 | } | 761 | } |
729 | 762 | ||
730 | fn highlight_name_ref_by_syntax(name: ast::NameRef) -> Highlight { | 763 | fn highlight_name_ref_by_syntax(name: ast::NameRef, sema: &Semantics<RootDatabase>) -> Highlight { |
731 | let default = HighlightTag::UnresolvedReference; | 764 | let default = HighlightTag::UnresolvedReference; |
732 | 765 | ||
733 | let parent = match name.syntax().parent() { | 766 | let parent = match name.syntax().parent() { |
@@ -737,7 +770,20 @@ fn highlight_name_ref_by_syntax(name: ast::NameRef) -> Highlight { | |||
737 | 770 | ||
738 | let tag = match parent.kind() { | 771 | let tag = match parent.kind() { |
739 | METHOD_CALL_EXPR => HighlightTag::Function, | 772 | METHOD_CALL_EXPR => HighlightTag::Function, |
740 | FIELD_EXPR => HighlightTag::Field, | 773 | FIELD_EXPR => { |
774 | let h = HighlightTag::Field; | ||
775 | let is_union = ast::FieldExpr::cast(parent) | ||
776 | .and_then(|field_expr| { | ||
777 | let field = sema.resolve_field(&field_expr)?; | ||
778 | Some(if let VariantDef::Union(_) = field.parent_def(sema.db) { | ||
779 | true | ||
780 | } else { | ||
781 | false | ||
782 | }) | ||
783 | }) | ||
784 | .unwrap_or(false); | ||
785 | return if is_union { h | HighlightModifier::Unsafe } else { h.into() }; | ||
786 | } | ||
741 | PATH_SEGMENT => { | 787 | PATH_SEGMENT => { |
742 | let path = match parent.parent().and_then(ast::Path::cast) { | 788 | let path = match parent.parent().and_then(ast::Path::cast) { |
743 | Some(it) => it, | 789 | Some(it) => it, |