Skip to main content

ktrs_compose/rules/
lambda_parameter_event_trailing.rs

1//! Port of `rules/LambdaParameterEventTrailing.kt`.
2
3use ktrs_ast::Ast;
4use ktrs_ast::psi::KtFunction;
5
6use crate::core::compose_kt_config::ComposeKtConfig;
7use crate::core::compose_kt_visitor::ComposeKtVisitor;
8use crate::core::emitter::Emitter;
9use crate::core::util::composables::function_emits_content;
10use crate::core::util::kt_annotateds::is_composable;
11use crate::core::util::lambdas::is_lambda;
12use crate::core::util::modifiers::modifier_parameter;
13
14pub struct LambdaParameterEventTrailing;
15
16impl ComposeKtVisitor for LambdaParameterEventTrailing {
17    fn visit_composable(&self, ast: &mut Ast, function: KtFunction, emitter: &mut dyn Emitter, config: &dyn ComposeKtConfig) {
18        if !function_emits_content(ast, function, config) {
19            return;
20        }
21        if modifier_parameter(ast, function, config).is_none() {
22            return;
23        }
24        let Some(trailing_param) = function.value_parameters(ast).last().copied() else { return };
25        let Some(type_reference) = trailing_param.type_reference(ast) else { return };
26        if !is_lambda(ast, type_reference, &[]) {
27            return;
28        }
29        if is_composable(ast, type_reference.node()) {
30            return;
31        }
32        if trailing_param.has_default_value(ast) {
33            return;
34        }
35        let Some(name) = trailing_param.name(ast) else { return };
36        if !name.starts_with("on") {
37            return;
38        }
39        emitter.report(ast, trailing_param.node(), EVENT_LAMBDA_IS_TRAILING_LAMBDA, false);
40    }
41}
42
43pub const EVENT_LAMBDA_IS_TRAILING_LAMBDA: &str = "\
44Lambda parameters in a @Composable that are for events (e.g. onClick, onChange, etc) and are required (they don't have a default value) should not be used as the trailing parameter.
45Composable functions that emit content usually reserve the trailing lambda syntax for the content slot, and that can lead to an assumption that other composables can be used in that lambda.
46See https://mrmans0n.github.io/compose-rules/rules/#avoid-using-the-trailing-lambda-for-event-lambdas-in-ui-composables for more information.";