Add HighlightTag::Operator, use it for unsafe deref. Move unsafe validation to its own file

This commit is contained in:
Paul Daniel Faria 2020-05-28 09:30:19 -04:00
parent 6c1682396c
commit f678e0d837
11 changed files with 81 additions and 58 deletions

View File

@ -25,9 +25,11 @@
use hir_ty::{
autoderef,
display::{HirDisplayError, HirFormatter},
expr::{ExprValidator, UnsafeValidator},
method_resolution, ApplicationTy, Canonical, GenericPredicate, InEnvironment, Substs,
TraitEnvironment, Ty, TyDefId, TypeCtor,
expr::ExprValidator,
method_resolution,
method_resolution, ApplicationTy, Canonical, InEnvironment, Substs, TraitEnvironment, Ty,
TyDefId, TypeCtor,
unsafe_validation::UnsafeValidator,
};
use ra_db::{CrateId, CrateName, Edition, FileId};
use ra_prof::profile;

View File

@ -9,9 +9,7 @@
use crate::{
db::HirDatabase,
diagnostics::{
MissingFields, MissingMatchArms, MissingOkInTailExpr, MissingPatFields, MissingUnsafe,
},
diagnostics::{MissingFields, MissingMatchArms, MissingOkInTailExpr, MissingPatFields},
lower::CallableDef,
utils::variant_data,
ApplicationTy, InferenceResult, Ty, TypeCtor,
@ -317,8 +315,8 @@ pub fn record_pattern_missing_fields(
}
pub struct UnsafeExpr {
expr: ExprId,
inside_unsafe_block: bool,
pub expr: ExprId,
pub inside_unsafe_block: bool,
}
impl UnsafeExpr {
@ -383,43 +381,3 @@ pub fn unsafe_expressions(
unsafe_exprs
}
pub struct UnsafeValidator<'a, 'b: 'a> {
func: FunctionId,
infer: Arc<InferenceResult>,
sink: &'a mut DiagnosticSink<'b>,
}
impl<'a, 'b> UnsafeValidator<'a, 'b> {
pub fn new(
func: FunctionId,
infer: Arc<InferenceResult>,
sink: &'a mut DiagnosticSink<'b>,
) -> UnsafeValidator<'a, 'b> {
UnsafeValidator { func, infer, sink }
}
pub fn validate_body(&mut self, db: &dyn HirDatabase) {
let def = self.func.into();
let unsafe_expressions = unsafe_expressions(db, self.infer.as_ref(), def);
let func_data = db.function_data(self.func);
if func_data.is_unsafe
|| unsafe_expressions
.iter()
.filter(|unsafe_expr| !unsafe_expr.inside_unsafe_block)
.count()
== 0
{
return;
}
let (_, body_source) = db.body_with_source_map(def);
for unsafe_expr in unsafe_expressions {
if !unsafe_expr.inside_unsafe_block {
if let Ok(in_file) = body_source.as_ref().expr_syntax(unsafe_expr.expr) {
self.sink.push(MissingUnsafe { file: in_file.file_id, expr: in_file.value })
}
}
}
}
}

View File

@ -37,6 +37,7 @@ fn from(it: $sv) -> $e {
pub mod db;
pub mod diagnostics;
pub mod expr;
pub mod unsafe_validation;
#[cfg(test)]
mod tests;

View File

@ -12,9 +12,8 @@
use stdx::format_to;
use crate::{
db::HirDatabase,
diagnostics::Diagnostic,
expr::{ExprValidator, UnsafeValidator},
db::HirDatabase, diagnostics::Diagnostic, expr::ExprValidator,
unsafe_validation::UnsafeValidator,
};
#[salsa::database(

View File

@ -0,0 +1,63 @@
//! Provides validations for unsafe code. Currently checks if unsafe functions are missing
//! unsafe blocks.
use std::sync::Arc;
use hir_def::FunctionId;
use hir_expand::diagnostics::DiagnosticSink;
use crate::{
db::HirDatabase, diagnostics::MissingUnsafe, expr::unsafe_expressions, InferenceResult,
};
pub use hir_def::{
body::{
scope::{ExprScopes, ScopeEntry, ScopeId},
Body, BodySourceMap, ExprPtr, ExprSource, PatPtr, PatSource,
},
expr::{
ArithOp, Array, BinaryOp, BindingAnnotation, CmpOp, Expr, ExprId, Literal, LogicOp,
MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, Statement, UnaryOp,
},
LocalFieldId, VariantId,
};
pub struct UnsafeValidator<'a, 'b: 'a> {
func: FunctionId,
infer: Arc<InferenceResult>,
sink: &'a mut DiagnosticSink<'b>,
}
impl<'a, 'b> UnsafeValidator<'a, 'b> {
pub fn new(
func: FunctionId,
infer: Arc<InferenceResult>,
sink: &'a mut DiagnosticSink<'b>,
) -> UnsafeValidator<'a, 'b> {
UnsafeValidator { func, infer, sink }
}
pub fn validate_body(&mut self, db: &dyn HirDatabase) {
let def = self.func.into();
let unsafe_expressions = unsafe_expressions(db, self.infer.as_ref(), def);
let func_data = db.function_data(self.func);
if func_data.is_unsafe
|| unsafe_expressions
.iter()
.filter(|unsafe_expr| !unsafe_expr.inside_unsafe_block)
.count()
== 0
{
return;
}
let (_, body_source) = db.body_with_source_map(def);
for unsafe_expr in unsafe_expressions {
if !unsafe_expr.inside_unsafe_block {
if let Ok(in_file) = body_source.as_ref().expr_syntax(unsafe_expr.expr) {
self.sink.push(MissingUnsafe { file: in_file.file_id, expr: in_file.value })
}
}
}
}
}

View File

@ -12,7 +12,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
.string_literal { color: #CC9393; }
.field { color: #94BFF3; }
.function { color: #93E0E3; }
.function.unsafe { color: #BC8383; }
.function.unsafe { color: #E28C14; }
.operator.unsafe { color: #BC8383; }
.parameter { color: #94BFF3; }
.text { color: #DCDCCC; }

View File

@ -12,7 +12,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
.string_literal { color: #CC9393; }
.field { color: #94BFF3; }
.function { color: #93E0E3; }
.function.unsafe { color: #BC8383; }
.function.unsafe { color: #E28C14; }
.operator.unsafe { color: #BC8383; }
.parameter { color: #94BFF3; }
.text { color: #DCDCCC; }

View File

@ -12,7 +12,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
.string_literal { color: #CC9393; }
.field { color: #94BFF3; }
.function { color: #93E0E3; }
.function.unsafe { color: #BC8383; }
.function.unsafe { color: #E28C14; }
.operator.unsafe { color: #BC8383; }
.parameter { color: #94BFF3; }
.text { color: #DCDCCC; }
@ -47,7 +47,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
<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">y</span> = <span class="function 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>

View File

@ -12,7 +12,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
.string_literal { color: #CC9393; }
.field { color: #94BFF3; }
.function { color: #93E0E3; }
.function.unsafe { color: #BC8383; }
.function.unsafe { color: #E28C14; }
.operator.unsafe { color: #BC8383; }
.parameter { color: #94BFF3; }
.text { color: #DCDCCC; }

View File

@ -12,7 +12,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
.string_literal { color: #CC9393; }
.field { color: #94BFF3; }
.function { color: #93E0E3; }
.function.unsafe { color: #BC8383; }
.function.unsafe { color: #E28C14; }
.operator.unsafe { color: #BC8383; }
.parameter { color: #94BFF3; }
.text { color: #DCDCCC; }

View File

@ -71,7 +71,7 @@ fn html_escape(text: &str) -> String {
.string_literal { color: #CC9393; }
.field { color: #94BFF3; }
.function { color: #93E0E3; }
.function.unsafe { color: #BC8383; }
.function.unsafe { color: #E28C14; }
.operator.unsafe { color: #BC8383; }
.parameter { color: #94BFF3; }
.text { color: #DCDCCC; }