diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2020-08-08 17:45:37 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2020-08-08 17:45:37 +0100 |
commit | 8a57afe5a4bfab40072a83f7dc4ca560bf860919 (patch) | |
tree | 167d3717945c94c7523bbda5018239ed3a1c5fca /crates/ra_ide | |
parent | eed05a95b47c00bf6ce06e156716cd0648a88fb2 (diff) | |
parent | be935b2b56dcbda5a5918d8c600552b0adbb3a96 (diff) |
Merge #5684
5684: Semantic highlighting for unsafe union field access r=jonas-schievink a=Nashenas88
This change adds support for unions in inference and lowering, then extends on that to add the unsafe semantic modifier on field access only. The `is_possibly_unsafe` function in `syntax_highlighting.rs` could be extended to support fns and static muts so that their definitions are not highlighted as unsafe, but only their usage.
Also, each commit of this PR updates the tests. By reviewing the files by commit, it's easy to see how the changes in the code affected the tests.
Co-authored-by: Paul Daniel Faria <[email protected]>
Diffstat (limited to 'crates/ra_ide')
-rw-r--r-- | crates/ra_ide/src/syntax_highlighting.rs | 66 | ||||
-rw-r--r-- | crates/ra_ide/src/syntax_highlighting/tests.rs | 11 | ||||
-rw-r--r-- | crates/ra_ide/test_data/highlight_unsafe.html | 11 |
3 files changed, 78 insertions, 10 deletions
diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs index 89efe71da..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>, |
@@ -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 | } |
@@ -652,10 +676,19 @@ fn is_child_of_impl(element: &SyntaxElement) -> bool { | |||
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) => { |
@@ -725,7 +758,7 @@ fn highlight_name_by_syntax(name: ast::Name) -> Highlight { | |||
725 | tag.into() | 758 | tag.into() |
726 | } | 759 | } |
727 | 760 | ||
728 | fn highlight_name_ref_by_syntax(name: ast::NameRef) -> Highlight { | 761 | fn highlight_name_ref_by_syntax(name: ast::NameRef, sema: &Semantics<RootDatabase>) -> Highlight { |
729 | let default = HighlightTag::UnresolvedReference; | 762 | let default = HighlightTag::UnresolvedReference; |
730 | 763 | ||
731 | let parent = match name.syntax().parent() { | 764 | let parent = match name.syntax().parent() { |
@@ -735,7 +768,20 @@ fn highlight_name_ref_by_syntax(name: ast::NameRef) -> Highlight { | |||
735 | 768 | ||
736 | let tag = match parent.kind() { | 769 | let tag = match parent.kind() { |
737 | METHOD_CALL_EXPR => HighlightTag::Function, | 770 | METHOD_CALL_EXPR => HighlightTag::Function, |
738 | 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 | } | ||
739 | PATH_SEGMENT => { | 785 | PATH_SEGMENT => { |
740 | let path = match parent.parent().and_then(ast::Path::cast) { | 786 | let path = match parent.parent().and_then(ast::Path::cast) { |
741 | Some(it) => it, | 787 | Some(it) => it, |
diff --git a/crates/ra_ide/src/syntax_highlighting/tests.rs b/crates/ra_ide/src/syntax_highlighting/tests.rs index b9b358022..730efff0d 100644 --- a/crates/ra_ide/src/syntax_highlighting/tests.rs +++ b/crates/ra_ide/src/syntax_highlighting/tests.rs | |||
@@ -275,6 +275,11 @@ fn test_unsafe_highlighting() { | |||
275 | r#" | 275 | r#" |
276 | unsafe fn unsafe_fn() {} | 276 | unsafe fn unsafe_fn() {} |
277 | 277 | ||
278 | union Union { | ||
279 | a: u32, | ||
280 | b: f32, | ||
281 | } | ||
282 | |||
278 | struct HasUnsafeFn; | 283 | struct HasUnsafeFn; |
279 | 284 | ||
280 | impl HasUnsafeFn { | 285 | impl HasUnsafeFn { |
@@ -289,8 +294,14 @@ static mut global_mut: TypeForStaticMut = TypeForStaticMut { a: 0 }; | |||
289 | 294 | ||
290 | fn main() { | 295 | fn main() { |
291 | let x = &5 as *const usize; | 296 | let x = &5 as *const usize; |
297 | let u = Union { b: 0 }; | ||
292 | unsafe { | 298 | unsafe { |
293 | unsafe_fn(); | 299 | unsafe_fn(); |
300 | let b = u.b; | ||
301 | match u { | ||
302 | Union { b: 0 } => (), | ||
303 | Union { a } => (), | ||
304 | } | ||
294 | HasUnsafeFn.unsafe_method(); | 305 | HasUnsafeFn.unsafe_method(); |
295 | let y = *(x); | 306 | let y = *(x); |
296 | let z = -x; | 307 | let z = -x; |
diff --git a/crates/ra_ide/test_data/highlight_unsafe.html b/crates/ra_ide/test_data/highlight_unsafe.html index 87d8c1556..79409fe81 100644 --- a/crates/ra_ide/test_data/highlight_unsafe.html +++ b/crates/ra_ide/test_data/highlight_unsafe.html | |||
@@ -37,6 +37,11 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
37 | </style> | 37 | </style> |
38 | <pre><code><span class="keyword unsafe">unsafe</span> <span class="keyword">fn</span> <span class="function declaration unsafe">unsafe_fn</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span> | 38 | <pre><code><span class="keyword unsafe">unsafe</span> <span class="keyword">fn</span> <span class="function declaration unsafe">unsafe_fn</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span> |
39 | 39 | ||
40 | <span class="keyword">union</span> <span class="union declaration">Union</span> <span class="punctuation">{</span> | ||
41 | <span class="field declaration">a</span><span class="punctuation">:</span> <span class="builtin_type">u32</span><span class="punctuation">,</span> | ||
42 | <span class="field declaration">b</span><span class="punctuation">:</span> <span class="builtin_type">f32</span><span class="punctuation">,</span> | ||
43 | <span class="punctuation">}</span> | ||
44 | |||
40 | <span class="keyword">struct</span> <span class="struct declaration">HasUnsafeFn</span><span class="punctuation">;</span> | 45 | <span class="keyword">struct</span> <span class="struct declaration">HasUnsafeFn</span><span class="punctuation">;</span> |
41 | 46 | ||
42 | <span class="keyword">impl</span> <span class="struct">HasUnsafeFn</span> <span class="punctuation">{</span> | 47 | <span class="keyword">impl</span> <span class="struct">HasUnsafeFn</span> <span class="punctuation">{</span> |
@@ -51,8 +56,14 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
51 | 56 | ||
52 | <span class="keyword">fn</span> <span class="function declaration">main</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span> | 57 | <span class="keyword">fn</span> <span class="function declaration">main</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span> |
53 | <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> | 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> |
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> | ||
54 | <span class="keyword unsafe">unsafe</span> <span class="punctuation">{</span> | 60 | <span class="keyword unsafe">unsafe</span> <span class="punctuation">{</span> |
55 | <span class="function unsafe">unsafe_fn</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span> | 61 | <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> | ||
63 | <span class="keyword control">match</span> <span class="variable">u</span> <span class="punctuation">{</span> | ||
64 | <span class="union">Union</span> <span class="punctuation">{</span> <span class="field unsafe">b</span><span class="punctuation">:</span> <span class="numeric_literal">0</span> <span class="punctuation">}</span> <span class="operator">=></span> <span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">,</span> | ||
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> | ||
66 | <span class="punctuation">}</span> | ||
56 | <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> | 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> |
57 | <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> | 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> |
58 | <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> | 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> |