Skip to main content

gobject_linter/rules/
use_g_value_set_static_string.rs

1use gobject_ast::model::{CallExpression, Expression, FileModel, FunctionDefItem};
2
3use crate::{
4    ast_context::AstContext,
5    config::Config,
6    rules::{Fix, Rule, Violation},
7};
8
9pub struct UseGValueSetStaticString;
10
11impl Rule for UseGValueSetStaticString {
12    fn name(&self) -> &'static str {
13        "use_g_value_set_static_string"
14    }
15
16    fn description(&self) -> &'static str {
17        "Use g_value_set_static_string for string literals instead of g_value_set_string"
18    }
19
20    fn category(&self) -> crate::rules::Category {
21        crate::rules::Category::Perf
22    }
23
24    fn fixable(&self) -> bool {
25        true
26    }
27
28    fn check_func_impl(
29        &self,
30        _ast_context: &AstContext,
31        config: &Config,
32        func: &FunctionDefItem,
33        file: &FileModel,
34        violations: &mut Vec<Violation>,
35    ) {
36        for call in func.find_calls(&["g_value_set_string"]) {
37            self.check_call(file, call, config, violations);
38        }
39    }
40}
41
42impl UseGValueSetStaticString {
43    fn check_call(
44        &self,
45        file: &FileModel,
46        call: &CallExpression,
47        config: &Config,
48        violations: &mut Vec<Violation>,
49    ) {
50        // Need at least 2 arguments
51        if call.arguments.len() < 2 {
52            return;
53        }
54
55        // Check if second argument is a string literal
56        let Some(second_expr) = call.get_arg(1) else {
57            return;
58        };
59        if !second_expr.is_string_literal() {
60            return;
61        }
62
63        // Get the string literal for the message
64        let Expression::StringLiteral(string_lit) = second_expr else {
65            unreachable!();
66        };
67
68        // Build the fix - replace just the function name
69        let args: Vec<&str> = call
70            .arguments
71            .iter()
72            .filter_map(|arg| arg.location().as_str())
73            .collect();
74        let replacement = config.style.format_call("g_value_set_static_string", &args);
75
76        let fix = Fix::new(
77            call.location.start_byte,
78            call.location.end_byte,
79            replacement,
80        );
81
82        violations.push(self.violation_with_fix_at(
83            &file.path,
84            &call.location,
85            format!(
86                "Use g_value_set_static_string instead of g_value_set_string for string literal {}",
87                string_lit.value
88            ),
89            fix,
90        ));
91    }
92}