From a9cb2933fbeddef4ed70bde77ded4f9bb185548e Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Tue, 2 Jun 2020 18:49:09 -0400 Subject: Add highlight support for unsafe fn calls and raw ptr deref --- crates/ra_hir/src/code_model.rs | 8 ++++ crates/ra_hir_def/src/data.rs | 6 ++- .../ra_ide/src/snapshots/highlight_injection.html | 1 + crates/ra_ide/src/snapshots/highlight_strings.html | 1 + crates/ra_ide/src/snapshots/highlight_unsafe.html | 48 ++++++++++++++++++++++ crates/ra_ide/src/snapshots/highlighting.html | 1 + .../ra_ide/src/snapshots/rainbow_highlighting.html | 1 + crates/ra_ide/src/syntax_highlighting.rs | 25 ++++++++++- crates/ra_ide/src/syntax_highlighting/html.rs | 1 + crates/ra_ide/src/syntax_highlighting/tags.rs | 8 ++-- crates/ra_ide/src/syntax_highlighting/tests.rs | 31 ++++++++++++++ 11 files changed, 125 insertions(+), 6 deletions(-) create mode 100644 crates/ra_ide/src/snapshots/highlight_unsafe.html (limited to 'crates') diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index e40aeffbc..4a06f3bcd 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -637,6 +637,10 @@ impl Function { 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) { let _p = profile("Function::diagnostics"); 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 { return go(&self.ty.value); diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs index e2130d931..807195d25 100644 --- a/crates/ra_hir_def/src/data.rs +++ b/crates/ra_hir_def/src/data.rs @@ -34,6 +34,7 @@ pub struct FunctionData { /// True if the first param is `self`. This is relevant to decide whether this /// can be called as a method. pub has_self_param: bool, + pub is_unsafe: bool, pub visibility: RawVisibility, } @@ -85,11 +86,14 @@ impl FunctionData { ret_type }; + let is_unsafe = src.value.unsafe_token().is_some(); + let vis_default = RawVisibility::default_for_container(loc.container); let 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) } } diff --git a/crates/ra_ide/src/snapshots/highlight_injection.html b/crates/ra_ide/src/snapshots/highlight_injection.html index 68fc589bc..fcdc98201 100644 --- a/crates/ra_ide/src/snapshots/highlight_injection.html +++ b/crates/ra_ide/src/snapshots/highlight_injection.html @@ -10,6 +10,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } +.operator.unsafe { color: #E28C14; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } diff --git a/crates/ra_ide/src/snapshots/highlight_strings.html b/crates/ra_ide/src/snapshots/highlight_strings.html index 41cddd0ff..e97192b61 100644 --- a/crates/ra_ide/src/snapshots/highlight_strings.html +++ b/crates/ra_ide/src/snapshots/highlight_strings.html @@ -10,6 +10,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } +.operator.unsafe { color: #E28C14; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } diff --git a/crates/ra_ide/src/snapshots/highlight_unsafe.html b/crates/ra_ide/src/snapshots/highlight_unsafe.html new file mode 100644 index 000000000..17ffc727c --- /dev/null +++ b/crates/ra_ide/src/snapshots/highlight_unsafe.html @@ -0,0 +1,48 @@ + + +
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;
+    }
+}
\ No newline at end of file diff --git a/crates/ra_ide/src/snapshots/highlighting.html b/crates/ra_ide/src/snapshots/highlighting.html index 352e35095..42c5f3e55 100644 --- a/crates/ra_ide/src/snapshots/highlighting.html +++ b/crates/ra_ide/src/snapshots/highlighting.html @@ -10,6 +10,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } +.operator.unsafe { color: #E28C14; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } diff --git a/crates/ra_ide/src/snapshots/rainbow_highlighting.html b/crates/ra_ide/src/snapshots/rainbow_highlighting.html index 2a0294f71..2dd61d20d 100644 --- a/crates/ra_ide/src/snapshots/rainbow_highlighting.html +++ b/crates/ra_ide/src/snapshots/rainbow_highlighting.html @@ -10,6 +10,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } +.operator.unsafe { color: #E28C14; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs index 0b53ebe69..19ecd54d6 100644 --- a/crates/ra_ide/src/syntax_highlighting.rs +++ b/crates/ra_ide/src/syntax_highlighting.rs @@ -406,6 +406,23 @@ fn highlight_element( _ => 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() => { let h = Highlight::new(HighlightTag::Keyword); @@ -458,7 +475,13 @@ fn highlight_name(db: &RootDatabase, def: Definition) -> Highlight { Definition::Field(_) => HighlightTag::Field, Definition::ModuleDef(def) => match def { 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::Enum(_)) => HighlightTag::Enum, hir::ModuleDef::Adt(hir::Adt::Union(_)) => HighlightTag::Union, diff --git a/crates/ra_ide/src/syntax_highlighting/html.rs b/crates/ra_ide/src/syntax_highlighting/html.rs index edfe61f39..7d946c98d 100644 --- a/crates/ra_ide/src/syntax_highlighting/html.rs +++ b/crates/ra_ide/src/syntax_highlighting/html.rs @@ -69,6 +69,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } +.operator.unsafe { color: #E28C14; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } diff --git a/crates/ra_ide/src/syntax_highlighting/tags.rs b/crates/ra_ide/src/syntax_highlighting/tags.rs index 1514531de..94f466966 100644 --- a/crates/ra_ide/src/syntax_highlighting/tags.rs +++ b/crates/ra_ide/src/syntax_highlighting/tags.rs @@ -24,12 +24,14 @@ pub enum HighlightTag { Enum, EnumVariant, Field, + FormatSpecifier, Function, Keyword, Lifetime, Macro, Module, NumericLiteral, + Operator, SelfKeyword, SelfType, Static, @@ -41,8 +43,6 @@ pub enum HighlightTag { Union, Local, UnresolvedReference, - FormatSpecifier, - Operator, } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] @@ -72,12 +72,14 @@ impl HighlightTag { HighlightTag::Enum => "enum", HighlightTag::EnumVariant => "enum_variant", HighlightTag::Field => "field", + HighlightTag::FormatSpecifier => "format_specifier", HighlightTag::Function => "function", HighlightTag::Keyword => "keyword", HighlightTag::Lifetime => "lifetime", HighlightTag::Macro => "macro", HighlightTag::Module => "module", HighlightTag::NumericLiteral => "numeric_literal", + HighlightTag::Operator => "operator", HighlightTag::SelfKeyword => "self_keyword", HighlightTag::SelfType => "self_type", HighlightTag::Static => "static", @@ -89,8 +91,6 @@ impl HighlightTag { HighlightTag::Union => "union", HighlightTag::Local => "variable", HighlightTag::UnresolvedReference => "unresolved_reference", - HighlightTag::FormatSpecifier => "format_specifier", - HighlightTag::Operator => "operator", } } } diff --git a/crates/ra_ide/src/syntax_highlighting/tests.rs b/crates/ra_ide/src/syntax_highlighting/tests.rs index 7dc229cab..36a1aa419 100644 --- a/crates/ra_ide/src/syntax_highlighting/tests.rs +++ b/crates/ra_ide/src/syntax_highlighting/tests.rs @@ -258,3 +258,34 @@ fn main() { fs::write(dst_file, &actual_html).unwrap(); 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); +} -- cgit v1.2.3