Skip to content

Commit be935b2

Browse files
committed
Apply unsafe semantic highlighting to union field access
1 parent 3bf033e commit be935b2

File tree

2 files changed

+59
-13
lines changed

2 files changed

+59
-13
lines changed

crates/ra_ide/src/syntax_highlighting.rs

Lines changed: 56 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ mod injection;
44
#[cfg(test)]
55
mod tests;
66

7-
use hir::{Name, Semantics};
7+
use hir::{Name, Semantics, VariantDef};
88
use ra_ide_db::{
99
defs::{classify_name, classify_name_ref, Definition, NameClass, NameRefClass},
1010
RootDatabase,
@@ -455,6 +455,18 @@ fn macro_call_range(macro_call: &ast::MacroCall) -> Option<TextRange> {
455455
Some(TextRange::new(range_start, range_end))
456456
}
457457

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+
458470
fn highlight_element(
459471
sema: &Semantics<RootDatabase>,
460472
bindings_shadow_count: &mut FxHashMap<Name, u32>,
@@ -484,10 +496,19 @@ fn highlight_element(
484496

485497
match name_kind {
486498
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
488511
}
489-
Some(NameClass::ConstReference(def)) => highlight_name(db, def),
490-
Some(NameClass::FieldShorthand { .. }) => HighlightTag::Field.into(),
491512
None => highlight_name_by_syntax(name) | HighlightModifier::Definition,
492513
}
493514
}
@@ -498,6 +519,7 @@ fn highlight_element(
498519
}
499520
NAME_REF => {
500521
let name_ref = element.into_node().and_then(ast::NameRef::cast).unwrap();
522+
let possibly_unsafe = is_possibly_unsafe(&name_ref);
501523
match classify_name_ref(sema, &name_ref) {
502524
Some(name_kind) => match name_kind {
503525
NameRefClass::Definition(def) => {
@@ -508,11 +530,13 @@ fn highlight_element(
508530
binding_hash = Some(calc_binding_hash(&name, *shadow_count))
509531
}
510532
};
511-
highlight_name(db, def)
533+
highlight_name(db, def, possibly_unsafe)
512534
}
513535
NameRefClass::FieldShorthand { .. } => HighlightTag::Field.into(),
514536
},
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+
}
516540
None => HighlightTag::UnresolvedReference.into(),
517541
}
518542
}
@@ -652,10 +676,19 @@ fn is_child_of_impl(element: &SyntaxElement) -> bool {
652676
}
653677
}
654678

655-
fn highlight_name(db: &RootDatabase, def: Definition) -> Highlight {
679+
fn highlight_name(db: &RootDatabase, def: Definition, possibly_unsafe: bool) -> Highlight {
656680
match def {
657681
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+
}
659692
Definition::ModuleDef(def) => match def {
660693
hir::ModuleDef::Module(_) => HighlightTag::Module,
661694
hir::ModuleDef::Function(func) => {
@@ -724,7 +757,7 @@ fn highlight_name_by_syntax(name: ast::Name) -> Highlight {
724757
tag.into()
725758
}
726759

727-
fn highlight_name_ref_by_syntax(name: ast::NameRef) -> Highlight {
760+
fn highlight_name_ref_by_syntax(name: ast::NameRef, sema: &Semantics<RootDatabase>) -> Highlight {
728761
let default = HighlightTag::UnresolvedReference;
729762

730763
let parent = match name.syntax().parent() {
@@ -734,7 +767,20 @@ fn highlight_name_ref_by_syntax(name: ast::NameRef) -> Highlight {
734767

735768
let tag = match parent.kind() {
736769
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+
}
738784
PATH_SEGMENT => {
739785
let path = match parent.parent().and_then(ast::Path::cast) {
740786
Some(it) => it,

crates/ra_ide/test_data/highlight_unsafe.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,10 @@
5353
<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>
5454
<span class="keyword unsafe">unsafe</span> <span class="punctuation">{</span>
5555
<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>
5757
<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>
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>
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 unsafe">a</span> <span class="punctuation">}</span> <span class="operator">=&gt;</span> <span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">,</span>
6060
<span class="punctuation">}</span>
6161
<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>
6262
<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>

0 commit comments

Comments
 (0)