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

davidcole1340 / ext-php-rs / 15331766277

29 May 2025 07:22PM CUT coverage: 20.798% (-0.1%) from 20.927%
15331766277

Pull #436

github

Xenira
chore(macro)!: change rename defaults to match psr

BREAKING CHANGE: Methods and Properties are renamed to camelCase by default. Classes to PascalCase and constants to UPPER_CASE.

Refs: #189
Pull Request #436: chore(macro)!: change rename defaults to match psr

8 of 29 new or added lines in 5 files covered. (27.59%)

2 existing lines in 2 files now uncovered.

818 of 3933 relevant lines covered (20.8%)

2.05 hits per line

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

76.67
/crates/macros/src/parsing.rs
1
use darling::FromMeta;
2

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

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

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

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

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

48
impl PhpRename {
49
    pub fn rename(&self, name: impl AsRef<str>, default: RenameRule) -> String {
12✔
50
        if let Some(name) = self.name.as_ref() {
18✔
NEW
51
            return name.to_string();
×
52
        }
53

54
        name.as_ref().rename(self.rename.unwrap_or(default))
6✔
55
    }
56

NEW
57
    pub fn rename_method(&self, name: impl AsRef<str>, default: RenameRule) -> String {
×
NEW
58
        if let Some(name) = self.name.as_ref() {
×
NEW
59
            return name.to_string();
×
60
        }
61

NEW
62
        name.as_ref().rename_method(self.rename.unwrap_or(default))
×
63
    }
64
}
65

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

86
impl RenameRule {
87
    fn rename(self, value: impl AsRef<str>) -> String {
15✔
88
        match self {
15✔
89
            Self::None => value.as_ref().to_string(),
4✔
90
            Self::Camel => ident_case::RenameRule::CamelCase.apply_to_field(value.as_ref()),
2✔
91
            Self::Pascal => ident_case::RenameRule::PascalCase.apply_to_field(value.as_ref()),
2✔
92
            Self::Snake => ident_case::RenameRule::SnakeCase.apply_to_field(value.as_ref()),
2✔
93
            Self::ScreamingSnakeCase => {
×
94
                ident_case::RenameRule::ScreamingSnakeCase.apply_to_field(value.as_ref())
5✔
95
            }
96
        }
97
    }
98
}
99

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

109
impl<T> MethodRename for T
110
where
111
    T: ToString + Rename,
112
{
113
    fn rename_method(&self, rule: RenameRule) -> String {
90✔
114
        let original = self.to_string();
90✔
115
        match rule {
90✔
116
            RenameRule::None => original,
18✔
UNCOV
117
            _ => {
×
118
                if MAGIC_METHOD.contains(&original.as_str()) {
72✔
119
                    match original.as_str() {
68✔
120
                        "__to_string" => "__toString".to_string(),
72✔
121
                        "__debug_info" => "__debugInfo".to_string(),
68✔
122
                        "__call_static" => "__callStatic".to_string(),
64✔
123
                        _ => (*self).to_string(),
56✔
124
                    }
125
                } else {
126
                    self.rename(rule)
4✔
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
            rename: None,
144
        };
145
        assert_eq!(rename.rename("test", RenameRule::None), "test");
146
        assert_eq!(rename.rename("Test", RenameRule::None), "test");
147
        assert_eq!(rename.rename("TEST", RenameRule::None), "test");
148

149
        let rename = PhpRename {
150
            name: None,
151
            rename: Some(RenameRule::ScreamingSnakeCase),
152
        };
153
        assert_eq!(rename.rename("test", RenameRule::None), "TEST");
154
        assert_eq!(rename.rename("Test", RenameRule::None), "TEST");
155
        assert_eq!(rename.rename("TEST", RenameRule::None), "TEST");
156

157
        let rename = PhpRename {
158
            name: Some("test".to_string()),
159
            rename: Some(RenameRule::ScreamingSnakeCase),
160
        };
161
        assert_eq!(rename.rename("test", RenameRule::None), "test");
162
        assert_eq!(rename.rename("Test", RenameRule::None), "test");
163
        assert_eq!(rename.rename("TEST", RenameRule::None), "test");
164

165
        let rename = PhpRename {
166
            name: None,
167
            rename: None,
168
        };
169
        assert_eq!(rename.rename("test", RenameRule::None), "test");
170
        assert_eq!(rename.rename("Test", RenameRule::None), "Test");
171
        assert_eq!(rename.rename("TEST", RenameRule::None), "TEST");
172
    }
173

174
    #[test]
175
    fn rename_magic_method() {
176
        for &(magic, expected) in &[
177
            ("__construct", "__construct"),
178
            ("__destruct", "__destruct"),
179
            ("__call", "__call"),
180
            ("__call_static", "__callStatic"),
181
            ("__get", "__get"),
182
            ("__set", "__set"),
183
            ("__isset", "__isset"),
184
            ("__unset", "__unset"),
185
            ("__sleep", "__sleep"),
186
            ("__wakeup", "__wakeup"),
187
            ("__serialize", "__serialize"),
188
            ("__unserialize", "__unserialize"),
189
            ("__to_string", "__toString"),
190
            ("__invoke", "__invoke"),
191
            ("__set_state", "__set_state"),
192
            ("__clone", "__clone"),
193
            ("__debug_info", "__debugInfo"),
194
        ] {
195
            assert_eq!(magic, magic.rename_method(RenameRule::None));
196
            assert_eq!(expected, magic.rename_method(RenameRule::Camel));
197
            assert_eq!(expected, magic.rename_method(RenameRule::Pascal));
198
            assert_eq!(expected, magic.rename_method(RenameRule::Snake));
199
            assert_eq!(
200
                expected,
201
                magic.rename_method(RenameRule::ScreamingSnakeCase)
202
            );
203
        }
204
    }
205

206
    #[test]
207
    fn rename_method() {
208
        let &(original, camel, snake, pascal, screaming_snake) =
209
            &("get_name", "getName", "get_name", "GetName", "GET_NAME");
210
        assert_eq!(original, original.rename_method(RenameRule::None));
211
        assert_eq!(camel, original.rename_method(RenameRule::Camel));
212
        assert_eq!(pascal, original.rename_method(RenameRule::Pascal));
213
        assert_eq!(snake, original.rename_method(RenameRule::Snake));
214
        assert_eq!(
215
            screaming_snake,
216
            original.rename_method(RenameRule::ScreamingSnakeCase)
217
        );
218
    }
219

220
    #[test]
221
    fn rename() {
222
        let &(original, camel, snake, pascal, screaming_snake) =
223
            &("get_name", "getName", "get_name", "GetName", "GET_NAME");
224
        assert_eq!(original, original.rename(RenameRule::None));
225
        assert_eq!(camel, original.rename(RenameRule::Camel));
226
        assert_eq!(pascal, original.rename(RenameRule::Pascal));
227
        assert_eq!(snake, original.rename(RenameRule::Snake));
228
        assert_eq!(
229
            screaming_snake,
230
            original.rename(RenameRule::ScreamingSnakeCase)
231
        );
232
    }
233
}
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