Skip to main content

gobject_linter/rules/
missing_implementation.rs

1use std::collections::HashSet;
2
3use crate::{ast_context::AstContext, config::Config, rules::Rule};
4
5/// Rule that checks for functions declared in headers but never implemented
6pub struct MissingImplementation;
7
8impl Rule for MissingImplementation {
9    fn name(&self) -> &'static str {
10        "missing_implementation"
11    }
12
13    fn description(&self) -> &'static str {
14        "Report functions declared in headers but not implemented"
15    }
16
17    fn category(&self) -> crate::rules::Category {
18        crate::rules::Category::Suspicious
19    }
20
21    fn check_all(
22        &self,
23        ast_context: &AstContext,
24        _config: &Config,
25        violations: &mut Vec<crate::rules::Violation>,
26    ) {
27        let mut defined: HashSet<String> = HashSet::new();
28        for (_, file) in ast_context.iter_all_files() {
29            for f in file.iter_function_definitions() {
30                defined.insert(f.name.clone());
31            }
32            for gt in file.iter_all_gobject_types() {
33                defined.insert(format!("{}_get_type", gt.function_prefix));
34            }
35            // #define g_foo_get_type _g_foo_get_type
36            for (name, value) in file.iter_defines() {
37                if let Some(value) = value {
38                    let raw = value.as_raw_str();
39                    if raw.starts_with('_') && &raw[1..] == name {
40                        defined.insert(raw.to_owned());
41                    }
42                }
43            }
44        }
45
46        for (path, file) in ast_context.iter_header_files() {
47            for func in file.iter_function_declarations() {
48                if func.is_static || func.name.ends_with("_quark") {
49                    continue;
50                }
51                if defined.contains(func.name.as_str()) {
52                    continue;
53                }
54                violations.push(self.violation(
55                    path,
56                    func.location.line,
57                    1,
58                    format!(
59                        "Function '{}' is declared in a header but has no implementation",
60                        func.name
61                    ),
62                ));
63            }
64        }
65    }
66}