cxx_qt_gen/generator/naming/
property.rs1use crate::{
6 naming::Name,
7 parser::property::{FlagState, ParsedQProperty},
8};
9use quote::format_ident;
10use syn::Result;
11
12use crate::generator::structuring::StructuredQObject;
13use core::ops::Deref;
14
15#[derive(Debug)]
16pub enum NameState {
17 Auto(Name),
18 Custom(Name),
19}
20
21impl Deref for NameState {
22 type Target = Name;
23
24 fn deref(&self) -> &Self::Target {
25 match self {
26 Self::Auto(name) => name,
27 Self::Custom(name) => name,
28 }
29 }
30}
31
32impl NameState {
33 pub fn from_flag_with_auto_fn(
34 state: &FlagState,
35 auto_fn: impl Fn() -> Name,
36 structured_qobject: &StructuredQObject,
37 signal: bool,
38 ) -> Result<Self> {
39 let lookup_fn = if signal {
40 StructuredQObject::signal_lookup
41 } else {
42 StructuredQObject::method_lookup
43 };
44 Ok(match state {
45 FlagState::Auto => Self::Auto(auto_fn()),
46 FlagState::Custom(ident) => Self::Custom(lookup_fn(structured_qobject, ident)?),
47 })
48 }
49}
50
51pub struct QPropertyNames {
53 pub name: Name,
54 pub getter: NameState,
55 pub setter: Option<NameState>,
56 pub notify: Option<NameState>,
57 pub reset: Option<Name>,
58}
59
60impl QPropertyNames {
61 pub(crate) fn try_from_property(
62 property: &ParsedQProperty,
63 structured_qobject: &StructuredQObject,
64 ) -> Result<Self> {
65 let property_name = &property.name;
66
67 let flags = &property.flags;
69
70 let getter = NameState::from_flag_with_auto_fn(
71 &flags.read,
72 || getter_name_from_property(property_name),
73 structured_qobject,
74 false,
75 )?;
76
77 let setter = flags
78 .write
79 .clone()
80 .map(|setter| {
81 NameState::from_flag_with_auto_fn(
82 &setter,
83 || setter_name_from_property(property_name),
84 structured_qobject,
85 false,
86 )
87 })
88 .transpose()?;
89
90 let notify = flags
91 .notify
92 .clone()
93 .map(|notify| {
94 NameState::from_flag_with_auto_fn(
95 ¬ify,
96 || notify_name_from_property(property_name),
97 structured_qobject,
98 true,
99 )
100 })
101 .transpose()?;
102
103 let reset = flags
104 .reset
105 .as_ref()
106 .map(|ident| structured_qobject.method_lookup(ident))
107 .transpose()?;
108
109 Ok(Self {
110 getter,
111 setter,
112 notify,
113 reset,
114 name: property_name.clone(),
115 })
116 }
117}
118
119fn capitalise_first(str: String) -> String {
120 let mut out = "".to_string();
121 if let Some(first) = str.chars().next() {
122 out.push(first.to_ascii_uppercase());
123 out.push_str(&str[1..]);
124 }
125 out
126}
127
128fn getter_name_from_property(name: &Name) -> Name {
130 name.clone()
131 .with_cxx_name(format!("get{}", capitalise_first(name.cxx_unqualified())))
132}
133
134fn setter_name_from_property(name: &Name) -> Name {
136 name.clone()
137 .with_rust_name(format_ident!("set_{}", name.rust_unqualified()))
138 .with_cxx_name(format!("set{}", capitalise_first(name.cxx_unqualified())))
139}
140
141fn notify_name_from_property(name: &Name) -> Name {
143 name.clone()
144 .with_rust_name(format_ident!("{}_changed", name.rust_unqualified()))
145 .with_cxx_name(format!("{}Changed", name.cxx_unqualified()))
146}
147
148#[cfg(test)]
149pub mod tests {
150 use syn::parse_quote;
151
152 use super::*;
153 use crate::parser::property::QPropertyFlags;
154 use crate::parser::qobject::ParsedQObject;
155
156 pub fn create_i32_qpropertyname() -> QPropertyNames {
157 let property = ParsedQProperty {
158 name: Name::mock_name_with_cxx("my_property", "myProperty"),
159 ty: parse_quote! { i32 },
160 flags: QPropertyFlags::default(),
161 };
162
163 let obj = ParsedQObject::mock();
164
165 let structured_qobject = StructuredQObject::mock(&obj);
166 QPropertyNames::try_from_property(&property, &structured_qobject)
167 .expect("Failed to create QPropertyNames")
168 }
169
170 #[test]
171 fn test_parsed_property() {
172 let names = create_i32_qpropertyname();
173 assert_eq!(names.name.cxx_unqualified(), "myProperty");
174 assert_eq!(names.name.rust_unqualified(), "my_property");
175 assert_eq!(names.getter.cxx_unqualified(), "getMyProperty");
176 assert_eq!(names.getter.rust_unqualified(), "my_property");
177 assert_eq!(
178 names.setter.as_ref().unwrap().cxx_unqualified(),
179 "setMyProperty"
180 );
181 assert_eq!(
182 names.setter.as_ref().unwrap().rust_unqualified(),
183 "set_my_property"
184 );
185 assert_eq!(
186 names.notify.as_ref().unwrap().cxx_unqualified(),
187 "myPropertyChanged"
188 );
189 assert_eq!(
190 names.notify.as_ref().unwrap().rust_unqualified(),
191 "my_property_changed"
192 );
193 }
194
195 #[test]
196 fn test_capitalise_first() {
197 assert_eq!(capitalise_first("abc".to_owned()), "Abc".to_owned());
198 assert_eq!(capitalise_first("".to_string()), "".to_owned());
199 assert_eq!(capitalise_first("a".to_owned()), "A".to_owned());
200 }
201}