use std::collections::HashMap;
use gobject_ast::model::GObjectTypeKind;
use crate::{
ast_context::AstContext,
config::Config,
rules::{Rule, Violation},
};
pub struct MatchingDeclareDefine;
impl Rule for MatchingDeclareDefine {
fn name(&self) -> &'static str {
"matching_declare_define"
}
fn description(&self) -> &'static str {
"Ensure G_DECLARE_* and G_DEFINE_* macros are used consistently"
}
fn category(&self) -> crate::rules::Category {
crate::rules::Category::Pedantic
}
fn min_glib_version(&self) -> Option<(u32, u32)> {
Some((2, 70))
}
fn check_all(
&self,
ast_context: &AstContext,
_config: &Config,
violations: &mut Vec<Violation>,
) {
let mut declared_types: HashMap<&str, &GObjectTypeKind> = HashMap::new();
for (_path, file) in ast_context.iter_all_files() {
for gt in file.iter_all_gobject_types() {
if gt.kind.is_declare() {
declared_types.insert(>.type_name, >.kind);
}
}
}
for (path, file) in ast_context.iter_c_files() {
for gt in file.iter_all_gobject_types() {
if gt.kind.is_define() {
if let Some(declare_kind) = declared_types.get(gt.type_name.as_str())
&& !declare_kind.is_compatible_with(>.kind)
{
violations.push(self.violation(
path,
gt.location.line,
1,
format!(
"'{}' is declared with {} but defined with {}",
gt.type_name,
declare_kind.macro_name(),
gt.kind.macro_name()
),
));
}
}
}
}
}
}