Apply unsafe semantic highlighting to union field access
This commit is contained in:
parent
3bf033e548
commit
be935b2b56
@ -4,7 +4,7 @@
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
use hir::{Name, Semantics};
|
use hir::{Name, Semantics, VariantDef};
|
||||||
use ra_ide_db::{
|
use ra_ide_db::{
|
||||||
defs::{classify_name, classify_name_ref, Definition, NameClass, NameRefClass},
|
defs::{classify_name, classify_name_ref, Definition, NameClass, NameRefClass},
|
||||||
RootDatabase,
|
RootDatabase,
|
||||||
@ -455,6 +455,18 @@ fn macro_call_range(macro_call: &ast::MacroCall) -> Option<TextRange> {
|
|||||||
Some(TextRange::new(range_start, range_end))
|
Some(TextRange::new(range_start, range_end))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_possibly_unsafe(name_ref: &ast::NameRef) -> bool {
|
||||||
|
name_ref
|
||||||
|
.syntax()
|
||||||
|
.parent()
|
||||||
|
.and_then(|parent| {
|
||||||
|
ast::FieldExpr::cast(parent.clone())
|
||||||
|
.map(|_| true)
|
||||||
|
.or_else(|| ast::RecordPatField::cast(parent).map(|_| true))
|
||||||
|
})
|
||||||
|
.unwrap_or(false)
|
||||||
|
}
|
||||||
|
|
||||||
fn highlight_element(
|
fn highlight_element(
|
||||||
sema: &Semantics<RootDatabase>,
|
sema: &Semantics<RootDatabase>,
|
||||||
bindings_shadow_count: &mut FxHashMap<Name, u32>,
|
bindings_shadow_count: &mut FxHashMap<Name, u32>,
|
||||||
@ -484,10 +496,19 @@ fn highlight_element(
|
|||||||
|
|
||||||
match name_kind {
|
match name_kind {
|
||||||
Some(NameClass::Definition(def)) => {
|
Some(NameClass::Definition(def)) => {
|
||||||
highlight_name(db, def) | HighlightModifier::Definition
|
highlight_name(db, def, false) | HighlightModifier::Definition
|
||||||
|
}
|
||||||
|
Some(NameClass::ConstReference(def)) => highlight_name(db, def, false),
|
||||||
|
Some(NameClass::FieldShorthand { field, .. }) => {
|
||||||
|
let mut h = HighlightTag::Field.into();
|
||||||
|
if let Definition::Field(field) = field {
|
||||||
|
if let VariantDef::Union(_) = field.parent_def(db) {
|
||||||
|
h |= HighlightModifier::Unsafe;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h
|
||||||
}
|
}
|
||||||
Some(NameClass::ConstReference(def)) => highlight_name(db, def),
|
|
||||||
Some(NameClass::FieldShorthand { .. }) => HighlightTag::Field.into(),
|
|
||||||
None => highlight_name_by_syntax(name) | HighlightModifier::Definition,
|
None => highlight_name_by_syntax(name) | HighlightModifier::Definition,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -498,6 +519,7 @@ fn highlight_element(
|
|||||||
}
|
}
|
||||||
NAME_REF => {
|
NAME_REF => {
|
||||||
let name_ref = element.into_node().and_then(ast::NameRef::cast).unwrap();
|
let name_ref = element.into_node().and_then(ast::NameRef::cast).unwrap();
|
||||||
|
let possibly_unsafe = is_possibly_unsafe(&name_ref);
|
||||||
match classify_name_ref(sema, &name_ref) {
|
match classify_name_ref(sema, &name_ref) {
|
||||||
Some(name_kind) => match name_kind {
|
Some(name_kind) => match name_kind {
|
||||||
NameRefClass::Definition(def) => {
|
NameRefClass::Definition(def) => {
|
||||||
@ -508,11 +530,13 @@ fn highlight_element(
|
|||||||
binding_hash = Some(calc_binding_hash(&name, *shadow_count))
|
binding_hash = Some(calc_binding_hash(&name, *shadow_count))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
highlight_name(db, def)
|
highlight_name(db, def, possibly_unsafe)
|
||||||
}
|
}
|
||||||
NameRefClass::FieldShorthand { .. } => HighlightTag::Field.into(),
|
NameRefClass::FieldShorthand { .. } => HighlightTag::Field.into(),
|
||||||
},
|
},
|
||||||
None if syntactic_name_ref_highlighting => highlight_name_ref_by_syntax(name_ref),
|
None if syntactic_name_ref_highlighting => {
|
||||||
|
highlight_name_ref_by_syntax(name_ref, sema)
|
||||||
|
}
|
||||||
None => HighlightTag::UnresolvedReference.into(),
|
None => HighlightTag::UnresolvedReference.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -652,10 +676,19 @@ fn is_child_of_impl(element: &SyntaxElement) -> bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn highlight_name(db: &RootDatabase, def: Definition) -> Highlight {
|
fn highlight_name(db: &RootDatabase, def: Definition, possibly_unsafe: bool) -> Highlight {
|
||||||
match def {
|
match def {
|
||||||
Definition::Macro(_) => HighlightTag::Macro,
|
Definition::Macro(_) => HighlightTag::Macro,
|
||||||
Definition::Field(_) => HighlightTag::Field,
|
Definition::Field(field) => {
|
||||||
|
let mut h = HighlightTag::Field.into();
|
||||||
|
if possibly_unsafe {
|
||||||
|
if let VariantDef::Union(_) = field.parent_def(db) {
|
||||||
|
h |= HighlightModifier::Unsafe;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return h;
|
||||||
|
}
|
||||||
Definition::ModuleDef(def) => match def {
|
Definition::ModuleDef(def) => match def {
|
||||||
hir::ModuleDef::Module(_) => HighlightTag::Module,
|
hir::ModuleDef::Module(_) => HighlightTag::Module,
|
||||||
hir::ModuleDef::Function(func) => {
|
hir::ModuleDef::Function(func) => {
|
||||||
@ -724,7 +757,7 @@ fn highlight_name_by_syntax(name: ast::Name) -> Highlight {
|
|||||||
tag.into()
|
tag.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn highlight_name_ref_by_syntax(name: ast::NameRef) -> Highlight {
|
fn highlight_name_ref_by_syntax(name: ast::NameRef, sema: &Semantics<RootDatabase>) -> Highlight {
|
||||||
let default = HighlightTag::UnresolvedReference;
|
let default = HighlightTag::UnresolvedReference;
|
||||||
|
|
||||||
let parent = match name.syntax().parent() {
|
let parent = match name.syntax().parent() {
|
||||||
@ -734,7 +767,20 @@ fn highlight_name_ref_by_syntax(name: ast::NameRef) -> Highlight {
|
|||||||
|
|
||||||
let tag = match parent.kind() {
|
let tag = match parent.kind() {
|
||||||
METHOD_CALL_EXPR => HighlightTag::Function,
|
METHOD_CALL_EXPR => HighlightTag::Function,
|
||||||
FIELD_EXPR => HighlightTag::Field,
|
FIELD_EXPR => {
|
||||||
|
let h = HighlightTag::Field;
|
||||||
|
let is_union = ast::FieldExpr::cast(parent)
|
||||||
|
.and_then(|field_expr| {
|
||||||
|
let field = sema.resolve_field(&field_expr)?;
|
||||||
|
Some(if let VariantDef::Union(_) = field.parent_def(sema.db) {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.unwrap_or(false);
|
||||||
|
return if is_union { h | HighlightModifier::Unsafe } else { h.into() };
|
||||||
|
}
|
||||||
PATH_SEGMENT => {
|
PATH_SEGMENT => {
|
||||||
let path = match parent.parent().and_then(ast::Path::cast) {
|
let path = match parent.parent().and_then(ast::Path::cast) {
|
||||||
Some(it) => it,
|
Some(it) => it,
|
||||||
|
@ -53,10 +53,10 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
|||||||
<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>
|
<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>
|
||||||
<span class="keyword unsafe">unsafe</span> <span class="punctuation">{</span>
|
<span class="keyword unsafe">unsafe</span> <span class="punctuation">{</span>
|
||||||
<span class="function unsafe">unsafe_fn</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span>
|
<span class="function unsafe">unsafe_fn</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span>
|
||||||
<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>
|
<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>
|
||||||
<span class="keyword control">match</span> <span class="variable">u</span> <span class="punctuation">{</span>
|
<span class="keyword control">match</span> <span class="variable">u</span> <span class="punctuation">{</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="operator">=></span> <span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">,</span>
|
<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>
|
||||||
<span class="union">Union</span> <span class="punctuation">{</span> <span class="field">a</span> <span class="punctuation">}</span> <span class="operator">=></span> <span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">,</span>
|
<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>
|
||||||
<span class="punctuation">}</span>
|
<span class="punctuation">}</span>
|
||||||
<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>
|
<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>
|
||||||
<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>
|
<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>
|
||||||
|
Loading…
Reference in New Issue
Block a user