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

davidcole1340 / ext-php-rs / 16006197694

01 Jul 2025 05:33PM UTC coverage: 21.654% (-0.3%) from 21.978%
16006197694

Pull #471

github

web-flow
Merge 7af465c1e into 68e218f9b
Pull Request #471: feat(sapi): expand `SapiBuilder`

66 of 69 new or added lines in 1 file covered. (95.65%)

748 existing lines in 21 files now uncovered.

830 of 3833 relevant lines covered (21.65%)

3.63 hits per line

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

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

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

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

34
pub trait Rename {
35
    fn rename(&self, rule: RenameRule) -> String;
36
}
37

38
pub trait MethodRename: Rename {
39
    fn rename_method(&self, rule: RenameRule) -> String;
40
}
41

42
#[derive(FromMeta, Debug, Default)]
43
#[darling(default)]
44
pub struct PhpRename {
45
    name: Option<String>,
46
    change_case: Option<RenameRule>,
47
}
48

49
impl PhpRename {
50
    pub fn rename(&self, name: impl AsRef<str>, default: RenameRule) -> String {
12✔
51
        if let Some(name) = self.name.as_ref() {
18✔
52
            name.to_string()
×
53
        } else {
54
            name.as_ref().rename(self.change_case.unwrap_or(default))
30✔
55
        }
56
    }
57

58
    pub fn rename_method(&self, name: impl AsRef<str>, default: RenameRule) -> String {
97✔
59
        if let Some(name) = self.name.as_ref() {
103✔
60
            name.to_string()
×
61
        } else {
62
            name.as_ref()
91✔
63
                .rename_method(self.change_case.unwrap_or(default))
364✔
64
        }
65
    }
66
}
67

68
#[derive(Debug, Copy, Clone, FromMeta, Default)]
69
pub enum RenameRule {
70
    /// Methods won't be renamed.
71
    #[darling(rename = "none")]
72
    None,
73
    /// Methods will be converted to `camelCase`.
74
    #[darling(rename = "camelCase")]
75
    #[default]
76
    Camel,
77
    /// Methods will be converted to `snake_case`.
78
    #[darling(rename = "snake_case")]
79
    Snake,
80
    /// Methods will be converted to `PascalCase`.
81
    #[darling(rename = "PascalCase")]
82
    Pascal,
83
    /// Renames to `UPPER_SNAKE_CASE`.
84
    #[darling(rename = "UPPER_CASE")]
85
    ScreamingSnake,
86
}
87

88
impl RenameRule {
89
    fn rename(self, value: impl AsRef<str>) -> String {
21✔
90
        match self {
21✔
91
            Self::None => value.as_ref().to_string(),
1✔
92
            Self::Camel => value.as_ref().to_case(Case::Camel),
6✔
93
            Self::Pascal => value.as_ref().to_case(Case::Pascal),
6✔
94
            Self::Snake => value.as_ref().to_case(Case::Snake),
24✔
95
            Self::ScreamingSnake => value.as_ref().to_case(Case::Constant),
24✔
96
        }
97
    }
98
}
99

100
impl<T> Rename for T
101
where
102
    T: ToString,
103
{
104
    fn rename(&self, rule: RenameRule) -> String {
21✔
105
        rule.rename(self.to_string())
84✔
106
    }
107
}
108

109
impl<T> MethodRename for T
110
where
111
    T: ToString + Rename,
112
{
113
    fn rename_method(&self, rule: RenameRule) -> String {
181✔
114
        let original = self.to_string();
543✔
115
        match rule {
181✔
116
            RenameRule::None => original,
35✔
UNCOV
117
            _ => {
×
118
                if MAGIC_METHOD.contains(&original.as_str()) {
438✔
119
                    match original.as_str() {
136✔
120
                        "__to_string" => "__toString".to_string(),
152✔
121
                        "__debug_info" => "__debugInfo".to_string(),
144✔
122
                        "__call_static" => "__callStatic".to_string(),
136✔
123
                        _ => original,
112✔
124
                    }
125
                } else {
126
                    self.rename(rule)
10✔
127
                }
128
            }
129
        }
130
    }
131
}
132

133
#[cfg(test)]
134
mod tests {
135
    use crate::parsing::{MethodRename, Rename};
136

137
    use super::{PhpRename, RenameRule};
138

139
    #[test]
140
    fn php_rename() {
141
        let rename = PhpRename {
142
            name: Some("test".to_string()),
143
            change_case: None,
144
        };
145
        assert_eq!(rename.rename("testCase", RenameRule::Snake), "test");
146
        assert_eq!(rename.rename("TestCase", RenameRule::Snake), "test");
147
        assert_eq!(rename.rename("TEST_CASE", RenameRule::Snake), "test");
148

149
        let rename = PhpRename {
150
            name: None,
151
            change_case: Some(RenameRule::ScreamingSnake),
152
        };
153
        assert_eq!(rename.rename("testCase", RenameRule::Snake), "TEST_CASE");
154
        assert_eq!(rename.rename("TestCase", RenameRule::Snake), "TEST_CASE");
155
        assert_eq!(rename.rename("TEST_CASE", RenameRule::Snake), "TEST_CASE");
156

157
        let rename = PhpRename {
158
            name: Some("test".to_string()),
159
            change_case: Some(RenameRule::ScreamingSnake),
160
        };
161
        assert_eq!(rename.rename("testCase", RenameRule::Snake), "test");
162
        assert_eq!(rename.rename("TestCase", RenameRule::Snake), "test");
163
        assert_eq!(rename.rename("TEST_CASE", RenameRule::Snake), "test");
164

165
        let rename = PhpRename {
166
            name: None,
167
            change_case: None,
168
        };
169
        assert_eq!(rename.rename("testCase", RenameRule::Snake), "test_case");
170
        assert_eq!(rename.rename("TestCase", RenameRule::Snake), "test_case");
171
        assert_eq!(rename.rename("TEST_CASE", RenameRule::Snake), "test_case");
172
    }
173

174
    #[test]
175
    fn php_rename_method() {
176
        let rename = PhpRename {
177
            name: Some("test".to_string()),
178
            change_case: None,
179
        };
180
        assert_eq!(rename.rename_method("testCase", RenameRule::Snake), "test");
181
        assert_eq!(rename.rename_method("TestCase", RenameRule::Snake), "test");
182
        assert_eq!(rename.rename_method("TEST_CASE", RenameRule::Snake), "test");
183

184
        let rename = PhpRename {
185
            name: None,
186
            change_case: Some(RenameRule::ScreamingSnake),
187
        };
188
        assert_eq!(
189
            rename.rename_method("testCase", RenameRule::Snake),
190
            "TEST_CASE"
191
        );
192
        assert_eq!(
193
            rename.rename_method("TestCase", RenameRule::Snake),
194
            "TEST_CASE"
195
        );
196
        assert_eq!(
197
            rename.rename_method("TEST_CASE", RenameRule::Snake),
198
            "TEST_CASE"
199
        );
200

201
        let rename = PhpRename {
202
            name: Some("test".to_string()),
203
            change_case: Some(RenameRule::ScreamingSnake),
204
        };
205
        assert_eq!(rename.rename_method("testCase", RenameRule::Snake), "test");
206
        assert_eq!(rename.rename_method("TestCase", RenameRule::Snake), "test");
207
        assert_eq!(rename.rename_method("TEST_CASE", RenameRule::Snake), "test");
208

209
        let rename = PhpRename {
210
            name: None,
211
            change_case: None,
212
        };
213
        assert_eq!(
214
            rename.rename_method("testCase", RenameRule::Snake),
215
            "test_case"
216
        );
217
        assert_eq!(
218
            rename.rename_method("TestCase", RenameRule::Snake),
219
            "test_case"
220
        );
221
        assert_eq!(
222
            rename.rename_method("TEST_CASE", RenameRule::Snake),
223
            "test_case"
224
        );
225
    }
226

227
    #[test]
228
    fn rename_magic_method() {
229
        for &(magic, expected) in &[
230
            ("__construct", "__construct"),
231
            ("__destruct", "__destruct"),
232
            ("__call", "__call"),
233
            ("__call_static", "__callStatic"),
234
            ("__get", "__get"),
235
            ("__set", "__set"),
236
            ("__isset", "__isset"),
237
            ("__unset", "__unset"),
238
            ("__sleep", "__sleep"),
239
            ("__wakeup", "__wakeup"),
240
            ("__serialize", "__serialize"),
241
            ("__unserialize", "__unserialize"),
242
            ("__to_string", "__toString"),
243
            ("__invoke", "__invoke"),
244
            ("__set_state", "__set_state"),
245
            ("__clone", "__clone"),
246
            ("__debug_info", "__debugInfo"),
247
        ] {
248
            assert_eq!(magic, magic.rename_method(RenameRule::None));
249
            assert_eq!(
250
                magic,
251
                PhpRename {
252
                    name: None,
253
                    change_case: Some(RenameRule::None)
254
                }
255
                .rename_method(magic, RenameRule::ScreamingSnake)
256
            );
257

258
            assert_eq!(expected, magic.rename_method(RenameRule::Camel));
259
            assert_eq!(
260
                expected,
261
                PhpRename {
262
                    name: None,
263
                    change_case: Some(RenameRule::Camel)
264
                }
265
                .rename_method(magic, RenameRule::ScreamingSnake)
266
            );
267

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

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

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

300
    #[test]
301
    fn rename_method() {
302
        let &(original, camel, snake, pascal, screaming_snake) =
303
            &("get_name", "getName", "get_name", "GetName", "GET_NAME");
304
        assert_eq!(original, original.rename_method(RenameRule::None));
305
        assert_eq!(camel, original.rename_method(RenameRule::Camel));
306
        assert_eq!(pascal, original.rename_method(RenameRule::Pascal));
307
        assert_eq!(snake, original.rename_method(RenameRule::Snake));
308
        assert_eq!(
309
            screaming_snake,
310
            original.rename_method(RenameRule::ScreamingSnake)
311
        );
312
    }
313

314
    #[test]
315
    fn rename() {
316
        let &(original, camel, snake, pascal, screaming_snake) =
317
            &("get_name", "getName", "get_name", "GetName", "GET_NAME");
318
        assert_eq!(original, original.rename(RenameRule::None));
319
        assert_eq!(camel, original.rename(RenameRule::Camel));
320
        assert_eq!(pascal, original.rename(RenameRule::Pascal));
321
        assert_eq!(snake, original.rename(RenameRule::Snake));
322
        assert_eq!(screaming_snake, original.rename(RenameRule::ScreamingSnake));
323
    }
324
}
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