diff options
author | Paul Daniel Faria <[email protected]> | 2020-06-27 22:11:43 +0100 |
---|---|---|
committer | Paul Daniel Faria <[email protected]> | 2020-08-10 13:44:54 +0100 |
commit | d5f11e530dbf6edbdd0ca32d6cd5fafe634c8c4a (patch) | |
tree | b348ea6d5552be08913ac3a451836cad5ac75c1a /crates/ra_ide/src/syntax_highlighting.rs | |
parent | 38440d53d8329ac9f3f2013c6e32b3f69b069c72 (diff) |
Unsafe borrow of packed fields: account for borrow through ref binding, auto ref function calls
Diffstat (limited to 'crates/ra_ide/src/syntax_highlighting.rs')
-rw-r--r-- | crates/ra_ide/src/syntax_highlighting.rs | 137 |
1 files changed, 117 insertions, 20 deletions
diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs index a4a7aa228..454fef39c 100644 --- a/crates/ra_ide/src/syntax_highlighting.rs +++ b/crates/ra_ide/src/syntax_highlighting.rs | |||
@@ -497,9 +497,9 @@ fn highlight_element( | |||
497 | match name_kind { | 497 | match name_kind { |
498 | Some(NameClass::ExternCrate(_)) => HighlightTag::Module.into(), | 498 | Some(NameClass::ExternCrate(_)) => HighlightTag::Module.into(), |
499 | Some(NameClass::Definition(def)) => { | 499 | Some(NameClass::Definition(def)) => { |
500 | highlight_name(db, def, false) | HighlightModifier::Definition | 500 | highlight_name(sema, db, def, None, false) | HighlightModifier::Definition |
501 | } | 501 | } |
502 | Some(NameClass::ConstReference(def)) => highlight_name(db, def, false), | 502 | Some(NameClass::ConstReference(def)) => highlight_name(sema, db, def, None, false), |
503 | Some(NameClass::FieldShorthand { field, .. }) => { | 503 | Some(NameClass::FieldShorthand { field, .. }) => { |
504 | let mut h = HighlightTag::Field.into(); | 504 | let mut h = HighlightTag::Field.into(); |
505 | if let Definition::Field(field) = field { | 505 | if let Definition::Field(field) = field { |
@@ -532,7 +532,7 @@ fn highlight_element( | |||
532 | binding_hash = Some(calc_binding_hash(&name, *shadow_count)) | 532 | binding_hash = Some(calc_binding_hash(&name, *shadow_count)) |
533 | } | 533 | } |
534 | }; | 534 | }; |
535 | highlight_name(db, def, possibly_unsafe) | 535 | highlight_name(sema, db, def, Some(name_ref), possibly_unsafe) |
536 | } | 536 | } |
537 | NameRefClass::FieldShorthand { .. } => HighlightTag::Field.into(), | 537 | NameRefClass::FieldShorthand { .. } => HighlightTag::Field.into(), |
538 | }, | 538 | }, |
@@ -565,8 +565,8 @@ fn highlight_element( | |||
565 | _ => h, | 565 | _ => h, |
566 | } | 566 | } |
567 | } | 567 | } |
568 | REF_EXPR => { | 568 | T![&] => { |
569 | let ref_expr = element.into_node().and_then(ast::RefExpr::cast)?; | 569 | let ref_expr = element.parent().and_then(ast::RefExpr::cast)?; |
570 | let expr = ref_expr.expr()?; | 570 | let expr = ref_expr.expr()?; |
571 | let field_expr = match expr { | 571 | let field_expr = match expr { |
572 | ast::Expr::FieldExpr(fe) => fe, | 572 | ast::Expr::FieldExpr(fe) => fe, |
@@ -668,6 +668,52 @@ fn highlight_element( | |||
668 | HighlightTag::SelfKeyword.into() | 668 | HighlightTag::SelfKeyword.into() |
669 | } | 669 | } |
670 | } | 670 | } |
671 | T![ref] => { | ||
672 | let modifier: Option<HighlightModifier> = (|| { | ||
673 | let bind_pat = element.parent().and_then(ast::BindPat::cast)?; | ||
674 | let parent = bind_pat.syntax().parent()?; | ||
675 | |||
676 | let ty = if let Some(pat_list) = | ||
677 | ast::RecordFieldPatList::cast(parent.clone()) | ||
678 | { | ||
679 | let record_pat = | ||
680 | pat_list.syntax().parent().and_then(ast::RecordPat::cast)?; | ||
681 | sema.type_of_pat(&ast::Pat::RecordPat(record_pat)) | ||
682 | } else if let Some(let_stmt) = ast::LetStmt::cast(parent.clone()) { | ||
683 | let field_expr = | ||
684 | if let ast::Expr::FieldExpr(field_expr) = let_stmt.initializer()? { | ||
685 | field_expr | ||
686 | } else { | ||
687 | return None; | ||
688 | }; | ||
689 | |||
690 | sema.type_of_expr(&field_expr.expr()?) | ||
691 | } else if let Some(record_field_pat) = ast::RecordFieldPat::cast(parent) { | ||
692 | let record_pat = record_field_pat | ||
693 | .syntax() | ||
694 | .parent() | ||
695 | .and_then(ast::RecordFieldPatList::cast)? | ||
696 | .syntax() | ||
697 | .parent() | ||
698 | .and_then(ast::RecordPat::cast)?; | ||
699 | sema.type_of_pat(&ast::Pat::RecordPat(record_pat)) | ||
700 | } else { | ||
701 | None | ||
702 | }?; | ||
703 | |||
704 | if !ty.is_packed(db) { | ||
705 | return None; | ||
706 | } | ||
707 | |||
708 | Some(HighlightModifier::Unsafe) | ||
709 | })(); | ||
710 | |||
711 | if let Some(modifier) = modifier { | ||
712 | h | modifier | ||
713 | } else { | ||
714 | h | ||
715 | } | ||
716 | } | ||
671 | _ => h, | 717 | _ => h, |
672 | } | 718 | } |
673 | } | 719 | } |
@@ -697,7 +743,13 @@ fn is_child_of_impl(element: &SyntaxElement) -> bool { | |||
697 | } | 743 | } |
698 | } | 744 | } |
699 | 745 | ||
700 | fn highlight_name(db: &RootDatabase, def: Definition, possibly_unsafe: bool) -> Highlight { | 746 | fn highlight_name( |
747 | sema: &Semantics<RootDatabase>, | ||
748 | db: &RootDatabase, | ||
749 | def: Definition, | ||
750 | name_ref: Option<ast::NameRef>, | ||
751 | possibly_unsafe: bool, | ||
752 | ) -> Highlight { | ||
701 | match def { | 753 | match def { |
702 | Definition::Macro(_) => HighlightTag::Macro, | 754 | Definition::Macro(_) => HighlightTag::Macro, |
703 | Definition::Field(field) => { | 755 | Definition::Field(field) => { |
@@ -716,6 +768,29 @@ fn highlight_name(db: &RootDatabase, def: Definition, possibly_unsafe: bool) -> | |||
716 | let mut h = HighlightTag::Function.into(); | 768 | let mut h = HighlightTag::Function.into(); |
717 | if func.is_unsafe(db) { | 769 | if func.is_unsafe(db) { |
718 | h |= HighlightModifier::Unsafe; | 770 | h |= HighlightModifier::Unsafe; |
771 | } else { | ||
772 | (|| { | ||
773 | let method_call_expr = | ||
774 | name_ref?.syntax().parent().and_then(ast::MethodCallExpr::cast)?; | ||
775 | let expr = method_call_expr.expr()?; | ||
776 | let field_expr = if let ast::Expr::FieldExpr(field_expr) = expr { | ||
777 | Some(field_expr) | ||
778 | } else { | ||
779 | None | ||
780 | }?; | ||
781 | let ty = sema.type_of_expr(&field_expr.expr()?)?; | ||
782 | if !ty.is_packed(db) { | ||
783 | return None; | ||
784 | } | ||
785 | |||
786 | let func = sema.resolve_method_call(&method_call_expr)?; | ||
787 | if func.self_param(db)?.is_ref { | ||
788 | Some(HighlightModifier::Unsafe) | ||
789 | } else { | ||
790 | None | ||
791 | } | ||
792 | })() | ||
793 | .map(|modifier| h |= modifier); | ||
719 | } | 794 | } |
720 | return h; | 795 | return h; |
721 | } | 796 | } |
@@ -787,8 +862,33 @@ fn highlight_name_ref_by_syntax(name: ast::NameRef, sema: &Semantics<RootDatabas | |||
787 | _ => return default.into(), | 862 | _ => return default.into(), |
788 | }; | 863 | }; |
789 | 864 | ||
790 | let tag = match parent.kind() { | 865 | match parent.kind() { |
791 | METHOD_CALL_EXPR => HighlightTag::Function, | 866 | METHOD_CALL_EXPR => { |
867 | let mut h = Highlight::new(HighlightTag::Function); | ||
868 | let modifier: Option<HighlightModifier> = (|| { | ||
869 | let method_call_expr = ast::MethodCallExpr::cast(parent)?; | ||
870 | let expr = method_call_expr.expr()?; | ||
871 | let field_expr = if let ast::Expr::FieldExpr(field_expr) = expr { | ||
872 | field_expr | ||
873 | } else { | ||
874 | return None; | ||
875 | }; | ||
876 | |||
877 | let expr = field_expr.expr()?; | ||
878 | let ty = sema.type_of_expr(&expr)?; | ||
879 | if ty.is_packed(sema.db) { | ||
880 | Some(HighlightModifier::Unsafe) | ||
881 | } else { | ||
882 | None | ||
883 | } | ||
884 | })(); | ||
885 | |||
886 | if let Some(modifier) = modifier { | ||
887 | h |= modifier; | ||
888 | } | ||
889 | |||
890 | h | ||
891 | } | ||
792 | FIELD_EXPR => { | 892 | FIELD_EXPR => { |
793 | let h = HighlightTag::Field; | 893 | let h = HighlightTag::Field; |
794 | let is_union = ast::FieldExpr::cast(parent) | 894 | let is_union = ast::FieldExpr::cast(parent) |
@@ -801,7 +901,7 @@ fn highlight_name_ref_by_syntax(name: ast::NameRef, sema: &Semantics<RootDatabas | |||
801 | }) | 901 | }) |
802 | }) | 902 | }) |
803 | .unwrap_or(false); | 903 | .unwrap_or(false); |
804 | return if is_union { h | HighlightModifier::Unsafe } else { h.into() }; | 904 | if is_union { h | HighlightModifier::Unsafe } else { h.into() } |
805 | } | 905 | } |
806 | PATH_SEGMENT => { | 906 | PATH_SEGMENT => { |
807 | let path = match parent.parent().and_then(ast::Path::cast) { | 907 | let path = match parent.parent().and_then(ast::Path::cast) { |
@@ -826,18 +926,15 @@ fn highlight_name_ref_by_syntax(name: ast::NameRef, sema: &Semantics<RootDatabas | |||
826 | }; | 926 | }; |
827 | 927 | ||
828 | match parent.kind() { | 928 | match parent.kind() { |
829 | CALL_EXPR => HighlightTag::Function, | 929 | CALL_EXPR => HighlightTag::Function.into(), |
830 | _ => { | 930 | _ => if name.text().chars().next().unwrap_or_default().is_uppercase() { |
831 | if name.text().chars().next().unwrap_or_default().is_uppercase() { | 931 | HighlightTag::Struct.into() |
832 | HighlightTag::Struct | 932 | } else { |
833 | } else { | 933 | HighlightTag::Constant |
834 | HighlightTag::Constant | ||
835 | } | ||
836 | } | 934 | } |
935 | .into(), | ||
837 | } | 936 | } |
838 | } | 937 | } |
839 | _ => default, | 938 | _ => default.into(), |
840 | }; | 939 | } |
841 | |||
842 | tag.into() | ||
843 | } | 940 | } |