diff options
author | Dmitry <[email protected]> | 2020-08-09 14:35:51 +0100 |
---|---|---|
committer | Dmitry <[email protected]> | 2020-08-09 14:39:32 +0100 |
commit | 8068302fefc75440b823f4bf1731a5f347d7c767 (patch) | |
tree | 251b967182e79bc82a58c2fb208c688f6152df1f /crates/ra_ide/src/syntax_highlighting.rs | |
parent | 1a43a0f63e0008787225abb6fb2baef97b6a39e0 (diff) | |
parent | 8a57afe5a4bfab40072a83f7dc4ca560bf860919 (diff) |
Merge remote-tracking branch 'origin/master'
Diffstat (limited to 'crates/ra_ide/src/syntax_highlighting.rs')
-rw-r--r-- | crates/ra_ide/src/syntax_highlighting.rs | 97 |
1 files changed, 72 insertions, 25 deletions
diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs index d456d5d36..f71b804fe 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>, |
@@ -464,7 +476,7 @@ fn highlight_element( | |||
464 | let db = sema.db; | 476 | let db = sema.db; |
465 | let mut binding_hash = None; | 477 | let mut binding_hash = None; |
466 | let highlight: Highlight = match element.kind() { | 478 | let highlight: Highlight = match element.kind() { |
467 | FN_DEF => { | 479 | FN => { |
468 | bindings_shadow_count.clear(); | 480 | bindings_shadow_count.clear(); |
469 | return None; | 481 | return None; |
470 | } | 482 | } |
@@ -484,10 +496,19 @@ fn highlight_element( | |||
484 | 496 | ||
485 | match name_kind { | 497 | match name_kind { |
486 | Some(NameClass::Definition(def)) => { | 498 | Some(NameClass::Definition(def)) => { |
487 | highlight_name(db, def) | HighlightModifier::Definition | 499 | highlight_name(db, def, false) | HighlightModifier::Definition |
500 | } | ||
501 | Some(NameClass::ConstReference(def)) => highlight_name(db, def, false), | ||
502 | Some(NameClass::FieldShorthand { field, .. }) => { | ||
503 | let mut h = HighlightTag::Field.into(); | ||
504 | if let Definition::Field(field) = field { | ||
505 | if let VariantDef::Union(_) = field.parent_def(db) { | ||
506 | h |= HighlightModifier::Unsafe; | ||
507 | } | ||
508 | } | ||
509 | |||
510 | h | ||
488 | } | 511 | } |
489 | Some(NameClass::ConstReference(def)) => highlight_name(db, def), | ||
490 | Some(NameClass::FieldShorthand { .. }) => HighlightTag::Field.into(), | ||
491 | None => highlight_name_by_syntax(name) | HighlightModifier::Definition, | 512 | None => highlight_name_by_syntax(name) | HighlightModifier::Definition, |
492 | } | 513 | } |
493 | } | 514 | } |
@@ -498,6 +519,7 @@ fn highlight_element( | |||
498 | } | 519 | } |
499 | NAME_REF => { | 520 | NAME_REF => { |
500 | let name_ref = element.into_node().and_then(ast::NameRef::cast).unwrap(); | 521 | let name_ref = element.into_node().and_then(ast::NameRef::cast).unwrap(); |
522 | let possibly_unsafe = is_possibly_unsafe(&name_ref); | ||
501 | match classify_name_ref(sema, &name_ref) { | 523 | match classify_name_ref(sema, &name_ref) { |
502 | Some(name_kind) => match name_kind { | 524 | Some(name_kind) => match name_kind { |
503 | NameRefClass::Definition(def) => { | 525 | NameRefClass::Definition(def) => { |
@@ -508,11 +530,13 @@ fn highlight_element( | |||
508 | binding_hash = Some(calc_binding_hash(&name, *shadow_count)) | 530 | binding_hash = Some(calc_binding_hash(&name, *shadow_count)) |
509 | } | 531 | } |
510 | }; | 532 | }; |
511 | highlight_name(db, def) | 533 | highlight_name(db, def, possibly_unsafe) |
512 | } | 534 | } |
513 | NameRefClass::FieldShorthand { .. } => HighlightTag::Field.into(), | 535 | NameRefClass::FieldShorthand { .. } => HighlightTag::Field.into(), |
514 | }, | 536 | }, |
515 | None if syntactic_name_ref_highlighting => highlight_name_ref_by_syntax(name_ref), | 537 | None if syntactic_name_ref_highlighting => { |
538 | highlight_name_ref_by_syntax(name_ref, sema) | ||
539 | } | ||
516 | None => HighlightTag::UnresolvedReference.into(), | 540 | None => HighlightTag::UnresolvedReference.into(), |
517 | } | 541 | } |
518 | } | 542 | } |
@@ -546,7 +570,7 @@ fn highlight_element( | |||
546 | T![!] if element.parent().and_then(ast::MacroCall::cast).is_some() => { | 570 | T![!] if element.parent().and_then(ast::MacroCall::cast).is_some() => { |
547 | HighlightTag::Macro.into() | 571 | HighlightTag::Macro.into() |
548 | } | 572 | } |
549 | T![*] if element.parent().and_then(ast::PointerType::cast).is_some() => { | 573 | T![*] if element.parent().and_then(ast::PtrType::cast).is_some() => { |
550 | HighlightTag::Keyword.into() | 574 | HighlightTag::Keyword.into() |
551 | } | 575 | } |
552 | T![*] if element.parent().and_then(ast::PrefixExpr::cast).is_some() => { | 576 | T![*] if element.parent().and_then(ast::PrefixExpr::cast).is_some() => { |
@@ -577,7 +601,7 @@ fn highlight_element( | |||
577 | _ if element.parent().and_then(ast::RangePat::cast).is_some() => { | 601 | _ if element.parent().and_then(ast::RangePat::cast).is_some() => { |
578 | HighlightTag::Operator.into() | 602 | HighlightTag::Operator.into() |
579 | } | 603 | } |
580 | _ if element.parent().and_then(ast::DotDotPat::cast).is_some() => { | 604 | _ if element.parent().and_then(ast::RestPat::cast).is_some() => { |
581 | HighlightTag::Operator.into() | 605 | HighlightTag::Operator.into() |
582 | } | 606 | } |
583 | _ if element.parent().and_then(ast::Attr::cast).is_some() => { | 607 | _ if element.parent().and_then(ast::Attr::cast).is_some() => { |
@@ -647,15 +671,24 @@ fn highlight_element( | |||
647 | 671 | ||
648 | fn is_child_of_impl(element: &SyntaxElement) -> bool { | 672 | fn is_child_of_impl(element: &SyntaxElement) -> bool { |
649 | match element.parent() { | 673 | match element.parent() { |
650 | Some(e) => e.kind() == IMPL_DEF, | 674 | Some(e) => e.kind() == IMPL, |
651 | _ => false, | 675 | _ => false, |
652 | } | 676 | } |
653 | } | 677 | } |
654 | 678 | ||
655 | fn highlight_name(db: &RootDatabase, def: Definition) -> Highlight { | 679 | fn highlight_name(db: &RootDatabase, def: Definition, possibly_unsafe: bool) -> Highlight { |
656 | match def { | 680 | match def { |
657 | Definition::Macro(_) => HighlightTag::Macro, | 681 | Definition::Macro(_) => HighlightTag::Macro, |
658 | Definition::Field(_) => HighlightTag::Field, | 682 | Definition::Field(field) => { |
683 | let mut h = HighlightTag::Field.into(); | ||
684 | if possibly_unsafe { | ||
685 | if let VariantDef::Union(_) = field.parent_def(db) { | ||
686 | h |= HighlightModifier::Unsafe; | ||
687 | } | ||
688 | } | ||
689 | |||
690 | return h; | ||
691 | } | ||
659 | Definition::ModuleDef(def) => match def { | 692 | Definition::ModuleDef(def) => match def { |
660 | hir::ModuleDef::Module(_) => HighlightTag::Module, | 693 | hir::ModuleDef::Module(_) => HighlightTag::Module, |
661 | hir::ModuleDef::Function(func) => { | 694 | hir::ModuleDef::Function(func) => { |
@@ -677,6 +710,7 @@ fn highlight_name(db: &RootDatabase, def: Definition) -> Highlight { | |||
677 | let mut h = Highlight::new(HighlightTag::Static); | 710 | let mut h = Highlight::new(HighlightTag::Static); |
678 | if s.is_mut(db) { | 711 | if s.is_mut(db) { |
679 | h |= HighlightModifier::Mutable; | 712 | h |= HighlightModifier::Mutable; |
713 | h |= HighlightModifier::Unsafe; | ||
680 | } | 714 | } |
681 | return h; | 715 | return h; |
682 | } | 716 | } |
@@ -705,26 +739,26 @@ fn highlight_name_by_syntax(name: ast::Name) -> Highlight { | |||
705 | }; | 739 | }; |
706 | 740 | ||
707 | let tag = match parent.kind() { | 741 | let tag = match parent.kind() { |
708 | STRUCT_DEF => HighlightTag::Struct, | 742 | STRUCT => HighlightTag::Struct, |
709 | ENUM_DEF => HighlightTag::Enum, | 743 | ENUM => HighlightTag::Enum, |
710 | UNION_DEF => HighlightTag::Union, | 744 | UNION => HighlightTag::Union, |
711 | TRAIT_DEF => HighlightTag::Trait, | 745 | TRAIT => HighlightTag::Trait, |
712 | TYPE_ALIAS_DEF => HighlightTag::TypeAlias, | 746 | TYPE_ALIAS => HighlightTag::TypeAlias, |
713 | TYPE_PARAM => HighlightTag::TypeParam, | 747 | TYPE_PARAM => HighlightTag::TypeParam, |
714 | RECORD_FIELD_DEF => HighlightTag::Field, | 748 | RECORD_FIELD => HighlightTag::Field, |
715 | MODULE => HighlightTag::Module, | 749 | MODULE => HighlightTag::Module, |
716 | FN_DEF => HighlightTag::Function, | 750 | FN => HighlightTag::Function, |
717 | CONST_DEF => HighlightTag::Constant, | 751 | CONST => HighlightTag::Constant, |
718 | STATIC_DEF => HighlightTag::Static, | 752 | STATIC => HighlightTag::Static, |
719 | ENUM_VARIANT => HighlightTag::EnumVariant, | 753 | VARIANT => HighlightTag::EnumVariant, |
720 | BIND_PAT => HighlightTag::Local, | 754 | IDENT_PAT => HighlightTag::Local, |
721 | _ => default, | 755 | _ => default, |
722 | }; | 756 | }; |
723 | 757 | ||
724 | tag.into() | 758 | tag.into() |
725 | } | 759 | } |
726 | 760 | ||
727 | fn highlight_name_ref_by_syntax(name: ast::NameRef) -> Highlight { | 761 | fn highlight_name_ref_by_syntax(name: ast::NameRef, sema: &Semantics<RootDatabase>) -> Highlight { |
728 | let default = HighlightTag::UnresolvedReference; | 762 | let default = HighlightTag::UnresolvedReference; |
729 | 763 | ||
730 | let parent = match name.syntax().parent() { | 764 | let parent = match name.syntax().parent() { |
@@ -734,7 +768,20 @@ fn highlight_name_ref_by_syntax(name: ast::NameRef) -> Highlight { | |||
734 | 768 | ||
735 | let tag = match parent.kind() { | 769 | let tag = match parent.kind() { |
736 | METHOD_CALL_EXPR => HighlightTag::Function, | 770 | METHOD_CALL_EXPR => HighlightTag::Function, |
737 | FIELD_EXPR => HighlightTag::Field, | 771 | FIELD_EXPR => { |
772 | let h = HighlightTag::Field; | ||
773 | let is_union = ast::FieldExpr::cast(parent) | ||
774 | .and_then(|field_expr| { | ||
775 | let field = sema.resolve_field(&field_expr)?; | ||
776 | Some(if let VariantDef::Union(_) = field.parent_def(sema.db) { | ||
777 | true | ||
778 | } else { | ||
779 | false | ||
780 | }) | ||
781 | }) | ||
782 | .unwrap_or(false); | ||
783 | return if is_union { h | HighlightModifier::Unsafe } else { h.into() }; | ||
784 | } | ||
738 | PATH_SEGMENT => { | 785 | PATH_SEGMENT => { |
739 | let path = match parent.parent().and_then(ast::Path::cast) { | 786 | let path = match parent.parent().and_then(ast::Path::cast) { |
740 | Some(it) => it, | 787 | Some(it) => it, |