ktrs_compose/rules/
modifier_missing.rs1use 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_annotated_with;
11use crate::core::util::kt_functions::{defined_in_interface, is_internal, is_override, returns_value};
12use crate::core::util::modifiers::{is_modifier_receiver, modifier_parameter};
13use crate::core::util::previews::is_preview;
14
15pub struct ModifierMissing;
16
17impl ComposeKtVisitor for ModifierMissing {
18 fn visit_composable(&self, ast: &mut Ast, function: KtFunction, emitter: &mut dyn Emitter, config: &dyn ComposeKtConfig) {
19 if returns_value(ast, function)
20 || is_override(ast, function)
21 || defined_in_interface(ast, function)
22 || is_preview(ast, function.node())
23 || is_modifier_receiver(ast, function.node(), config)
24 {
25 return;
26 }
27 if is_annotated_with(ast, function.node(), &config.get_set("modifierMissingIgnoreAnnotated", &[])) {
28 return;
29 }
30 let should_check = match config.get_string("checkModifiersForVisibility", Some("only_public")).as_deref() {
31 Some("public_and_internal") => function.is_public(ast) || is_internal(ast, function.node()),
32 Some("all") => true,
33 _ => function.is_public(ast),
34 };
35 if !should_check || modifier_parameter(ast, function, config).is_some() {
36 return;
37 }
38 if function_emits_content(ast, function, config) {
39 emitter.report(ast, function.node(), MISSING_MODIFIER_CONTENT_COMPOSABLE, false);
40 }
41 }
42}
43
44pub const MISSING_MODIFIER_CONTENT_COMPOSABLE: &str = "\
45This @Composable function emits content but doesn't have a modifier parameter.
46See https://mrmans0n.github.io/compose-rules/rules/#when-should-i-expose-modifier-parameters for more information.";