gobject_linter/rules/
missing_implementation.rs1use std::collections::HashSet;
2
3use crate::{ast_context::AstContext, config::Config, rules::Rule};
4
5pub 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 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}