ktrs_compose/rules/
state_parameter.rs1use 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 StateParameter;
14
15impl ComposeKtVisitor for StateParameter {
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| STATE_REGEX.matches(&t.text(ast))))
21 .collect();
22 for parameter in parameters {
23 emitter.report(ast, parameter.node(), STATE_PARAMETER_IN_COMPOSE, false);
24 }
25 }
26}
27
28static STATE_REGEX: LazyLock<KotlinRegex> = LazyLock::new(|| KotlinRegex::new("(State<.*>|(Int|Float|Double|Long)State)\\??"));
29
30pub const STATE_PARAMETER_IN_COMPOSE: &str = "\
31State shouldn't be used as a parameter in a @Composable function, as it encourages components that are not fully stateless.
32Instead, pass the snapshot state value and provide event callbacks for changes.
33See https://github.com/androidx/androidx/blob/androidx-main/compose/docs/compose-component-api-guidelines.md#statet-as-a-parameter for more information.";