Skip to main content

sniff/
roles_surface_contract.rs

1use crate::roles::normalize_path;
2use crate::types::FileRecord;
3
4fn looks_like_callback_contract_source(source: &str) -> bool {
5    let lowered = source.to_lowercase();
6    if !lowered.contains("data class") {
7        return false;
8    }
9    if lowered.contains("@composable") || lowered.contains("\nfun ") {
10        return false;
11    }
12
13    let callback_properties = source.matches("-> Unit").count()
14        + source.matches("-> () -> Unit").count()
15        + source.matches("= {}").count()
16        + source.matches("= { _ -> }").count();
17
18    callback_properties >= 3
19}
20
21pub fn is_callback_contract_module(file: &FileRecord) -> bool {
22    let normalized = normalize_path(&file.file_path);
23    let name = crate::roles::file_name(&normalized).to_lowercase();
24
25    let looks_like_kotlin = normalized.ends_with(".kt") || normalized.ends_with(".kts");
26    if !looks_like_kotlin {
27        return false;
28    }
29
30    let name_hint = name.ends_with("callbacks.kt")
31        || name.ends_with("callbacks.kts")
32        || name.ends_with("models.kt")
33        || name.ends_with("bindings.kt");
34
35    name_hint && looks_like_callback_contract_source(&file.source)
36        || looks_like_callback_contract_source(&file.source)
37}