Skip to main content

ktrs_compose/rules/
mutable_state_parameter.rs

1//! Port of `rules/MutableStateParameter.kt`.
2
3use std::sync::LazyLock;
4
5use ktrs_ast::Ast;
6use ktrs_ast::psi::KtFunction;
7use ktrs_lint::rules::internal::KotlinRegex;
8
9use crate::core::compose_kt_config::ComposeKtConfig;
10use crate::core::compose_kt_visitor::ComposeKtVisitor;
11use crate::core::emitter::Emitter;
12
13pub struct MutableStateParameter;
14
15impl ComposeKtVisitor for MutableStateParameter {
16    fn visit_composable(&self, ast: &mut Ast, function: KtFunction, emitter: &mut dyn Emitter, _config: &dyn ComposeKtConfig) {
17        let parameters: Vec<_> = function
18            .value_parameters(ast)
19            .into_iter()
20            .filter(|it| it.type_reference(ast).is_some_and(|t| MUTABLE_STATE_REGEX.matches(&t.text(ast))))
21            .collect();
22        for parameter in parameters {
23            emitter.report(ast, parameter.node(), MUTABLE_STATE_PARAMETER_IN_COMPOSE, false);
24        }
25    }
26}
27
28static MUTABLE_STATE_REGEX: LazyLock<KotlinRegex> = LazyLock::new(|| {
29    KotlinRegex::new(concat!(
30        "(MutableState<.*>|",
31        "Mutable(Int|Float|Double|Long)State|",
32        "MutableIntList|MutableLongList|MutableFloatList|",
33        "MutableIntSet|MutableLongSet|MutableFloatSet|",
34        "MutableIntIntMap|MutableIntLongMap|MutableIntFloatMap|",
35        "MutableLongIntMap|MutableLongLongMap|MutableLongFloatMap|",
36        "MutableFloatIntMap|MutableFloatLongMap|MutableFloatFloatMap)\\??",
37    ))
38});
39
40pub const MUTABLE_STATE_PARAMETER_IN_COMPOSE: &str = "\
41MutableState shouldn't be used as a parameter in a @Composable function, as it promotes joint ownership over a state between a component and its user.
42If possible, consider making the component stateless and concede the state change to the caller. If mutation of the parent’s owned property is required in the component, consider creating a ComponentState class with the domain specific meaningful field that is backed by mutableStateOf().
43See https://mrmans0n.github.io/compose-rules/rules/#do-not-use-mutablestate-as-a-parameter for more information.";