use std::any::{Any, TypeId};
use solang_parser::pt::Loc;
use violation_error::ViolationError;
use crate::parser::{CommentsRef, ParseItem};
pub mod macros;
pub mod violation_error;
pub mod contract;
pub mod r#enum;
pub mod error;
pub mod event;
pub mod function;
pub mod r#struct;
pub mod r#type;
pub mod variable;
#[derive(Debug, PartialEq, Eq)]
pub struct Violation {
pub rule_name: &'static str,
pub rule_description: &'static str,
pub error: ViolationError,
pub loc: Loc,
}
pub trait Rule {
type Target: Any;
const NAME: &'static str;
const DESCRIPTION: &'static str;
fn check(
parent: Option<&ParseItem>,
item: &Self::Target,
comments: &CommentsRef,
) -> Option<Violation>;
}
pub trait DynRule {
fn name(&self) -> &'static str;
fn description(&self) -> &'static str;
fn target_type_id(&self) -> TypeId;
fn check_dyn(
&self,
parent: Option<&ParseItem>,
item: &dyn Any,
comments: &CommentsRef,
) -> Option<Violation>;
}
impl Violation {
#[must_use]
pub const fn new(
rule_name: &'static str,
rule_description: &'static str,
error: ViolationError,
loc: Loc,
) -> Self {
Self {
rule_name,
rule_description,
error,
loc,
}
}
}
impl<R: Rule> DynRule for R
where
R::Target: Any,
{
fn name(&self) -> &'static str {
R::NAME
}
fn description(&self) -> &'static str {
R::DESCRIPTION
}
fn target_type_id(&self) -> TypeId {
TypeId::of::<R::Target>()
}
fn check_dyn(
&self,
parent: Option<&ParseItem>,
item: &dyn Any,
comments: &CommentsRef,
) -> Option<Violation> {
let item = item
.downcast_ref::<R::Target>()
.expect("Item type mismatch");
R::check(parent, item, comments)
}
}