aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide
diff options
context:
space:
mode:
authorPaul Daniel Faria <[email protected]>2020-08-07 14:33:40 +0100
committerPaul Daniel Faria <[email protected]>2020-08-08 16:29:56 +0100
commitbe935b2b56dcbda5a5918d8c600552b0adbb3a96 (patch)
tree6ecdb8cfd62ac5d08d4746e17604b6ccd1ad6d21 /crates/ra_ide
parent3bf033e54814919f2214ca4e9b73cebc5ba7d86d (diff)
Apply unsafe semantic highlighting to union field access
Diffstat (limited to 'crates/ra_ide')
-rw-r--r--crates/ra_ide/src/syntax_highlighting.rs66
-rw-r--r--crates/ra_ide/test_data/highlight_unsafe.html6
2 files changed, 59 insertions, 13 deletions
diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs
index a32ae0165..bfe6143ca 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)]
5mod tests; 5mod tests;
6 6
7use hir::{Name, Semantics}; 7use hir::{Name, Semantics, VariantDef};
8use ra_ide_db::{ 8use 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
458fn 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
458fn highlight_element( 470fn 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
655fn highlight_name(db: &RootDatabase, def: Definition) -> Highlight { 679fn 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) => {
@@ -724,7 +757,7 @@ fn highlight_name_by_syntax(name: ast::Name) -> Highlight {
724 tag.into() 757 tag.into()
725} 758}
726 759
727fn highlight_name_ref_by_syntax(name: ast::NameRef) -> Highlight { 760fn highlight_name_ref_by_syntax(name: ast::NameRef, sema: &Semantics<RootDatabase>) -> Highlight {
728 let default = HighlightTag::UnresolvedReference; 761 let default = HighlightTag::UnresolvedReference;
729 762
730 let parent = match name.syntax().parent() { 763 let parent = match name.syntax().parent() {
@@ -734,7 +767,20 @@ fn highlight_name_ref_by_syntax(name: ast::NameRef) -> Highlight {
734 767
735 let tag = match parent.kind() { 768 let tag = match parent.kind() {
736 METHOD_CALL_EXPR => HighlightTag::Function, 769 METHOD_CALL_EXPR => HighlightTag::Function,
737 FIELD_EXPR => HighlightTag::Field, 770 FIELD_EXPR => {
771 let h = HighlightTag::Field;
772 let is_union = ast::FieldExpr::cast(parent)
773 .and_then(|field_expr| {
774 let field = sema.resolve_field(&field_expr)?;
775 Some(if let VariantDef::Union(_) = field.parent_def(sema.db) {
776 true
777 } else {
778 false
779 })
780 })
781 .unwrap_or(false);
782 return if is_union { h | HighlightModifier::Unsafe } else { h.into() };
783 }
738 PATH_SEGMENT => { 784 PATH_SEGMENT => {
739 let path = match parent.parent().and_then(ast::Path::cast) { 785 let path = match parent.parent().and_then(ast::Path::cast) {
740 Some(it) => it, 786 Some(it) => it,
diff --git a/crates/ra_ide/test_data/highlight_unsafe.html b/crates/ra_ide/test_data/highlight_unsafe.html
index de70363da..cfc872832 100644
--- a/crates/ra_ide/test_data/highlight_unsafe.html
+++ b/crates/ra_ide/test_data/highlight_unsafe.html
@@ -53,10 +53,10 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
53 <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> 53 <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> 54 <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> 55 <span class="function unsafe">unsafe_fn</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span>
56 <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">b</span><span class="punctuation">;</span> 56 <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>
57 <span class="keyword control">match</span> <span class="variable">u</span> <span class="punctuation">{</span> 57 <span class="keyword control">match</span> <span class="variable">u</span> <span class="punctuation">{</span>
58 <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="operator">=&gt;</span> <span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">,</span> 58 <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">=&gt;</span> <span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">,</span>
59 <span class="union">Union</span> <span class="punctuation">{</span> <span class="field">a</span> <span class="punctuation">}</span> <span class="operator">=&gt;</span> <span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">,</span> 59 <span class="union">Union</span> <span class="punctuation">{</span> <span class="field unsafe">a</span> <span class="punctuation">}</span> <span class="operator">=&gt;</span> <span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">,</span>
60 <span class="punctuation">}</span> 60 <span class="punctuation">}</span>
61 <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> 61 <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>
62 <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> 62 <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>