gobject-linter 0.1.2

A fast tree-sitter-based linter for GObject/C code
Documentation
use gobject_ast::model::{EnumInfo, FileModel};

use crate::{
    ast_context::AstContext,
    config::Config,
    rules::{Rule, Violation},
};

pub struct PropertyEnumCoverage;

impl Rule for PropertyEnumCoverage {
    fn name(&self) -> &'static str {
        "property_enum_coverage"
    }

    fn description(&self) -> &'static str {
        "Ensure all property enum values have corresponding g_param_spec or g_object_class_override_property"
    }

    fn category(&self) -> crate::rules::Category {
        crate::rules::Category::Correctness
    }

    fn check_enum(
        &self,
        _ast_context: &AstContext,
        _config: &Config,
        enum_info: &EnumInfo,
        file: &FileModel,
        violations: &mut Vec<Violation>,
    ) {
        if !enum_info.is_property_enum() {
            return;
        }

        let property_values: Vec<&str> = enum_info
            .values
            .iter()
            .filter(|v| !v.is_prop_0() && !v.is_prop_last())
            .map(|v| v.name.as_str())
            .collect();

        if property_values.is_empty() {
            return;
        }

        let Some(gobject_type) = file.find_gobject_type_for_property_enum(enum_info) else {
            return;
        };

        let installed_properties: Vec<_> = gobject_type
            .properties
            .iter()
            .filter_map(|assignment| assignment.get_installed_enum_value())
            .collect();

        for prop_name in property_values {
            if !installed_properties.iter().any(|p| p == &prop_name) {
                violations.push(self.violation(
                    &file.path,
                    enum_info.location.line,
                    1,
                    format!(
                        "Property enum value '{}' is declared but never installed in {}",
                        prop_name,
                        gobject_type.class_init_function_name()
                    ),
                ));
            }
        }
    }
}