gobject_linter/rules/
matching_declare_define.rs1use std::collections::HashMap;
2
3use gobject_ast::model::GObjectTypeKind;
4
5use crate::{
6 ast_context::AstContext,
7 config::Config,
8 rules::{Rule, Violation},
9};
10
11pub struct MatchingDeclareDefine;
12
13impl Rule for MatchingDeclareDefine {
14 fn name(&self) -> &'static str {
15 "matching_declare_define"
16 }
17
18 fn description(&self) -> &'static str {
19 "Ensure G_DECLARE_* and G_DEFINE_* macros are used consistently"
20 }
21
22 fn category(&self) -> crate::rules::Category {
23 crate::rules::Category::Pedantic
24 }
25
26 fn min_glib_version(&self) -> Option<(u32, u32)> {
27 Some((2, 70))
28 }
29
30 fn check_all(
31 &self,
32 ast_context: &AstContext,
33 _config: &Config,
34 violations: &mut Vec<Violation>,
35 ) {
36 let mut declared_types: HashMap<&str, &GObjectTypeKind> = HashMap::new();
38
39 for (_path, file) in ast_context.iter_all_files() {
41 for gt in file.iter_all_gobject_types() {
42 if gt.kind.is_declare() {
43 declared_types.insert(>.type_name, >.kind);
44 }
45 }
46 }
47
48 for (path, file) in ast_context.iter_c_files() {
50 for gt in file.iter_all_gobject_types() {
51 if gt.kind.is_define() {
52 if let Some(declare_kind) = declared_types.get(gt.type_name.as_str())
54 && !declare_kind.is_compatible_with(>.kind)
55 {
56 violations.push(self.violation(
57 path,
58 gt.location.line,
59 1,
60 format!(
61 "'{}' is declared with {} but defined with {}",
62 gt.type_name,
63 declare_kind.macro_name(),
64 gt.kind.macro_name()
65 ),
66 ));
67 }
68 }
69 }
70 }
71 }
72}