diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_hir/src/code_model.rs | 18 | ||||
-rw-r--r-- | crates/ra_hir/src/lib.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/semantics.rs | 99 | ||||
-rw-r--r-- | crates/ra_hir_def/src/adt.rs | 42 | ||||
-rw-r--r-- | crates/ra_ide/src/syntax_highlighting.rs | 89 | ||||
-rw-r--r-- | crates/ra_ide/src/syntax_highlighting/tests.rs | 33 | ||||
-rw-r--r-- | crates/ra_ide/test_data/highlight_unsafe.html | 33 |
7 files changed, 284 insertions, 32 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 44456e49e..0007d7fa8 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs | |||
@@ -4,6 +4,7 @@ use std::{iter, sync::Arc}; | |||
4 | use arrayvec::ArrayVec; | 4 | use arrayvec::ArrayVec; |
5 | use either::Either; | 5 | use either::Either; |
6 | use hir_def::{ | 6 | use hir_def::{ |
7 | adt::ReprKind, | ||
7 | adt::StructKind, | 8 | adt::StructKind, |
8 | adt::VariantData, | 9 | adt::VariantData, |
9 | builtin_type::BuiltinType, | 10 | builtin_type::BuiltinType, |
@@ -431,6 +432,10 @@ impl Struct { | |||
431 | Type::from_def(db, self.id.lookup(db.upcast()).container.module(db.upcast()).krate, self.id) | 432 | Type::from_def(db, self.id.lookup(db.upcast()).container.module(db.upcast()).krate, self.id) |
432 | } | 433 | } |
433 | 434 | ||
435 | pub fn repr(self, db: &dyn HirDatabase) -> Option<ReprKind> { | ||
436 | db.struct_data(self.id).repr.clone() | ||
437 | } | ||
438 | |||
434 | fn variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData> { | 439 | fn variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData> { |
435 | db.struct_data(self.id).variant_data.clone() | 440 | db.struct_data(self.id).variant_data.clone() |
436 | } | 441 | } |
@@ -1253,6 +1258,19 @@ impl Type { | |||
1253 | ) | 1258 | ) |
1254 | } | 1259 | } |
1255 | 1260 | ||
1261 | pub fn is_packed(&self, db: &dyn HirDatabase) -> bool { | ||
1262 | let adt_id = match self.ty.value { | ||
1263 | Ty::Apply(ApplicationTy { ctor: TypeCtor::Adt(adt_id), .. }) => adt_id, | ||
1264 | _ => return false, | ||
1265 | }; | ||
1266 | |||
1267 | let adt = adt_id.into(); | ||
1268 | match adt { | ||
1269 | Adt::Struct(s) => matches!(s.repr(db), Some(ReprKind::Packed)), | ||
1270 | _ => false, | ||
1271 | } | ||
1272 | } | ||
1273 | |||
1256 | pub fn is_raw_ptr(&self) -> bool { | 1274 | pub fn is_raw_ptr(&self) -> bool { |
1257 | matches!(&self.ty.value, Ty::Apply(ApplicationTy { ctor: TypeCtor::RawPtr(..), .. })) | 1275 | matches!(&self.ty.value, Ty::Apply(ApplicationTy { ctor: TypeCtor::RawPtr(..), .. })) |
1258 | } | 1276 | } |
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 31f3241c9..34b02c536 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs | |||
@@ -49,7 +49,7 @@ pub use hir_def::{ | |||
49 | docs::Documentation, | 49 | docs::Documentation, |
50 | nameres::ModuleSource, | 50 | nameres::ModuleSource, |
51 | path::{ModPath, Path, PathKind}, | 51 | path::{ModPath, Path, PathKind}, |
52 | type_ref::Mutability, | 52 | type_ref::{Mutability, TypeRef}, |
53 | }; | 53 | }; |
54 | pub use hir_expand::{ | 54 | pub use hir_expand::{ |
55 | hygiene::Hygiene, name::Name, HirFileId, InFile, MacroCallId, MacroCallLoc, | 55 | hygiene::Hygiene, name::Name, HirFileId, InFile, MacroCallId, MacroCallLoc, |
diff --git a/crates/ra_hir/src/semantics.rs b/crates/ra_hir/src/semantics.rs index e392130ab..872f5fa4c 100644 --- a/crates/ra_hir/src/semantics.rs +++ b/crates/ra_hir/src/semantics.rs | |||
@@ -25,7 +25,8 @@ use crate::{ | |||
25 | semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, | 25 | semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, |
26 | source_analyzer::{resolve_hir_path, resolve_hir_path_qualifier, SourceAnalyzer}, | 26 | source_analyzer::{resolve_hir_path, resolve_hir_path_qualifier, SourceAnalyzer}, |
27 | AssocItem, Callable, Crate, Field, Function, HirFileId, ImplDef, InFile, Local, MacroDef, | 27 | AssocItem, Callable, Crate, Field, Function, HirFileId, ImplDef, InFile, Local, MacroDef, |
28 | Module, ModuleDef, Name, Origin, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam, VariantDef, | 28 | Module, ModuleDef, Name, Origin, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam, TypeRef, |
29 | VariantDef, | ||
29 | }; | 30 | }; |
30 | use resolver::TypeNs; | 31 | use resolver::TypeNs; |
31 | 32 | ||
@@ -279,6 +280,18 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { | |||
279 | pub fn assert_contains_node(&self, node: &SyntaxNode) { | 280 | pub fn assert_contains_node(&self, node: &SyntaxNode) { |
280 | self.imp.assert_contains_node(node) | 281 | self.imp.assert_contains_node(node) |
281 | } | 282 | } |
283 | |||
284 | pub fn is_unsafe_method_call(&self, method_call_expr: ast::MethodCallExpr) -> bool { | ||
285 | self.imp.is_unsafe_method_call(method_call_expr) | ||
286 | } | ||
287 | |||
288 | pub fn is_unsafe_ref_expr(&self, ref_expr: &ast::RefExpr) -> bool { | ||
289 | self.imp.is_unsafe_ref_expr(ref_expr) | ||
290 | } | ||
291 | |||
292 | pub fn is_unsafe_ident_pat(&self, ident_pat: &ast::IdentPat) -> bool { | ||
293 | self.imp.is_unsafe_ident_pat(ident_pat) | ||
294 | } | ||
282 | } | 295 | } |
283 | 296 | ||
284 | impl<'db> SemanticsImpl<'db> { | 297 | impl<'db> SemanticsImpl<'db> { |
@@ -574,6 +587,90 @@ impl<'db> SemanticsImpl<'db> { | |||
574 | }); | 587 | }); |
575 | InFile::new(file_id, node) | 588 | InFile::new(file_id, node) |
576 | } | 589 | } |
590 | |||
591 | pub fn is_unsafe_method_call(&self, method_call_expr: ast::MethodCallExpr) -> bool { | ||
592 | method_call_expr | ||
593 | .expr() | ||
594 | .and_then(|expr| { | ||
595 | let field_expr = if let ast::Expr::FieldExpr(field_expr) = expr { | ||
596 | field_expr | ||
597 | } else { | ||
598 | return None; | ||
599 | }; | ||
600 | let ty = self.type_of_expr(&field_expr.expr()?)?; | ||
601 | if !ty.is_packed(self.db) { | ||
602 | return None; | ||
603 | } | ||
604 | |||
605 | let func = self.resolve_method_call(&method_call_expr).map(Function::from)?; | ||
606 | let is_unsafe = func.has_self_param(self.db) | ||
607 | && matches!(func.params(self.db).first(), Some(TypeRef::Reference(..))); | ||
608 | Some(is_unsafe) | ||
609 | }) | ||
610 | .unwrap_or(false) | ||
611 | } | ||
612 | |||
613 | pub fn is_unsafe_ref_expr(&self, ref_expr: &ast::RefExpr) -> bool { | ||
614 | ref_expr | ||
615 | .expr() | ||
616 | .and_then(|expr| { | ||
617 | let field_expr = match expr { | ||
618 | ast::Expr::FieldExpr(field_expr) => field_expr, | ||
619 | _ => return None, | ||
620 | }; | ||
621 | let expr = field_expr.expr()?; | ||
622 | self.type_of_expr(&expr) | ||
623 | }) | ||
624 | // Binding a reference to a packed type is possibly unsafe. | ||
625 | .map(|ty| ty.is_packed(self.db)) | ||
626 | .unwrap_or(false) | ||
627 | |||
628 | // FIXME This needs layout computation to be correct. It will highlight | ||
629 | // more than it should with the current implementation. | ||
630 | } | ||
631 | |||
632 | pub fn is_unsafe_ident_pat(&self, ident_pat: &ast::IdentPat) -> bool { | ||
633 | if !ident_pat.ref_token().is_some() { | ||
634 | return false; | ||
635 | } | ||
636 | |||
637 | ident_pat | ||
638 | .syntax() | ||
639 | .parent() | ||
640 | .and_then(|parent| { | ||
641 | // `IdentPat` can live under `RecordPat` directly under `RecordPatField` or | ||
642 | // `RecordPatFieldList`. `RecordPatField` also lives under `RecordPatFieldList`, | ||
643 | // so this tries to lookup the `IdentPat` anywhere along that structure to the | ||
644 | // `RecordPat` so we can get the containing type. | ||
645 | let record_pat = ast::RecordPatField::cast(parent.clone()) | ||
646 | .and_then(|record_pat| record_pat.syntax().parent()) | ||
647 | .or_else(|| Some(parent.clone())) | ||
648 | .and_then(|parent| { | ||
649 | ast::RecordPatFieldList::cast(parent)? | ||
650 | .syntax() | ||
651 | .parent() | ||
652 | .and_then(ast::RecordPat::cast) | ||
653 | }); | ||
654 | |||
655 | // If this doesn't match a `RecordPat`, fallback to a `LetStmt` to see if | ||
656 | // this is initialized from a `FieldExpr`. | ||
657 | if let Some(record_pat) = record_pat { | ||
658 | self.type_of_pat(&ast::Pat::RecordPat(record_pat)) | ||
659 | } else if let Some(let_stmt) = ast::LetStmt::cast(parent) { | ||
660 | let field_expr = match let_stmt.initializer()? { | ||
661 | ast::Expr::FieldExpr(field_expr) => field_expr, | ||
662 | _ => return None, | ||
663 | }; | ||
664 | |||
665 | self.type_of_expr(&field_expr.expr()?) | ||
666 | } else { | ||
667 | None | ||
668 | } | ||
669 | }) | ||
670 | // Binding a reference to a packed type is possibly unsafe. | ||
671 | .map(|ty| ty.is_packed(self.db)) | ||
672 | .unwrap_or(false) | ||
673 | } | ||
577 | } | 674 | } |
578 | 675 | ||
579 | pub trait ToDef: AstNode + Clone { | 676 | pub trait ToDef: AstNode + Clone { |
diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs index 6cb56a1cd..35c3a9140 100644 --- a/crates/ra_hir_def/src/adt.rs +++ b/crates/ra_hir_def/src/adt.rs | |||
@@ -9,11 +9,12 @@ use hir_expand::{ | |||
9 | }; | 9 | }; |
10 | use ra_arena::{map::ArenaMap, Arena}; | 10 | use ra_arena::{map::ArenaMap, Arena}; |
11 | use ra_syntax::ast::{self, NameOwner, VisibilityOwner}; | 11 | use ra_syntax::ast::{self, NameOwner, VisibilityOwner}; |
12 | use tt::{Delimiter, DelimiterKind, Leaf, Subtree, TokenTree}; | ||
12 | 13 | ||
13 | use crate::{ | 14 | use crate::{ |
14 | body::{CfgExpander, LowerCtx}, | 15 | body::{CfgExpander, LowerCtx}, |
15 | db::DefDatabase, | 16 | db::DefDatabase, |
16 | item_tree::{Field, Fields, ItemTree}, | 17 | item_tree::{AttrOwner, Field, Fields, ItemTree, ModItem}, |
17 | src::HasChildSource, | 18 | src::HasChildSource, |
18 | src::HasSource, | 19 | src::HasSource, |
19 | trace::Trace, | 20 | trace::Trace, |
@@ -29,6 +30,7 @@ use ra_cfg::CfgOptions; | |||
29 | pub struct StructData { | 30 | pub struct StructData { |
30 | pub name: Name, | 31 | pub name: Name, |
31 | pub variant_data: Arc<VariantData>, | 32 | pub variant_data: Arc<VariantData>, |
33 | pub repr: Option<ReprKind>, | ||
32 | } | 34 | } |
33 | 35 | ||
34 | #[derive(Debug, Clone, PartialEq, Eq)] | 36 | #[derive(Debug, Clone, PartialEq, Eq)] |
@@ -58,26 +60,58 @@ pub struct FieldData { | |||
58 | pub visibility: RawVisibility, | 60 | pub visibility: RawVisibility, |
59 | } | 61 | } |
60 | 62 | ||
63 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
64 | pub enum ReprKind { | ||
65 | Packed, | ||
66 | Other, | ||
67 | } | ||
68 | |||
69 | fn repr_from_value(item_tree: &ItemTree, of: AttrOwner) -> Option<ReprKind> { | ||
70 | item_tree.attrs(of).by_key("repr").tt_values().find_map(parse_repr_tt) | ||
71 | } | ||
72 | |||
73 | fn parse_repr_tt(tt: &Subtree) -> Option<ReprKind> { | ||
74 | match tt.delimiter { | ||
75 | Some(Delimiter { kind: DelimiterKind::Parenthesis, .. }) => {} | ||
76 | _ => return None, | ||
77 | } | ||
78 | |||
79 | let mut it = tt.token_trees.iter(); | ||
80 | match it.next()? { | ||
81 | TokenTree::Leaf(Leaf::Ident(ident)) if ident.text == "packed" => Some(ReprKind::Packed), | ||
82 | _ => Some(ReprKind::Other), | ||
83 | } | ||
84 | } | ||
85 | |||
61 | impl StructData { | 86 | impl StructData { |
62 | pub(crate) fn struct_data_query(db: &dyn DefDatabase, id: StructId) -> Arc<StructData> { | 87 | pub(crate) fn struct_data_query(db: &dyn DefDatabase, id: StructId) -> Arc<StructData> { |
63 | let loc = id.lookup(db); | 88 | let loc = id.lookup(db); |
64 | let item_tree = db.item_tree(loc.id.file_id); | 89 | let item_tree = db.item_tree(loc.id.file_id); |
90 | let repr = repr_from_value(&item_tree, ModItem::from(loc.id.value).into()); | ||
65 | let cfg_options = db.crate_graph()[loc.container.module(db).krate].cfg_options.clone(); | 91 | let cfg_options = db.crate_graph()[loc.container.module(db).krate].cfg_options.clone(); |
66 | 92 | ||
67 | let strukt = &item_tree[loc.id.value]; | 93 | let strukt = &item_tree[loc.id.value]; |
68 | let variant_data = lower_fields(&item_tree, &cfg_options, &strukt.fields); | 94 | let variant_data = lower_fields(&item_tree, &cfg_options, &strukt.fields); |
69 | 95 | Arc::new(StructData { | |
70 | Arc::new(StructData { name: strukt.name.clone(), variant_data: Arc::new(variant_data) }) | 96 | name: strukt.name.clone(), |
97 | variant_data: Arc::new(variant_data), | ||
98 | repr, | ||
99 | }) | ||
71 | } | 100 | } |
72 | pub(crate) fn union_data_query(db: &dyn DefDatabase, id: UnionId) -> Arc<StructData> { | 101 | pub(crate) fn union_data_query(db: &dyn DefDatabase, id: UnionId) -> Arc<StructData> { |
73 | let loc = id.lookup(db); | 102 | let loc = id.lookup(db); |
74 | let item_tree = db.item_tree(loc.id.file_id); | 103 | let item_tree = db.item_tree(loc.id.file_id); |
104 | let repr = repr_from_value(&item_tree, ModItem::from(loc.id.value).into()); | ||
75 | let cfg_options = db.crate_graph()[loc.container.module(db).krate].cfg_options.clone(); | 105 | let cfg_options = db.crate_graph()[loc.container.module(db).krate].cfg_options.clone(); |
76 | 106 | ||
77 | let union = &item_tree[loc.id.value]; | 107 | let union = &item_tree[loc.id.value]; |
78 | let variant_data = lower_fields(&item_tree, &cfg_options, &union.fields); | 108 | let variant_data = lower_fields(&item_tree, &cfg_options, &union.fields); |
79 | 109 | ||
80 | Arc::new(StructData { name: union.name.clone(), variant_data: Arc::new(variant_data) }) | 110 | Arc::new(StructData { |
111 | name: union.name.clone(), | ||
112 | variant_data: Arc::new(variant_data), | ||
113 | repr, | ||
114 | }) | ||
81 | } | 115 | } |
82 | } | 116 | } |
83 | 117 | ||
diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs index 6b7874460..c10e15db8 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 | }, |
@@ -566,9 +566,20 @@ fn highlight_element( | |||
566 | } | 566 | } |
567 | } | 567 | } |
568 | p if p.is_punct() => match p { | 568 | p if p.is_punct() => match p { |
569 | T![::] | T![->] | T![=>] | T![&] | T![..] | T![=] | T![@] => { | 569 | T![&] => { |
570 | HighlightTag::Operator.into() | 570 | let h = HighlightTag::Operator.into(); |
571 | let is_unsafe = element | ||
572 | .parent() | ||
573 | .and_then(ast::RefExpr::cast) | ||
574 | .map(|ref_expr| sema.is_unsafe_ref_expr(&ref_expr)) | ||
575 | .unwrap_or(false); | ||
576 | if is_unsafe { | ||
577 | h | HighlightModifier::Unsafe | ||
578 | } else { | ||
579 | h | ||
580 | } | ||
571 | } | 581 | } |
582 | T![::] | T![->] | T![=>] | T![..] | T![=] | T![@] => HighlightTag::Operator.into(), | ||
572 | T![!] if element.parent().and_then(ast::MacroCall::cast).is_some() => { | 583 | T![!] if element.parent().and_then(ast::MacroCall::cast).is_some() => { |
573 | HighlightTag::Macro.into() | 584 | HighlightTag::Macro.into() |
574 | } | 585 | } |
@@ -649,6 +660,18 @@ fn highlight_element( | |||
649 | HighlightTag::SelfKeyword.into() | 660 | HighlightTag::SelfKeyword.into() |
650 | } | 661 | } |
651 | } | 662 | } |
663 | T![ref] => element | ||
664 | .parent() | ||
665 | .and_then(ast::IdentPat::cast) | ||
666 | .and_then(|ident_pat| { | ||
667 | if sema.is_unsafe_ident_pat(&ident_pat) { | ||
668 | Some(HighlightModifier::Unsafe) | ||
669 | } else { | ||
670 | None | ||
671 | } | ||
672 | }) | ||
673 | .map(|modifier| h | modifier) | ||
674 | .unwrap_or(h), | ||
652 | _ => h, | 675 | _ => h, |
653 | } | 676 | } |
654 | } | 677 | } |
@@ -678,7 +701,13 @@ fn is_child_of_impl(element: &SyntaxElement) -> bool { | |||
678 | } | 701 | } |
679 | } | 702 | } |
680 | 703 | ||
681 | fn highlight_name(db: &RootDatabase, def: Definition, possibly_unsafe: bool) -> Highlight { | 704 | fn highlight_name( |
705 | sema: &Semantics<RootDatabase>, | ||
706 | db: &RootDatabase, | ||
707 | def: Definition, | ||
708 | name_ref: Option<ast::NameRef>, | ||
709 | possibly_unsafe: bool, | ||
710 | ) -> Highlight { | ||
682 | match def { | 711 | match def { |
683 | Definition::Macro(_) => HighlightTag::Macro, | 712 | Definition::Macro(_) => HighlightTag::Macro, |
684 | Definition::Field(field) => { | 713 | Definition::Field(field) => { |
@@ -697,6 +726,15 @@ fn highlight_name(db: &RootDatabase, def: Definition, possibly_unsafe: bool) -> | |||
697 | let mut h = HighlightTag::Function.into(); | 726 | let mut h = HighlightTag::Function.into(); |
698 | if func.is_unsafe(db) { | 727 | if func.is_unsafe(db) { |
699 | h |= HighlightModifier::Unsafe; | 728 | h |= HighlightModifier::Unsafe; |
729 | } else { | ||
730 | let is_unsafe = name_ref | ||
731 | .and_then(|name_ref| name_ref.syntax().parent()) | ||
732 | .and_then(ast::MethodCallExpr::cast) | ||
733 | .map(|method_call_expr| sema.is_unsafe_method_call(method_call_expr)) | ||
734 | .unwrap_or(false); | ||
735 | if is_unsafe { | ||
736 | h |= HighlightModifier::Unsafe; | ||
737 | } | ||
700 | } | 738 | } |
701 | return h; | 739 | return h; |
702 | } | 740 | } |
@@ -768,8 +806,18 @@ fn highlight_name_ref_by_syntax(name: ast::NameRef, sema: &Semantics<RootDatabas | |||
768 | _ => return default.into(), | 806 | _ => return default.into(), |
769 | }; | 807 | }; |
770 | 808 | ||
771 | let tag = match parent.kind() { | 809 | match parent.kind() { |
772 | METHOD_CALL_EXPR => HighlightTag::Function, | 810 | METHOD_CALL_EXPR => { |
811 | let mut h = Highlight::new(HighlightTag::Function); | ||
812 | let is_unsafe = ast::MethodCallExpr::cast(parent) | ||
813 | .map(|method_call_expr| sema.is_unsafe_method_call(method_call_expr)) | ||
814 | .unwrap_or(false); | ||
815 | if is_unsafe { | ||
816 | h |= HighlightModifier::Unsafe; | ||
817 | } | ||
818 | |||
819 | h | ||
820 | } | ||
773 | FIELD_EXPR => { | 821 | FIELD_EXPR => { |
774 | let h = HighlightTag::Field; | 822 | let h = HighlightTag::Field; |
775 | let is_union = ast::FieldExpr::cast(parent) | 823 | let is_union = ast::FieldExpr::cast(parent) |
@@ -782,7 +830,11 @@ fn highlight_name_ref_by_syntax(name: ast::NameRef, sema: &Semantics<RootDatabas | |||
782 | }) | 830 | }) |
783 | }) | 831 | }) |
784 | .unwrap_or(false); | 832 | .unwrap_or(false); |
785 | return if is_union { h | HighlightModifier::Unsafe } else { h.into() }; | 833 | if is_union { |
834 | h | HighlightModifier::Unsafe | ||
835 | } else { | ||
836 | h.into() | ||
837 | } | ||
786 | } | 838 | } |
787 | PATH_SEGMENT => { | 839 | PATH_SEGMENT => { |
788 | let path = match parent.parent().and_then(ast::Path::cast) { | 840 | let path = match parent.parent().and_then(ast::Path::cast) { |
@@ -807,18 +859,15 @@ fn highlight_name_ref_by_syntax(name: ast::NameRef, sema: &Semantics<RootDatabas | |||
807 | }; | 859 | }; |
808 | 860 | ||
809 | match parent.kind() { | 861 | match parent.kind() { |
810 | CALL_EXPR => HighlightTag::Function, | 862 | CALL_EXPR => HighlightTag::Function.into(), |
811 | _ => { | 863 | _ => if name.text().chars().next().unwrap_or_default().is_uppercase() { |
812 | if name.text().chars().next().unwrap_or_default().is_uppercase() { | 864 | HighlightTag::Struct.into() |
813 | HighlightTag::Struct | 865 | } else { |
814 | } else { | 866 | HighlightTag::Constant |
815 | HighlightTag::Constant | ||
816 | } | ||
817 | } | 867 | } |
868 | .into(), | ||
818 | } | 869 | } |
819 | } | 870 | } |
820 | _ => default, | 871 | _ => default.into(), |
821 | }; | 872 | } |
822 | |||
823 | tag.into() | ||
824 | } | 873 | } |
diff --git a/crates/ra_ide/src/syntax_highlighting/tests.rs b/crates/ra_ide/src/syntax_highlighting/tests.rs index 09062c38e..a8087635a 100644 --- a/crates/ra_ide/src/syntax_highlighting/tests.rs +++ b/crates/ra_ide/src/syntax_highlighting/tests.rs | |||
@@ -292,10 +292,24 @@ struct TypeForStaticMut { | |||
292 | 292 | ||
293 | static mut global_mut: TypeForStaticMut = TypeForStaticMut { a: 0 }; | 293 | static mut global_mut: TypeForStaticMut = TypeForStaticMut { a: 0 }; |
294 | 294 | ||
295 | #[repr(packed)] | ||
296 | struct Packed { | ||
297 | a: u16, | ||
298 | } | ||
299 | |||
300 | trait DoTheAutoref { | ||
301 | fn calls_autoref(&self); | ||
302 | } | ||
303 | |||
304 | impl DoTheAutoref for u16 { | ||
305 | fn calls_autoref(&self) {} | ||
306 | } | ||
307 | |||
295 | fn main() { | 308 | fn main() { |
296 | let x = &5 as *const usize; | 309 | let x = &5 as *const _ as *const usize; |
297 | let u = Union { b: 0 }; | 310 | let u = Union { b: 0 }; |
298 | unsafe { | 311 | unsafe { |
312 | // unsafe fn and method calls | ||
299 | unsafe_fn(); | 313 | unsafe_fn(); |
300 | let b = u.b; | 314 | let b = u.b; |
301 | match u { | 315 | match u { |
@@ -303,9 +317,22 @@ fn main() { | |||
303 | Union { a } => (), | 317 | Union { a } => (), |
304 | } | 318 | } |
305 | HasUnsafeFn.unsafe_method(); | 319 | HasUnsafeFn.unsafe_method(); |
306 | let y = *(x); | 320 | |
307 | let z = -x; | 321 | // unsafe deref |
322 | let y = *x; | ||
323 | |||
324 | // unsafe access to a static mut | ||
308 | let a = global_mut.a; | 325 | let a = global_mut.a; |
326 | |||
327 | // unsafe ref of packed fields | ||
328 | let packed = Packed { a: 0 }; | ||
329 | let a = &packed.a; | ||
330 | let ref a = packed.a; | ||
331 | let Packed { ref a } = packed; | ||
332 | let Packed { a: ref _a } = packed; | ||
333 | |||
334 | // unsafe auto ref of packed field | ||
335 | packed.a.calls_autoref(); | ||
309 | } | 336 | } |
310 | } | 337 | } |
311 | "# | 338 | "# |
diff --git a/crates/ra_ide/test_data/highlight_unsafe.html b/crates/ra_ide/test_data/highlight_unsafe.html index 79409fe81..552fea668 100644 --- a/crates/ra_ide/test_data/highlight_unsafe.html +++ b/crates/ra_ide/test_data/highlight_unsafe.html | |||
@@ -54,10 +54,24 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
54 | 54 | ||
55 | <span class="keyword">static</span> <span class="keyword">mut</span> <span class="static declaration mutable unsafe">global_mut</span><span class="punctuation">:</span> <span class="struct">TypeForStaticMut</span> <span class="operator">=</span> <span class="struct">TypeForStaticMut</span> <span class="punctuation">{</span> <span class="field">a</span><span class="punctuation">:</span> <span class="numeric_literal">0</span> <span class="punctuation">}</span><span class="punctuation">;</span> | 55 | <span class="keyword">static</span> <span class="keyword">mut</span> <span class="static declaration mutable unsafe">global_mut</span><span class="punctuation">:</span> <span class="struct">TypeForStaticMut</span> <span class="operator">=</span> <span class="struct">TypeForStaticMut</span> <span class="punctuation">{</span> <span class="field">a</span><span class="punctuation">:</span> <span class="numeric_literal">0</span> <span class="punctuation">}</span><span class="punctuation">;</span> |
56 | 56 | ||
57 | <span class="attribute">#</span><span class="attribute">[</span><span class="function attribute">repr</span><span class="punctuation">(</span><span class="attribute">packed</span><span class="punctuation">)</span><span class="attribute">]</span> | ||
58 | <span class="keyword">struct</span> <span class="struct declaration">Packed</span> <span class="punctuation">{</span> | ||
59 | <span class="field declaration">a</span><span class="punctuation">:</span> <span class="builtin_type">u16</span><span class="punctuation">,</span> | ||
60 | <span class="punctuation">}</span> | ||
61 | |||
62 | <span class="keyword">trait</span> <span class="trait declaration">DoTheAutoref</span> <span class="punctuation">{</span> | ||
63 | <span class="keyword">fn</span> <span class="function declaration">calls_autoref</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span><span class="punctuation">;</span> | ||
64 | <span class="punctuation">}</span> | ||
65 | |||
66 | <span class="keyword">impl</span> <span class="trait">DoTheAutoref</span> <span class="keyword">for</span> <span class="builtin_type">u16</span> <span class="punctuation">{</span> | ||
67 | <span class="keyword">fn</span> <span class="function declaration">calls_autoref</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span> | ||
68 | <span class="punctuation">}</span> | ||
69 | |||
57 | <span class="keyword">fn</span> <span class="function declaration">main</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span> | 70 | <span class="keyword">fn</span> <span class="function declaration">main</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span> |
58 | <span class="keyword">let</span> <span class="variable declaration">x</span> <span class="operator">=</span> <span class="operator">&</span><span class="numeric_literal">5</span> <span class="keyword">as</span> <span class="keyword">*</span><span class="keyword">const</span> <span class="builtin_type">usize</span><span class="punctuation">;</span> | 71 | <span class="keyword">let</span> <span class="variable declaration">x</span> <span class="operator">=</span> <span class="operator">&</span><span class="numeric_literal">5</span> <span class="keyword">as</span> <span class="keyword">*</span><span class="keyword">const</span> <span class="punctuation">_</span> <span class="keyword">as</span> <span class="keyword">*</span><span class="keyword">const</span> <span class="builtin_type">usize</span><span class="punctuation">;</span> |
59 | <span class="keyword">let</span> <span class="variable declaration">u</span> <span class="operator">=</span> <span class="union">Union</span> <span class="punctuation">{</span> <span class="field">b</span><span class="punctuation">:</span> <span class="numeric_literal">0</span> <span class="punctuation">}</span><span class="punctuation">;</span> | 72 | <span class="keyword">let</span> <span class="variable declaration">u</span> <span class="operator">=</span> <span class="union">Union</span> <span class="punctuation">{</span> <span class="field">b</span><span class="punctuation">:</span> <span class="numeric_literal">0</span> <span class="punctuation">}</span><span class="punctuation">;</span> |
60 | <span class="keyword unsafe">unsafe</span> <span class="punctuation">{</span> | 73 | <span class="keyword unsafe">unsafe</span> <span class="punctuation">{</span> |
74 | <span class="comment">// unsafe fn and method calls</span> | ||
61 | <span class="function unsafe">unsafe_fn</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span> | 75 | <span class="function unsafe">unsafe_fn</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span> |
62 | <span class="keyword">let</span> <span class="variable declaration">b</span> <span class="operator">=</span> <span class="variable">u</span><span class="punctuation">.</span><span class="field unsafe">b</span><span class="punctuation">;</span> | 76 | <span class="keyword">let</span> <span class="variable declaration">b</span> <span class="operator">=</span> <span class="variable">u</span><span class="punctuation">.</span><span class="field unsafe">b</span><span class="punctuation">;</span> |
63 | <span class="keyword control">match</span> <span class="variable">u</span> <span class="punctuation">{</span> | 77 | <span class="keyword control">match</span> <span class="variable">u</span> <span class="punctuation">{</span> |
@@ -65,8 +79,21 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
65 | <span class="union">Union</span> <span class="punctuation">{</span> <span class="field unsafe">a</span> <span class="punctuation">}</span> <span class="operator">=></span> <span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">,</span> | 79 | <span class="union">Union</span> <span class="punctuation">{</span> <span class="field unsafe">a</span> <span class="punctuation">}</span> <span class="operator">=></span> <span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">,</span> |
66 | <span class="punctuation">}</span> | 80 | <span class="punctuation">}</span> |
67 | <span class="struct">HasUnsafeFn</span><span class="punctuation">.</span><span class="function unsafe">unsafe_method</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span> | 81 | <span class="struct">HasUnsafeFn</span><span class="punctuation">.</span><span class="function unsafe">unsafe_method</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span> |
68 | <span class="keyword">let</span> <span class="variable declaration">y</span> <span class="operator">=</span> <span class="operator unsafe">*</span><span class="punctuation">(</span><span class="variable">x</span><span class="punctuation">)</span><span class="punctuation">;</span> | 82 | |
69 | <span class="keyword">let</span> <span class="variable declaration">z</span> <span class="operator">=</span> <span class="numeric_literal">-</span><span class="variable">x</span><span class="punctuation">;</span> | 83 | <span class="comment">// unsafe deref</span> |
84 | <span class="keyword">let</span> <span class="variable declaration">y</span> <span class="operator">=</span> <span class="operator unsafe">*</span><span class="variable">x</span><span class="punctuation">;</span> | ||
85 | |||
86 | <span class="comment">// unsafe access to a static mut</span> | ||
70 | <span class="keyword">let</span> <span class="variable declaration">a</span> <span class="operator">=</span> <span class="static mutable unsafe">global_mut</span><span class="punctuation">.</span><span class="field">a</span><span class="punctuation">;</span> | 87 | <span class="keyword">let</span> <span class="variable declaration">a</span> <span class="operator">=</span> <span class="static mutable unsafe">global_mut</span><span class="punctuation">.</span><span class="field">a</span><span class="punctuation">;</span> |
88 | |||
89 | <span class="comment">// unsafe ref of packed fields</span> | ||
90 | <span class="keyword">let</span> <span class="variable declaration">packed</span> <span class="operator">=</span> <span class="struct">Packed</span> <span class="punctuation">{</span> <span class="field">a</span><span class="punctuation">:</span> <span class="numeric_literal">0</span> <span class="punctuation">}</span><span class="punctuation">;</span> | ||
91 | <span class="keyword">let</span> <span class="variable declaration">a</span> <span class="operator">=</span> <span class="operator unsafe">&</span><span class="variable">packed</span><span class="punctuation">.</span><span class="field">a</span><span class="punctuation">;</span> | ||
92 | <span class="keyword">let</span> <span class="keyword unsafe">ref</span> <span class="variable declaration">a</span> <span class="operator">=</span> <span class="variable">packed</span><span class="punctuation">.</span><span class="field">a</span><span class="punctuation">;</span> | ||
93 | <span class="keyword">let</span> <span class="struct">Packed</span> <span class="punctuation">{</span> <span class="keyword unsafe">ref</span> <span class="field">a</span> <span class="punctuation">}</span> <span class="operator">=</span> <span class="variable">packed</span><span class="punctuation">;</span> | ||
94 | <span class="keyword">let</span> <span class="struct">Packed</span> <span class="punctuation">{</span> <span class="field">a</span><span class="punctuation">:</span> <span class="keyword unsafe">ref</span> <span class="variable declaration">_a</span> <span class="punctuation">}</span> <span class="operator">=</span> <span class="variable">packed</span><span class="punctuation">;</span> | ||
95 | |||
96 | <span class="comment">// unsafe auto ref of packed field</span> | ||
97 | <span class="variable">packed</span><span class="punctuation">.</span><span class="field">a</span><span class="punctuation">.</span><span class="function unsafe">calls_autoref</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span> | ||
71 | <span class="punctuation">}</span> | 98 | <span class="punctuation">}</span> |
72 | <span class="punctuation">}</span></code></pre> \ No newline at end of file | 99 | <span class="punctuation">}</span></code></pre> \ No newline at end of file |