i_slint_compiler/generator/
accessor_names.rs1use smol_str::{SmolStr, format_smolstr};
14
15#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
17pub enum DeclarationKind {
18 Property,
19 Callback,
20 Function,
21}
22
23#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
25pub enum AccessorKind {
26 Getter,
28 Setter,
30 Invoker,
32 Handler,
34}
35
36impl AccessorKind {
37 pub const fn prefix(self) -> &'static str {
38 match self {
39 Self::Getter => "get_",
40 Self::Setter => "set_",
41 Self::Invoker => "invoke_",
42 Self::Handler => "on_",
43 }
44 }
45}
46
47impl DeclarationKind {
48 pub const fn accessor_kinds(self) -> &'static [AccessorKind] {
51 match self {
52 Self::Property => &[AccessorKind::Getter, AccessorKind::Setter],
53 Self::Callback => &[AccessorKind::Invoker, AccessorKind::Handler],
54 Self::Function => &[AccessorKind::Invoker],
55 }
56 }
57}
58
59pub fn rust_accessor_name(name: &str, accessor: AccessorKind) -> SmolStr {
66 format_accessor_name(name, accessor)
67}
68
69pub fn cpp_accessor_name(name: &str, accessor: AccessorKind) -> SmolStr {
76 format_accessor_name(name, accessor)
77}
78
79fn format_accessor_name(name: &str, accessor: AccessorKind) -> SmolStr {
80 let prefix = accessor.prefix();
81 if name.contains('-') {
82 let snake = name.replace('-', "_");
83 format_smolstr!("{prefix}{snake}")
84 } else {
85 format_smolstr!("{prefix}{name}")
86 }
87}
88
89#[cfg(any(feature = "rust", feature = "slint-sc"))]
92pub fn rust_accessor_ident(name: &str, accessor: AccessorKind) -> proc_macro2::Ident {
93 quote::format_ident!("{}", rust_accessor_name(name, accessor).as_str())
94}
95
96#[cfg(test)]
97mod tests {
98 use super::*;
99
100 #[test]
101 fn accessor_name_mapping() {
102 const CASES: &[(&str, AccessorKind, &str)] = &[
108 ("foo", AccessorKind::Getter, "get_foo"),
110 ("foo", AccessorKind::Setter, "set_foo"),
111 ("clicked", AccessorKind::Invoker, "invoke_clicked"),
112 ("clicked", AccessorKind::Handler, "on_clicked"),
113 ("foo_bar", AccessorKind::Getter, "get_foo_bar"),
114 ("foo-bar", AccessorKind::Getter, "get_foo_bar"),
116 ("multi-word-name", AccessorKind::Setter, "set_multi_word_name"),
117 ("do-it", AccessorKind::Invoker, "invoke_do_it"),
118 ("type", AccessorKind::Getter, "get_type"),
121 ("if", AccessorKind::Handler, "on_if"),
122 ("class", AccessorKind::Getter, "get_class"),
123 ("delete", AccessorKind::Invoker, "invoke_delete"),
124 ];
125 for &(name, kind, expected) in CASES {
126 assert_eq!(rust_accessor_name(name, kind), expected, "rust: ({name:?}, {kind:?})");
127 assert_eq!(cpp_accessor_name(name, kind), expected, "cpp: ({name:?}, {kind:?})");
128 }
129 }
130
131 #[test]
132 fn kebab_and_snake_collapse_to_same_accessor() {
133 assert_eq!(
136 rust_accessor_name("foo-bar", AccessorKind::Getter),
137 rust_accessor_name("foo_bar", AccessorKind::Getter),
138 );
139 }
140
141 #[test]
142 fn declaration_kind_accessor_sets() {
143 const CASES: &[(DeclarationKind, &[AccessorKind])] = &[
144 (DeclarationKind::Property, &[AccessorKind::Getter, AccessorKind::Setter]),
145 (DeclarationKind::Callback, &[AccessorKind::Invoker, AccessorKind::Handler]),
146 (DeclarationKind::Function, &[AccessorKind::Invoker]),
147 ];
148 for &(kind, expected) in CASES {
149 assert_eq!(kind.accessor_kinds(), expected, "{kind:?}");
150 }
151 }
152}