mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-28 21:05:02 +00:00
Add highlight support for unsafe fn calls and raw ptr deref
This commit is contained in:
parent
2f6ab77708
commit
a9cb2933fb
11 changed files with 125 additions and 6 deletions
|
@ -637,6 +637,10 @@ impl Function {
|
||||||
db.function_data(self.id).params.clone()
|
db.function_data(self.id).params.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_unsafe(self, db: &dyn HirDatabase) -> bool {
|
||||||
|
db.function_data(self.id).is_unsafe
|
||||||
|
}
|
||||||
|
|
||||||
pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) {
|
pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) {
|
||||||
let _p = profile("Function::diagnostics");
|
let _p = profile("Function::diagnostics");
|
||||||
let infer = db.infer(self.id.into());
|
let infer = db.infer(self.id.into());
|
||||||
|
@ -1190,6 +1194,10 @@ impl Type {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_raw_ptr(&self) -> bool {
|
||||||
|
matches!(&self.ty.value, Ty::Apply(ApplicationTy { ctor: TypeCtor::RawPtr(..), .. }))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn contains_unknown(&self) -> bool {
|
pub fn contains_unknown(&self) -> bool {
|
||||||
return go(&self.ty.value);
|
return go(&self.ty.value);
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@ pub struct FunctionData {
|
||||||
/// True if the first param is `self`. This is relevant to decide whether this
|
/// True if the first param is `self`. This is relevant to decide whether this
|
||||||
/// can be called as a method.
|
/// can be called as a method.
|
||||||
pub has_self_param: bool,
|
pub has_self_param: bool,
|
||||||
|
pub is_unsafe: bool,
|
||||||
pub visibility: RawVisibility,
|
pub visibility: RawVisibility,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,11 +86,14 @@ impl FunctionData {
|
||||||
ret_type
|
ret_type
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let is_unsafe = src.value.unsafe_token().is_some();
|
||||||
|
|
||||||
let vis_default = RawVisibility::default_for_container(loc.container);
|
let vis_default = RawVisibility::default_for_container(loc.container);
|
||||||
let visibility =
|
let visibility =
|
||||||
RawVisibility::from_ast_with_default(db, vis_default, src.map(|s| s.visibility()));
|
RawVisibility::from_ast_with_default(db, vis_default, src.map(|s| s.visibility()));
|
||||||
|
|
||||||
let sig = FunctionData { name, params, ret_type, has_self_param, visibility, attrs };
|
let sig =
|
||||||
|
FunctionData { name, params, ret_type, has_self_param, is_unsafe, visibility, attrs };
|
||||||
Arc::new(sig)
|
Arc::new(sig)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||||
.string_literal { color: #CC9393; }
|
.string_literal { color: #CC9393; }
|
||||||
.field { color: #94BFF3; }
|
.field { color: #94BFF3; }
|
||||||
.function { color: #93E0E3; }
|
.function { color: #93E0E3; }
|
||||||
|
.operator.unsafe { color: #E28C14; }
|
||||||
.parameter { color: #94BFF3; }
|
.parameter { color: #94BFF3; }
|
||||||
.text { color: #DCDCCC; }
|
.text { color: #DCDCCC; }
|
||||||
.type { color: #7CB8BB; }
|
.type { color: #7CB8BB; }
|
||||||
|
|
|
@ -10,6 +10,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||||
.string_literal { color: #CC9393; }
|
.string_literal { color: #CC9393; }
|
||||||
.field { color: #94BFF3; }
|
.field { color: #94BFF3; }
|
||||||
.function { color: #93E0E3; }
|
.function { color: #93E0E3; }
|
||||||
|
.operator.unsafe { color: #E28C14; }
|
||||||
.parameter { color: #94BFF3; }
|
.parameter { color: #94BFF3; }
|
||||||
.text { color: #DCDCCC; }
|
.text { color: #DCDCCC; }
|
||||||
.type { color: #7CB8BB; }
|
.type { color: #7CB8BB; }
|
||||||
|
|
48
crates/ra_ide/src/snapshots/highlight_unsafe.html
Normal file
48
crates/ra_ide/src/snapshots/highlight_unsafe.html
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
|
||||||
|
<style>
|
||||||
|
body { margin: 0; }
|
||||||
|
pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4em; }
|
||||||
|
|
||||||
|
.lifetime { color: #DFAF8F; font-style: italic; }
|
||||||
|
.comment { color: #7F9F7F; }
|
||||||
|
.struct, .enum { color: #7CB8BB; }
|
||||||
|
.enum_variant { color: #BDE0F3; }
|
||||||
|
.string_literal { color: #CC9393; }
|
||||||
|
.field { color: #94BFF3; }
|
||||||
|
.function { color: #93E0E3; }
|
||||||
|
.operator.unsafe { color: #E28C14; }
|
||||||
|
.parameter { color: #94BFF3; }
|
||||||
|
.text { color: #DCDCCC; }
|
||||||
|
.type { color: #7CB8BB; }
|
||||||
|
.builtin_type { color: #8CD0D3; }
|
||||||
|
.type_param { color: #DFAF8F; }
|
||||||
|
.attribute { color: #94BFF3; }
|
||||||
|
.numeric_literal { color: #BFEBBF; }
|
||||||
|
.bool_literal { color: #BFE6EB; }
|
||||||
|
.macro { color: #94BFF3; }
|
||||||
|
.module { color: #AFD8AF; }
|
||||||
|
.variable { color: #DCDCCC; }
|
||||||
|
.format_specifier { color: #CC696B; }
|
||||||
|
.mutable { text-decoration: underline; }
|
||||||
|
|
||||||
|
.keyword { color: #F0DFAF; font-weight: bold; }
|
||||||
|
.keyword.unsafe { color: #BC8383; font-weight: bold; }
|
||||||
|
.control { font-style: italic; }
|
||||||
|
</style>
|
||||||
|
<pre><code><span class="keyword unsafe">unsafe</span> <span class="keyword">fn</span> <span class="function declaration unsafe">unsafe_fn</span>() {}
|
||||||
|
|
||||||
|
<span class="keyword">struct</span> <span class="struct declaration">HasUnsafeFn</span>;
|
||||||
|
|
||||||
|
<span class="keyword">impl</span> <span class="struct">HasUnsafeFn</span> {
|
||||||
|
<span class="keyword unsafe">unsafe</span> <span class="keyword">fn</span> <span class="function declaration unsafe">unsafe_method</span>(&<span class="self_keyword">self</span>) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
<span class="keyword">fn</span> <span class="function declaration">main</span>() {
|
||||||
|
<span class="keyword">let</span> <span class="variable declaration">x</span> = &<span class="numeric_literal">5</span> <span class="keyword">as</span> *<span class="keyword">const</span> <span class="builtin_type">usize</span>;
|
||||||
|
<span class="keyword unsafe">unsafe</span> {
|
||||||
|
<span class="function unsafe">unsafe_fn</span>();
|
||||||
|
<span class="struct">HasUnsafeFn</span>.<span class="function unsafe">unsafe_method</span>();
|
||||||
|
<span class="keyword">let</span> <span class="variable declaration">y</span> = <span class="operator unsafe">*</span><span class="variable">x</span>;
|
||||||
|
<span class="keyword">let</span> <span class="variable declaration">z</span> = -<span class="variable">x</span>;
|
||||||
|
}
|
||||||
|
}</code></pre>
|
|
@ -10,6 +10,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||||
.string_literal { color: #CC9393; }
|
.string_literal { color: #CC9393; }
|
||||||
.field { color: #94BFF3; }
|
.field { color: #94BFF3; }
|
||||||
.function { color: #93E0E3; }
|
.function { color: #93E0E3; }
|
||||||
|
.operator.unsafe { color: #E28C14; }
|
||||||
.parameter { color: #94BFF3; }
|
.parameter { color: #94BFF3; }
|
||||||
.text { color: #DCDCCC; }
|
.text { color: #DCDCCC; }
|
||||||
.type { color: #7CB8BB; }
|
.type { color: #7CB8BB; }
|
||||||
|
|
|
@ -10,6 +10,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||||
.string_literal { color: #CC9393; }
|
.string_literal { color: #CC9393; }
|
||||||
.field { color: #94BFF3; }
|
.field { color: #94BFF3; }
|
||||||
.function { color: #93E0E3; }
|
.function { color: #93E0E3; }
|
||||||
|
.operator.unsafe { color: #E28C14; }
|
||||||
.parameter { color: #94BFF3; }
|
.parameter { color: #94BFF3; }
|
||||||
.text { color: #DCDCCC; }
|
.text { color: #DCDCCC; }
|
||||||
.type { color: #7CB8BB; }
|
.type { color: #7CB8BB; }
|
||||||
|
|
|
@ -406,6 +406,23 @@ fn highlight_element(
|
||||||
_ => h,
|
_ => h,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
PREFIX_EXPR => {
|
||||||
|
let prefix_expr = element.into_node().and_then(ast::PrefixExpr::cast)?;
|
||||||
|
match prefix_expr.op_kind() {
|
||||||
|
Some(ast::PrefixOp::Deref) => {}
|
||||||
|
_ => return None,
|
||||||
|
}
|
||||||
|
|
||||||
|
let expr = prefix_expr.expr()?;
|
||||||
|
let ty = sema.type_of_expr(&expr)?;
|
||||||
|
if !ty.is_raw_ptr() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut h = Highlight::new(HighlightTag::Operator);
|
||||||
|
h |= HighlightModifier::Unsafe;
|
||||||
|
h
|
||||||
|
}
|
||||||
|
|
||||||
k if k.is_keyword() => {
|
k if k.is_keyword() => {
|
||||||
let h = Highlight::new(HighlightTag::Keyword);
|
let h = Highlight::new(HighlightTag::Keyword);
|
||||||
|
@ -458,7 +475,13 @@ fn highlight_name(db: &RootDatabase, def: Definition) -> Highlight {
|
||||||
Definition::Field(_) => HighlightTag::Field,
|
Definition::Field(_) => HighlightTag::Field,
|
||||||
Definition::ModuleDef(def) => match def {
|
Definition::ModuleDef(def) => match def {
|
||||||
hir::ModuleDef::Module(_) => HighlightTag::Module,
|
hir::ModuleDef::Module(_) => HighlightTag::Module,
|
||||||
hir::ModuleDef::Function(_) => HighlightTag::Function,
|
hir::ModuleDef::Function(func) => {
|
||||||
|
let mut h = HighlightTag::Function.into();
|
||||||
|
if func.is_unsafe(db) {
|
||||||
|
h |= HighlightModifier::Unsafe;
|
||||||
|
}
|
||||||
|
return h;
|
||||||
|
}
|
||||||
hir::ModuleDef::Adt(hir::Adt::Struct(_)) => HighlightTag::Struct,
|
hir::ModuleDef::Adt(hir::Adt::Struct(_)) => HighlightTag::Struct,
|
||||||
hir::ModuleDef::Adt(hir::Adt::Enum(_)) => HighlightTag::Enum,
|
hir::ModuleDef::Adt(hir::Adt::Enum(_)) => HighlightTag::Enum,
|
||||||
hir::ModuleDef::Adt(hir::Adt::Union(_)) => HighlightTag::Union,
|
hir::ModuleDef::Adt(hir::Adt::Union(_)) => HighlightTag::Union,
|
||||||
|
|
|
@ -69,6 +69,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||||
.string_literal { color: #CC9393; }
|
.string_literal { color: #CC9393; }
|
||||||
.field { color: #94BFF3; }
|
.field { color: #94BFF3; }
|
||||||
.function { color: #93E0E3; }
|
.function { color: #93E0E3; }
|
||||||
|
.operator.unsafe { color: #E28C14; }
|
||||||
.parameter { color: #94BFF3; }
|
.parameter { color: #94BFF3; }
|
||||||
.text { color: #DCDCCC; }
|
.text { color: #DCDCCC; }
|
||||||
.type { color: #7CB8BB; }
|
.type { color: #7CB8BB; }
|
||||||
|
|
|
@ -24,12 +24,14 @@ pub enum HighlightTag {
|
||||||
Enum,
|
Enum,
|
||||||
EnumVariant,
|
EnumVariant,
|
||||||
Field,
|
Field,
|
||||||
|
FormatSpecifier,
|
||||||
Function,
|
Function,
|
||||||
Keyword,
|
Keyword,
|
||||||
Lifetime,
|
Lifetime,
|
||||||
Macro,
|
Macro,
|
||||||
Module,
|
Module,
|
||||||
NumericLiteral,
|
NumericLiteral,
|
||||||
|
Operator,
|
||||||
SelfKeyword,
|
SelfKeyword,
|
||||||
SelfType,
|
SelfType,
|
||||||
Static,
|
Static,
|
||||||
|
@ -41,8 +43,6 @@ pub enum HighlightTag {
|
||||||
Union,
|
Union,
|
||||||
Local,
|
Local,
|
||||||
UnresolvedReference,
|
UnresolvedReference,
|
||||||
FormatSpecifier,
|
|
||||||
Operator,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||||
|
@ -72,12 +72,14 @@ impl HighlightTag {
|
||||||
HighlightTag::Enum => "enum",
|
HighlightTag::Enum => "enum",
|
||||||
HighlightTag::EnumVariant => "enum_variant",
|
HighlightTag::EnumVariant => "enum_variant",
|
||||||
HighlightTag::Field => "field",
|
HighlightTag::Field => "field",
|
||||||
|
HighlightTag::FormatSpecifier => "format_specifier",
|
||||||
HighlightTag::Function => "function",
|
HighlightTag::Function => "function",
|
||||||
HighlightTag::Keyword => "keyword",
|
HighlightTag::Keyword => "keyword",
|
||||||
HighlightTag::Lifetime => "lifetime",
|
HighlightTag::Lifetime => "lifetime",
|
||||||
HighlightTag::Macro => "macro",
|
HighlightTag::Macro => "macro",
|
||||||
HighlightTag::Module => "module",
|
HighlightTag::Module => "module",
|
||||||
HighlightTag::NumericLiteral => "numeric_literal",
|
HighlightTag::NumericLiteral => "numeric_literal",
|
||||||
|
HighlightTag::Operator => "operator",
|
||||||
HighlightTag::SelfKeyword => "self_keyword",
|
HighlightTag::SelfKeyword => "self_keyword",
|
||||||
HighlightTag::SelfType => "self_type",
|
HighlightTag::SelfType => "self_type",
|
||||||
HighlightTag::Static => "static",
|
HighlightTag::Static => "static",
|
||||||
|
@ -89,8 +91,6 @@ impl HighlightTag {
|
||||||
HighlightTag::Union => "union",
|
HighlightTag::Union => "union",
|
||||||
HighlightTag::Local => "variable",
|
HighlightTag::Local => "variable",
|
||||||
HighlightTag::UnresolvedReference => "unresolved_reference",
|
HighlightTag::UnresolvedReference => "unresolved_reference",
|
||||||
HighlightTag::FormatSpecifier => "format_specifier",
|
|
||||||
HighlightTag::Operator => "operator",
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -258,3 +258,34 @@ fn main() {
|
||||||
fs::write(dst_file, &actual_html).unwrap();
|
fs::write(dst_file, &actual_html).unwrap();
|
||||||
assert_eq_text!(expected_html, actual_html);
|
assert_eq_text!(expected_html, actual_html);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_unsafe_highlighting() {
|
||||||
|
let (analysis, file_id) = single_file(
|
||||||
|
r#"
|
||||||
|
unsafe fn unsafe_fn() {}
|
||||||
|
|
||||||
|
struct HasUnsafeFn;
|
||||||
|
|
||||||
|
impl HasUnsafeFn {
|
||||||
|
unsafe fn unsafe_method(&self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let x = &5 as *const usize;
|
||||||
|
unsafe {
|
||||||
|
unsafe_fn();
|
||||||
|
HasUnsafeFn.unsafe_method();
|
||||||
|
let y = *x;
|
||||||
|
let z = -x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#
|
||||||
|
.trim(),
|
||||||
|
);
|
||||||
|
let dst_file = project_dir().join("crates/ra_ide/src/snapshots/highlight_unsafe.html");
|
||||||
|
let actual_html = &analysis.highlight_as_html(file_id, false).unwrap();
|
||||||
|
let expected_html = &read_text(&dst_file);
|
||||||
|
fs::write(dst_file, &actual_html).unwrap();
|
||||||
|
assert_eq_text!(expected_html, actual_html);
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue