mirror of
				https://github.com/rust-lang/rust-analyzer.git
				synced 2025-11-03 13:13:18 +00:00 
			
		
		
		
	Merge #4720
4720: Add highlight support for unsafe fn calls and raw ptr deref r=matklad a=Nashenas88 Addresses ide highlighting for #190 Co-authored-by: Paul Daniel Faria <Nashenas88@users.noreply.github.com>
This commit is contained in:
		
						commit
						dff8140a2e
					
				@ -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);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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; }
 | 
			
		||||
 | 
			
		||||
@ -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; }
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										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; }
 | 
			
		||||
.field              { color: #94BFF3; }
 | 
			
		||||
.function           { color: #93E0E3; }
 | 
			
		||||
.operator.unsafe    { color: #E28C14; }
 | 
			
		||||
.parameter          { color: #94BFF3; }
 | 
			
		||||
.text               { color: #DCDCCC; }
 | 
			
		||||
.type               { color: #7CB8BB; }
 | 
			
		||||
 | 
			
		||||
@ -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; }
 | 
			
		||||
 | 
			
		||||
@ -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,
 | 
			
		||||
 | 
			
		||||
@ -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; }
 | 
			
		||||
 | 
			
		||||
@ -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",
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user