aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide/src/syntax_highlighting.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide/src/syntax_highlighting.rs')
-rw-r--r--crates/ra_ide/src/syntax_highlighting.rs66
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)]
5mod tests; 5mod tests;
6 6
7use hir::{Name, Semantics}; 7use hir::{Name, Semantics, VariantDef};
8use ra_ide_db::{ 8use 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
458fn 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
458fn highlight_element( 470fn 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
657fn highlight_name(db: &RootDatabase, def: Definition) -> Highlight { 681fn 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
730fn highlight_name_ref_by_syntax(name: ast::NameRef) -> Highlight { 763fn 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,