aboutsummaryrefslogtreecommitdiff
path: root/crates/ide/src/syntax_highlighting.rs
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2020-08-19 12:27:02 +0100
committerGitHub <[email protected]>2020-08-19 12:27:02 +0100
commit529ca7e5e0573e15b23cd0067a691bf1ffebae84 (patch)
tree0cc09513805718a7c31cadb1776ff4eb865caaef /crates/ide/src/syntax_highlighting.rs
parentc1cfd010096daa85f8acd6f1ea15d92097816e14 (diff)
parent3456e2eec7c1e18734f8fa41924a83b4c676dc00 (diff)
Merge #5643
5643: Add new consuming modifier, apply consuming and mutable to methods r=matklad a=Nashenas88 This adds a new `consuming` semantic modifier for syntax highlighters. This also emits `mutable` and `consuming` in two cases: - When a method takes `&mut self`, then it now has `function.mutable` emitted. - When a method takes `self`, and the type of `Self` is not `Copy`, then `function.consuming` is emitted. CC @flodiebold Co-authored-by: Paul Daniel Faria <[email protected]>
Diffstat (limited to 'crates/ide/src/syntax_highlighting.rs')
-rw-r--r--crates/ide/src/syntax_highlighting.rs117
1 files changed, 74 insertions, 43 deletions
diff --git a/crates/ide/src/syntax_highlighting.rs b/crates/ide/src/syntax_highlighting.rs
index 5d7c7e8d0..9827c68af 100644
--- a/crates/ide/src/syntax_highlighting.rs
+++ b/crates/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, VariantDef}; 7use hir::{Mutability, Name, SelfKind, Semantics, VariantDef};
8use ide_db::{ 8use 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,
@@ -519,27 +519,29 @@ fn highlight_element(
519 } 519 }
520 NAME_REF => { 520 NAME_REF => {
521 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); 522 highlight_func_by_name_ref(sema, &name_ref).unwrap_or_else(|| {
523 match classify_name_ref(sema, &name_ref) { 523 let possibly_unsafe = is_possibly_unsafe(&name_ref);
524 Some(name_kind) => match name_kind { 524 match classify_name_ref(sema, &name_ref) {
525 NameRefClass::ExternCrate(_) => HighlightTag::Module.into(), 525 Some(name_kind) => match name_kind {
526 NameRefClass::Definition(def) => { 526 NameRefClass::ExternCrate(_) => HighlightTag::Module.into(),
527 if let Definition::Local(local) = &def { 527 NameRefClass::Definition(def) => {
528 if let Some(name) = local.name(db) { 528 if let Definition::Local(local) = &def {
529 let shadow_count = 529 if let Some(name) = local.name(db) {
530 bindings_shadow_count.entry(name.clone()).or_default(); 530 let shadow_count =
531 binding_hash = Some(calc_binding_hash(&name, *shadow_count)) 531 bindings_shadow_count.entry(name.clone()).or_default();
532 } 532 binding_hash = Some(calc_binding_hash(&name, *shadow_count))
533 }; 533 }
534 highlight_name(sema, db, def, Some(name_ref), possibly_unsafe) 534 };
535 highlight_name(sema, db, def, Some(name_ref), possibly_unsafe)
536 }
537 NameRefClass::FieldShorthand { .. } => HighlightTag::Field.into(),
538 },
539 None if syntactic_name_ref_highlighting => {
540 highlight_name_ref_by_syntax(name_ref, sema)
535 } 541 }
536 NameRefClass::FieldShorthand { .. } => HighlightTag::Field.into(), 542 None => HighlightTag::UnresolvedReference.into(),
537 },
538 None if syntactic_name_ref_highlighting => {
539 highlight_name_ref_by_syntax(name_ref, sema)
540 } 543 }
541 None => HighlightTag::UnresolvedReference.into(), 544 })
542 }
543 } 545 }
544 546
545 // Simple token-based highlighting 547 // Simple token-based highlighting
@@ -700,6 +702,35 @@ fn is_child_of_impl(element: &SyntaxElement) -> bool {
700 } 702 }
701} 703}
702 704
705fn highlight_func_by_name_ref(
706 sema: &Semantics<RootDatabase>,
707 name_ref: &ast::NameRef,
708) -> Option<Highlight> {
709 let parent = name_ref.syntax().parent()?;
710 let method_call = ast::MethodCallExpr::cast(parent)?;
711 highlight_method_call(sema, &method_call)
712}
713
714fn highlight_method_call(
715 sema: &Semantics<RootDatabase>,
716 method_call: &ast::MethodCallExpr,
717) -> Option<Highlight> {
718 let func = sema.resolve_method_call(&method_call)?;
719 let mut h = HighlightTag::Function.into();
720 if func.is_unsafe(sema.db) || sema.is_unsafe_method_call(&method_call) {
721 h |= HighlightModifier::Unsafe;
722 }
723
724 sema.method_reciever_kind(&method_call)
725 .map(|self_kind| match self_kind {
726 SelfKind::Shared => h,
727 SelfKind::Mutable => h | HighlightModifier::Mutable,
728 SelfKind::Consuming => h | HighlightModifier::Consuming,
729 SelfKind::Copied => h,
730 })
731 .or_else(|| Some(h))
732}
733
703fn highlight_name( 734fn highlight_name(
704 sema: &Semantics<RootDatabase>, 735 sema: &Semantics<RootDatabase>,
705 db: &RootDatabase, 736 db: &RootDatabase,
@@ -722,20 +753,26 @@ fn highlight_name(
722 Definition::ModuleDef(def) => match def { 753 Definition::ModuleDef(def) => match def {
723 hir::ModuleDef::Module(_) => HighlightTag::Module, 754 hir::ModuleDef::Module(_) => HighlightTag::Module,
724 hir::ModuleDef::Function(func) => { 755 hir::ModuleDef::Function(func) => {
725 let mut h = HighlightTag::Function.into(); 756 return name_ref
726 if func.is_unsafe(db) { 757 .and_then(|name_ref| highlight_func_by_name_ref(sema, &name_ref))
727 h |= HighlightModifier::Unsafe; 758 .unwrap_or_else(|| {
728 } else { 759 let mut h = HighlightTag::Function.into();
729 let is_unsafe = name_ref 760 if func.is_unsafe(db) {
730 .and_then(|name_ref| name_ref.syntax().parent()) 761 h |= HighlightModifier::Unsafe;
731 .and_then(ast::MethodCallExpr::cast) 762 }
732 .map(|method_call_expr| sema.is_unsafe_method_call(method_call_expr)) 763
733 .unwrap_or(false); 764 return if func.has_self_param(db) {
734 if is_unsafe { 765 match func.mutability_of_self_param(db) {
735 h |= HighlightModifier::Unsafe; 766 Some(mutability) => match mutability {
736 } 767 Mutability::Mut => h | HighlightModifier::Mutable,
737 } 768 Mutability::Shared => h,
738 return h; 769 },
770 None => h,
771 }
772 } else {
773 h
774 };
775 });
739 } 776 }
740 hir::ModuleDef::Adt(hir::Adt::Struct(_)) => HighlightTag::Struct, 777 hir::ModuleDef::Adt(hir::Adt::Struct(_)) => HighlightTag::Struct,
741 hir::ModuleDef::Adt(hir::Adt::Enum(_)) => HighlightTag::Enum, 778 hir::ModuleDef::Adt(hir::Adt::Enum(_)) => HighlightTag::Enum,
@@ -807,15 +844,9 @@ fn highlight_name_ref_by_syntax(name: ast::NameRef, sema: &Semantics<RootDatabas
807 844
808 match parent.kind() { 845 match parent.kind() {
809 METHOD_CALL_EXPR => { 846 METHOD_CALL_EXPR => {
810 let mut h = Highlight::new(HighlightTag::Function); 847 return ast::MethodCallExpr::cast(parent)
811 let is_unsafe = ast::MethodCallExpr::cast(parent) 848 .and_then(|method_call| highlight_method_call(sema, &method_call))
812 .map(|method_call_expr| sema.is_unsafe_method_call(method_call_expr)) 849 .unwrap_or_else(|| HighlightTag::Function.into());
813 .unwrap_or(false);
814 if is_unsafe {
815 h |= HighlightModifier::Unsafe;
816 }
817
818 h
819 } 850 }
820 FIELD_EXPR => { 851 FIELD_EXPR => {
821 let h = HighlightTag::Field; 852 let h = HighlightTag::Field;