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

davidcole1340 / ext-php-rs / 16719383449

04 Aug 2025 09:30AM UTC coverage: 27.104% (-0.04%) from 27.144%
16719383449

Pull #542

github

web-flow
Merge 51bb4ade4 into 34caede39
Pull Request #542: feat: Add constructor visability

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

86 existing lines in 4 files now uncovered.

1127 of 4158 relevant lines covered (27.1%)

5.66 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 },
×
NEW
41
        }.to_tokens(tokens);
×
42
    }
43
}
44

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

325
    #[test]
326
    fn rename() {
327
        let &(original, camel, snake, pascal, screaming_snake) =
328
            &("get_name", "getName", "get_name", "GetName", "GET_NAME");
329
        assert_eq!(original, original.rename(RenameRule::None));
330
        assert_eq!(camel, original.rename(RenameRule::Camel));
331
        assert_eq!(pascal, original.rename(RenameRule::Pascal));
332
        assert_eq!(snake, original.rename(RenameRule::Snake));
333
        assert_eq!(screaming_snake, original.rename(RenameRule::ScreamingSnake));
334
    }
335
}
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