• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

davidcole1340 / ext-php-rs / 16824767628

08 Aug 2025 07:35AM UTC coverage: 27.748% (-0.03%) from 27.778%
16824767628

Pull #542

github

web-flow
Merge 44b890823 into 896cb945d
Pull Request #542: feat: Add constructor visability

5 of 21 new or added lines in 4 files covered. (23.81%)

1 existing line in 1 file now uncovered.

1156 of 4166 relevant lines covered (27.75%)

7.7 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

75.0
/crates/macros/src/parsing.rs
1
use convert_case::{Case, Casing};
2
use darling::FromMeta;
3
use quote::{quote, ToTokens};
4

5
const MAGIC_METHOD: [&str; 17] = [
6
    "__construct",
7
    "__destruct",
8
    "__call",
9
    "__call_static",
10
    "__get",
11
    "__set",
12
    "__isset",
13
    "__unset",
14
    "__sleep",
15
    "__wakeup",
16
    "__serialize",
17
    "__unserialize",
18
    "__to_string",
19
    "__invoke",
20
    "__set_state",
21
    "__clone",
22
    "__debug_info",
23
];
24

25
#[derive(Debug, FromMeta)]
26
pub enum Visibility {
27
    #[darling(rename = "public")]
28
    Public,
29
    #[darling(rename = "private")]
30
    Private,
31
    #[darling(rename = "protected")]
32
    Protected,
33
}
34

35
impl ToTokens for Visibility {
NEW
36
    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
×
NEW
37
        match self {
×
NEW
38
            Visibility::Public => quote! { ::ext_php_rs::flags::MethodFlags::Public },
×
NEW
39
            Visibility::Protected => quote! { ::ext_php_rs::flags::MethodFlags::Protected },
×
NEW
40
            Visibility::Private => quote! { ::ext_php_rs::flags::MethodFlags::Private },
×
41
        }
NEW
42
        .to_tokens(tokens);
×
43
    }
44
}
45

46
pub trait Rename {
47
    fn rename(&self, rule: RenameRule) -> String;
48
}
49

50
pub trait MethodRename: Rename {
51
    fn rename_method(&self, rule: RenameRule) -> String;
52
}
53

54
#[derive(FromMeta, Debug, Default)]
55
#[darling(default)]
56
pub struct PhpRename {
57
    name: Option<String>,
58
    change_case: Option<RenameRule>,
59
}
60

61
impl PhpRename {
62
    pub fn rename(&self, name: impl AsRef<str>, default: RenameRule) -> String {
23✔
63
        if let Some(name) = self.name.as_ref() {
31✔
64
            name.to_string()
×
65
        } else {
66
            name.as_ref().rename(self.change_case.unwrap_or(default))
75✔
67
        }
68
    }
69

70
    pub fn rename_method(&self, name: impl AsRef<str>, default: RenameRule) -> String {
97✔
71
        if let Some(name) = self.name.as_ref() {
103✔
72
            name.to_string()
×
73
        } else {
74
            name.as_ref()
91✔
75
                .rename_method(self.change_case.unwrap_or(default))
364✔
76
        }
77
    }
78
}
79

80
#[derive(Debug, Copy, Clone, FromMeta, Default)]
81
pub enum RenameRule {
82
    /// Methods won't be renamed.
83
    #[darling(rename = "none")]
84
    None,
85
    /// Methods will be converted to `camelCase`.
86
    #[darling(rename = "camelCase")]
87
    #[default]
88
    Camel,
89
    /// Methods will be converted to `snake_case`.
90
    #[darling(rename = "snake_case")]
91
    Snake,
92
    /// Methods will be converted to `PascalCase`.
93
    #[darling(rename = "PascalCase")]
94
    Pascal,
95
    /// Renames to `UPPER_SNAKE_CASE`.
96
    #[darling(rename = "UPPER_CASE")]
97
    ScreamingSnake,
98
}
99

100
impl RenameRule {
101
    fn rename(self, value: impl AsRef<str>) -> String {
30✔
102
        match self {
30✔
103
            Self::None => value.as_ref().to_string(),
1✔
104
            Self::Camel => value.as_ref().to_case(Case::Camel),
6✔
105
            Self::Pascal => value.as_ref().to_case(Case::Pascal),
24✔
106
            Self::Snake => value.as_ref().to_case(Case::Snake),
24✔
107
            Self::ScreamingSnake => value.as_ref().to_case(Case::Constant),
33✔
108
        }
109
    }
110
}
111

112
impl<T> Rename for T
113
where
114
    T: ToString,
115
{
116
    fn rename(&self, rule: RenameRule) -> String {
30✔
117
        rule.rename(self.to_string())
120✔
118
    }
119
}
120

121
impl<T> MethodRename for T
122
where
123
    T: ToString + Rename,
124
{
125
    fn rename_method(&self, rule: RenameRule) -> String {
181✔
126
        let original = self.to_string();
543✔
127
        match rule {
181✔
128
            RenameRule::None => original,
35✔
129
            _ => {
×
130
                if MAGIC_METHOD.contains(&original.as_str()) {
438✔
131
                    match original.as_str() {
136✔
132
                        "__to_string" => "__toString".to_string(),
152✔
133
                        "__debug_info" => "__debugInfo".to_string(),
144✔
134
                        "__call_static" => "__callStatic".to_string(),
136✔
135
                        _ => original,
112✔
136
                    }
137
                } else {
138
                    self.rename(rule)
10✔
139
                }
140
            }
141
        }
142
    }
143
}
144

145
#[cfg(test)]
146
mod tests {
147
    use crate::parsing::{MethodRename, Rename};
148

149
    use super::{PhpRename, RenameRule};
150

151
    #[test]
152
    fn php_rename() {
153
        let rename = PhpRename {
154
            name: Some("test".to_string()),
155
            change_case: None,
156
        };
157
        assert_eq!(rename.rename("testCase", RenameRule::Snake), "test");
158
        assert_eq!(rename.rename("TestCase", RenameRule::Snake), "test");
159
        assert_eq!(rename.rename("TEST_CASE", RenameRule::Snake), "test");
160

161
        let rename = PhpRename {
162
            name: None,
163
            change_case: Some(RenameRule::ScreamingSnake),
164
        };
165
        assert_eq!(rename.rename("testCase", RenameRule::Snake), "TEST_CASE");
166
        assert_eq!(rename.rename("TestCase", RenameRule::Snake), "TEST_CASE");
167
        assert_eq!(rename.rename("TEST_CASE", RenameRule::Snake), "TEST_CASE");
168

169
        let rename = PhpRename {
170
            name: Some("test".to_string()),
171
            change_case: Some(RenameRule::ScreamingSnake),
172
        };
173
        assert_eq!(rename.rename("testCase", RenameRule::Snake), "test");
174
        assert_eq!(rename.rename("TestCase", RenameRule::Snake), "test");
175
        assert_eq!(rename.rename("TEST_CASE", RenameRule::Snake), "test");
176

177
        let rename = PhpRename {
178
            name: None,
179
            change_case: None,
180
        };
181
        assert_eq!(rename.rename("testCase", RenameRule::Snake), "test_case");
182
        assert_eq!(rename.rename("TestCase", RenameRule::Snake), "test_case");
183
        assert_eq!(rename.rename("TEST_CASE", RenameRule::Snake), "test_case");
184
    }
185

186
    #[test]
187
    fn php_rename_method() {
188
        let rename = PhpRename {
189
            name: Some("test".to_string()),
190
            change_case: None,
191
        };
192
        assert_eq!(rename.rename_method("testCase", RenameRule::Snake), "test");
193
        assert_eq!(rename.rename_method("TestCase", RenameRule::Snake), "test");
194
        assert_eq!(rename.rename_method("TEST_CASE", RenameRule::Snake), "test");
195

196
        let rename = PhpRename {
197
            name: None,
198
            change_case: Some(RenameRule::ScreamingSnake),
199
        };
200
        assert_eq!(
201
            rename.rename_method("testCase", RenameRule::Snake),
202
            "TEST_CASE"
203
        );
204
        assert_eq!(
205
            rename.rename_method("TestCase", RenameRule::Snake),
206
            "TEST_CASE"
207
        );
208
        assert_eq!(
209
            rename.rename_method("TEST_CASE", RenameRule::Snake),
210
            "TEST_CASE"
211
        );
212

213
        let rename = PhpRename {
214
            name: Some("test".to_string()),
215
            change_case: Some(RenameRule::ScreamingSnake),
216
        };
217
        assert_eq!(rename.rename_method("testCase", RenameRule::Snake), "test");
218
        assert_eq!(rename.rename_method("TestCase", RenameRule::Snake), "test");
219
        assert_eq!(rename.rename_method("TEST_CASE", RenameRule::Snake), "test");
220

221
        let rename = PhpRename {
222
            name: None,
223
            change_case: None,
224
        };
225
        assert_eq!(
226
            rename.rename_method("testCase", RenameRule::Snake),
227
            "test_case"
228
        );
229
        assert_eq!(
230
            rename.rename_method("TestCase", RenameRule::Snake),
231
            "test_case"
232
        );
233
        assert_eq!(
234
            rename.rename_method("TEST_CASE", RenameRule::Snake),
235
            "test_case"
236
        );
237
    }
238

239
    #[test]
240
    fn rename_magic_method() {
241
        for &(magic, expected) in &[
242
            ("__construct", "__construct"),
243
            ("__destruct", "__destruct"),
244
            ("__call", "__call"),
245
            ("__call_static", "__callStatic"),
246
            ("__get", "__get"),
247
            ("__set", "__set"),
248
            ("__isset", "__isset"),
249
            ("__unset", "__unset"),
250
            ("__sleep", "__sleep"),
251
            ("__wakeup", "__wakeup"),
252
            ("__serialize", "__serialize"),
253
            ("__unserialize", "__unserialize"),
254
            ("__to_string", "__toString"),
255
            ("__invoke", "__invoke"),
256
            ("__set_state", "__set_state"),
257
            ("__clone", "__clone"),
258
            ("__debug_info", "__debugInfo"),
259
        ] {
260
            assert_eq!(magic, magic.rename_method(RenameRule::None));
261
            assert_eq!(
262
                magic,
263
                PhpRename {
264
                    name: None,
265
                    change_case: Some(RenameRule::None)
266
                }
267
                .rename_method(magic, RenameRule::ScreamingSnake)
268
            );
269

270
            assert_eq!(expected, magic.rename_method(RenameRule::Camel));
271
            assert_eq!(
272
                expected,
273
                PhpRename {
274
                    name: None,
275
                    change_case: Some(RenameRule::Camel)
276
                }
277
                .rename_method(magic, RenameRule::ScreamingSnake)
278
            );
279

280
            assert_eq!(expected, magic.rename_method(RenameRule::Pascal));
281
            assert_eq!(
282
                expected,
283
                PhpRename {
284
                    name: None,
285
                    change_case: Some(RenameRule::Pascal)
286
                }
287
                .rename_method(magic, RenameRule::ScreamingSnake)
288
            );
289

290
            assert_eq!(expected, magic.rename_method(RenameRule::Snake));
291
            assert_eq!(
292
                expected,
293
                PhpRename {
294
                    name: None,
295
                    change_case: Some(RenameRule::Snake)
296
                }
297
                .rename_method(magic, RenameRule::ScreamingSnake)
298
            );
299

300
            assert_eq!(expected, magic.rename_method(RenameRule::ScreamingSnake));
301
            assert_eq!(
302
                expected,
303
                PhpRename {
304
                    name: None,
305
                    change_case: Some(RenameRule::ScreamingSnake)
306
                }
307
                .rename_method(magic, RenameRule::Camel)
308
            );
309
        }
310
    }
311

312
    #[test]
313
    fn rename_method() {
314
        let &(original, camel, snake, pascal, screaming_snake) =
315
            &("get_name", "getName", "get_name", "GetName", "GET_NAME");
316
        assert_eq!(original, original.rename_method(RenameRule::None));
317
        assert_eq!(camel, original.rename_method(RenameRule::Camel));
318
        assert_eq!(pascal, original.rename_method(RenameRule::Pascal));
319
        assert_eq!(snake, original.rename_method(RenameRule::Snake));
320
        assert_eq!(
321
            screaming_snake,
322
            original.rename_method(RenameRule::ScreamingSnake)
323
        );
324
    }
325

326
    #[test]
327
    fn rename() {
328
        let &(original, camel, snake, pascal, screaming_snake) =
329
            &("get_name", "getName", "get_name", "GetName", "GET_NAME");
330
        assert_eq!(original, original.rename(RenameRule::None));
331
        assert_eq!(camel, original.rename(RenameRule::Camel));
332
        assert_eq!(pascal, original.rename(RenameRule::Pascal));
333
        assert_eq!(snake, original.rename(RenameRule::Snake));
334
        assert_eq!(screaming_snake, original.rename(RenameRule::ScreamingSnake));
335
    }
336
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc