Add HighlightTag::Operator, use it for unsafe deref. Move unsafe validation to its own file
This commit is contained in:
@@ -9,9 +9,7 @@ use rustc_hash::FxHashSet;
|
||||
|
||||
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 })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ pub(crate) mod utils;
|
||||
pub mod db;
|
||||
pub mod diagnostics;
|
||||
pub mod expr;
|
||||
pub mod unsafe_validation;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
@@ -12,9 +12,8 @@ use rustc_hash::FxHashSet;
|
||||
use stdx::format_to;
|
||||
|
||||
use crate::{
|
||||
db::HirDatabase,
|
||||
diagnostics::Diagnostic,
|
||||
expr::{ExprValidator, UnsafeValidator},
|
||||
db::HirDatabase, diagnostics::Diagnostic, expr::ExprValidator,
|
||||
unsafe_validation::UnsafeValidator,
|
||||
};
|
||||
|
||||
#[salsa::database(
|
||||
|
||||
63
crates/ra_hir_ty/src/unsafe_validation.rs
Normal file
63
crates/ra_hir_ty/src/unsafe_validation.rs
Normal 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 })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user