fix_getters_rules/
function.rs

1//! Would-be-getter renaming rules definition.
2
3use once_cell::sync::Lazy;
4use std::{
5    collections::{HashMap, HashSet},
6    error::Error,
7    fmt::{self, Display},
8};
9
10use crate::{NewName, NewNameRule, ReturnsBool};
11
12/// Getters reserved suffix list.
13///
14/// Getter that we don't want to rename because
15/// they are Rust keywords or would result confusing.
16pub static RESERVED: Lazy<HashSet<&'static str>> = Lazy::new(|| {
17    let mut reserved = HashSet::new();
18    reserved.insert("");
19    reserved.insert("as");
20    reserved.insert("const"); // keep `get_const` similar to `get`
21    reserved.insert("else");
22    reserved.insert("false");
23    reserved.insert("for");
24    reserved.insert("if");
25    reserved.insert("in");
26    reserved.insert("mut"); // keep `get_mut` similar to `get`
27    reserved.insert("optional"); // keep `get_optional` similar to `get`
28    reserved.insert("or_init"); // keep `get_or_init`
29    reserved.insert("owned"); // keep `get_owned` similar to `get`
30    reserved.insert("ref"); // keep `get_ref` similar to `get`
31    reserved.insert("some"); // keep `get_some` similar to `get`
32    reserved.insert("true");
33    reserved.insert("unchecked");
34    reserved.insert("unchecked_mut");
35    reserved.insert("where");
36    reserved.insert("while");
37    reserved
38});
39
40/// Substitutes to be used when the suffix matches exactly.
41///
42/// The convention is to rename getters `get_suffix` as `suffix`,
43/// but there are cases for which a better name should be used:
44///
45/// - `get_type` -> `type_`.
46pub static EXACT_SUFFIX_SUBSTITUTES: Lazy<HashMap<&'static str, &'static str>> = Lazy::new(|| {
47    let mut exact_subs = HashMap::new();
48    exact_subs.insert("async", "async_");
49    exact_subs.insert("await", "await_");
50    exact_subs.insert("break", "break_");
51    exact_subs.insert("crate", "crate_");
52    exact_subs.insert("continue", "continue_");
53    exact_subs.insert("dyn", "dyn_");
54    exact_subs.insert("enum", "enum_");
55    exact_subs.insert("extern", "extern_");
56    exact_subs.insert("fn", "fn_");
57    exact_subs.insert("impl", "impl_");
58    exact_subs.insert("loop", "loop_");
59    exact_subs.insert("match", "match_");
60    exact_subs.insert("mod", "mod_");
61    exact_subs.insert("move", "move_");
62    exact_subs.insert("pub", "pub_");
63    exact_subs.insert("return", "return_");
64    exact_subs.insert("self", "self_");
65    exact_subs.insert("static", "static_");
66    exact_subs.insert("struct", "struct_");
67    exact_subs.insert("super", "super_");
68    exact_subs.insert("trait", "trait_");
69    exact_subs.insert("type", "type_");
70    exact_subs.insert("union", "union_");
71    exact_subs.insert("unsafe", "unsafe_");
72    exact_subs.insert("use", "use_");
73    exact_subs
74});
75
76/// Substitutes for tokens of `bool` getters.
77///
78/// The convention is to rename `bool` getters `get_suffix` as `is_suffix`,
79/// but there are cases for which we want a better name:
80///
81/// - `get_mute` -> `is_muted`.
82/// - `get_emit_eos` -> `emits_eos`.
83pub static BOOL_FIRST_TOKEN_SUBSTITUTES: Lazy<HashMap<&'static str, &'static str>> =
84    Lazy::new(|| {
85        let mut first_token_subs = HashMap::new();
86        first_token_subs.insert("activate", "activates");
87        first_token_subs.insert("accept", "accepts");
88        first_token_subs.insert("allow", "allows");
89        // Ex.: `get_always_show_image` -> `must_always_show_image`.
90        first_token_subs.insert("always", "must_always");
91        first_token_subs.insert("close", "closes");
92        first_token_subs.insert("create", "creates");
93        // Ex.: `get_destroy_with_parent` -> `must_destroy_with_parent`.
94        first_token_subs.insert("destroy", "must_destroy");
95        first_token_subs.insert("do", "does");
96        first_token_subs.insert("draw", "draws");
97        first_token_subs.insert("embed", "embeds");
98        first_token_subs.insert("emit", "emits");
99        first_token_subs.insert("enable", "enables");
100        first_token_subs.insert("exit", "exits");
101        first_token_subs.insert("expand", "expands");
102        first_token_subs.insert("fill", "fills");
103        first_token_subs.insert("fit", "fits");
104        // Ex.: `get_focus_on_map` -> `gets_focus_on_map`.
105        first_token_subs.insert("focus", "gets_focus");
106        first_token_subs.insert("follow", "follows");
107        first_token_subs.insert("hide", "hides");
108        first_token_subs.insert("ignore", "ignores");
109        first_token_subs.insert("invert", "inverts");
110        first_token_subs.insert("mute", "is_muted");
111        first_token_subs.insert("need", "needs");
112        first_token_subs.insert("propagate", "propagates");
113        first_token_subs.insert("populate", "populates");
114        first_token_subs.insert("receive", "receives");
115        first_token_subs.insert("reset", "resets");
116        first_token_subs.insert("require", "requires");
117        // Ex.: `get_reserve_indicator` -> `must_reserve_indicator`.
118        first_token_subs.insert("reserve", "must_reserve");
119        first_token_subs.insert("resize", "resizes");
120        first_token_subs.insert("restrict", "restricts");
121        first_token_subs.insert("reveal", "reveals");
122        first_token_subs.insert("select", "selects");
123        first_token_subs.insert("show", "shows");
124        first_token_subs.insert("shrink", "shrinks");
125        first_token_subs.insert("skip", "skips");
126        first_token_subs.insert("snap", "snaps");
127        first_token_subs.insert("support", "supports");
128        first_token_subs.insert("take", "takes");
129        first_token_subs.insert("track", "tracks");
130        // Ex.: `get_truncate_multiline` -> `must_truncate_multiline`.
131        first_token_subs.insert("truncate", "must_truncate");
132        first_token_subs.insert("use", "uses");
133        first_token_subs.insert("wrap", "wraps");
134        first_token_subs
135    });
136
137/// Set of `bool` getter suffix first tokens for which no be prefix should be applied.
138///
139/// The convention is to rename `bool` getters `get_suffix` as `is_suffix`,
140/// but there are cases for which the meaning makes it useless to add the `is` prefix:
141///
142/// - `get_has_entry` -> `has_entry`.
143pub static BOOL_FIRST_TOKEN_NO_PREFIX: Lazy<HashSet<&'static str>> = Lazy::new(|| {
144    let mut first_tokens = HashSet::new();
145    first_tokens.insert("can");
146    first_tokens.insert("has");
147    first_tokens.insert("must");
148    first_tokens.insert("should");
149    first_tokens.insert("state");
150    // Also add all the prefix substitutes (e.g. accepts, skips, ...)
151    for bool_substitute in BOOL_FIRST_TOKEN_SUBSTITUTES.values() {
152        first_tokens.insert(bool_substitute);
153    }
154    first_tokens
155});
156
157/// Substitutes of `bool` getter to be used when the suffix matches exactly.
158///
159/// The convention is to rename `bool` getters `get_suffix` as `is_suffix`,
160/// but there are cases for which it would be confusing to add the `is` prefix:
161///
162/// - `get_result` -> `result`.
163/// - `get_overwrite` -> `overwrites`. Note that if the getter suffix doesn't match
164///   exactly, this rule doesn't apply. Ex. `get_overwrite_mode` -> `is_overwrites_mode`
165pub static BOOL_EXACT_SUBSTITUTES: Lazy<HashMap<&'static str, &'static str>> = Lazy::new(|| {
166    let mut exact_subs = HashMap::new();
167    exact_subs.insert("result", "result");
168    exact_subs.insert("overwrite", "overwrites");
169    exact_subs.insert("visibility", "is_visible");
170    exact_subs
171});
172
173/// Special suffix to detect getters returning a `bool`.
174///
175/// Ex.: `get_seekable`.
176pub const BOOL_ABLE_PREFIX: &str = "able";
177
178/// Getters prefix to move to the end.
179///
180/// The convention is to use the form:
181/// - `get_structure_mut`.
182///
183/// but we can run into this one too:
184/// - `get_mut_structure`.
185pub static PREFIX_TO_POSTFIX: Lazy<HashSet<&'static str>> = Lazy::new(|| {
186    let mut prefix_to_postfix = HashSet::new();
187    prefix_to_postfix.insert("mut");
188    prefix_to_postfix
189});
190
191/// Attempts to apply getter name rules to this would-be-getter function.
192///
193/// The argument `returns_bool` hints the renaming process when
194/// the getter returns a unique `bool` value. Use [`ReturnsBool::Maybe`]
195/// if the return value is not known.
196pub fn try_rename_would_be_getter(
197    name: &str,
198    returns_bool: impl Into<ReturnsBool>,
199) -> Result<NewName, RenameError> {
200    let suffix = match name.strip_prefix("get_") {
201        Some(suffix) => suffix,
202        None => return Err(RenameError::NotGetFn),
203    };
204
205    try_rename_getter_suffix(suffix, returns_bool)
206}
207
208/// Attempts to apply getter name rules to this getter suffix.
209///
210/// The argument `returns_bool` hints the renaming process when
211/// the getter returns a unique `bool` value. Use [`ReturnsBool::Maybe`]
212/// if the return value is not known.
213pub fn try_rename_getter_suffix(
214    suffix: &str,
215    returns_bool: impl Into<ReturnsBool>,
216) -> Result<NewName, RenameError> {
217    use ReturnsBool::*;
218    let returns_bool = match returns_bool.into() {
219        False => ReturnsBool::False,
220        True => return Ok(rename_bool_getter(suffix)),
221        Maybe => {
222            if let Some(rename) = guesstimate_boolness_then_rename(suffix) {
223                return Ok(rename);
224            }
225            ReturnsBool::Maybe
226        }
227    };
228
229    if let Some(substitute) = EXACT_SUFFIX_SUBSTITUTES.get(suffix) {
230        return Ok(NewName {
231            new_name: substitute.to_string(),
232            returns_bool,
233            rule: NewNameRule::Substituted,
234        });
235    }
236
237    let splits: Vec<&str> = suffix.splitn(2, '_').collect();
238    if splits.len() > 1 && PREFIX_TO_POSTFIX.contains(splits[0]) {
239        Ok(NewName {
240            new_name: format!("{}_{}", splits[1], splits[0]),
241            returns_bool,
242            rule: NewNameRule::Fixed,
243        })
244    } else if RESERVED.contains(suffix) {
245        Err(RenameError::Reserved)
246    } else {
247        Ok(NewName {
248            new_name: suffix.to_string(),
249            returns_bool,
250            rule: NewNameRule::Regular,
251        })
252    }
253}
254
255/// Applies `bool` getter name rules.
256#[inline]
257pub fn rename_bool_getter(suffix: &str) -> NewName {
258    if let Some(substitute) = BOOL_EXACT_SUBSTITUTES.get(suffix) {
259        return NewName {
260            new_name: substitute.to_string(),
261            returns_bool: true.into(),
262            rule: NewNameRule::Substituted,
263        };
264    }
265
266    if let Some(new_name) = try_rename_bool_getter(suffix) {
267        new_name
268    } else {
269        NewName {
270            new_name: format!("is_{}", suffix),
271            returns_bool: true.into(),
272            rule: NewNameRule::Regular,
273        }
274    }
275}
276
277/// Attempts to apply special rules to the `bool` getter.
278///
279/// The substitutions are defined in [`BOOL_FIRST_TOKEN_SUBSTITUTES`]
280/// and [`BOOL_FIRST_TOKEN_NO_PREFIX`].
281#[inline]
282fn try_rename_bool_getter(suffix: &str) -> Option<NewName> {
283    let mut working_suffix = suffix;
284    let mut has_is_prefix = false;
285
286    if let Some(suffix_without_is) = suffix.strip_prefix("is_") {
287        working_suffix = suffix_without_is;
288        has_is_prefix = true;
289    }
290
291    let splits: Vec<&str> = working_suffix.splitn(2, '_').collect();
292    BOOL_FIRST_TOKEN_SUBSTITUTES
293        .get(splits[0])
294        .map(|substitute| {
295            if splits.len() == 1 {
296                NewName {
297                    new_name: substitute.to_string(),
298                    returns_bool: true.into(),
299                    rule: NewNameRule::Substituted,
300                }
301            } else {
302                NewName {
303                    new_name: format!("{}_{}", substitute, splits[1]),
304                    returns_bool: true.into(),
305                    rule: NewNameRule::Substituted,
306                }
307            }
308        })
309        .or_else(|| {
310            BOOL_FIRST_TOKEN_NO_PREFIX.get(splits[0]).map(|_| {
311                if splits.len() == 1 {
312                    NewName {
313                        new_name: splits[0].to_string(),
314                        returns_bool: true.into(),
315                        rule: NewNameRule::NoPrefix,
316                    }
317                } else {
318                    NewName {
319                        new_name: format!("{}_{}", splits[0], splits[1]),
320                        returns_bool: true.into(),
321                        rule: NewNameRule::NoPrefix,
322                    }
323                }
324            })
325        })
326        .or_else(|| {
327            // No bool rules applied to the working suffix
328            if has_is_prefix {
329                // but the suffix was already `is` prefixed
330                Some(NewName {
331                    new_name: suffix.to_string(),
332                    returns_bool: true.into(),
333                    rule: NewNameRule::Regular,
334                })
335            } else {
336                None
337            }
338        })
339}
340
341/// Attempts to determine whether the getter returns a `bool` from its name.
342///
343/// Uses [`BOOL_FIRST_TOKEN_SUBSTITUTES`], [`BOOL_FIRST_TOKEN_NO_PREFIX`] and
344/// [`BOOL_ABLE_PREFIX`] as a best effort estimation.
345///
346/// Returns the name substitute if `self` seems to be returning a `bool`.
347#[inline]
348pub fn guesstimate_boolness_then_rename(suffix: &str) -> Option<NewName> {
349    if let Some(new_name) = try_rename_bool_getter(suffix) {
350        return Some(new_name);
351    }
352
353    let splits: Vec<&str> = suffix.splitn(2, '_').collect();
354    if splits[0].ends_with(BOOL_ABLE_PREFIX) {
355        Some(NewName {
356            new_name: format!("is_{}", suffix),
357            returns_bool: true.into(),
358            rule: NewNameRule::Regular,
359        })
360    } else {
361        None
362    }
363}
364
365/// Would-be-getter rename attempt failure result.
366///
367/// Holds details about the reason of the failure.
368#[derive(Debug, Copy, Clone, PartialEq)]
369#[non_exhaustive]
370pub enum RenameError {
371    /// The function doesn't start with `get_`.
372    NotGetFn,
373    /// The function uses a reserved name and can't be renamed.
374    Reserved,
375}
376
377impl RenameError {
378    pub fn is_not_get_fn(&self) -> bool {
379        matches!(self, RenameError::NotGetFn)
380    }
381
382    pub fn is_reserved(&self) -> bool {
383        matches!(self, RenameError::Reserved)
384    }
385}
386
387impl Display for RenameError {
388    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
389        use RenameError::*;
390        match self {
391            NotGetFn => write!(f, "not a get function"),
392            Reserved => write!(f, "name is reserved"),
393        }
394    }
395}
396
397impl Error for RenameError {}
398
399#[cfg(test)]
400mod tests {
401    use super::*;
402
403    #[test]
404    fn bool_getter_rename_attempt() {
405        let new_name = try_rename_bool_getter(&"mute").unwrap();
406        assert!(new_name.is_substituted());
407        assert!(new_name.returns_bool().is_true());
408        assert_eq!(new_name, "is_muted");
409
410        let new_name = try_rename_bool_getter(&"emit_eos").unwrap();
411        assert!(new_name.is_substituted());
412        assert!(new_name.returns_bool().is_true());
413        assert_eq!(new_name, "emits_eos");
414
415        let new_name = try_rename_bool_getter(&"has_entry").unwrap();
416        assert!(new_name.is_no_prefix());
417        assert!(new_name.returns_bool().is_true());
418        assert_eq!(new_name, "has_entry");
419
420        let new_name = try_rename_bool_getter(&"is_emit_eos").unwrap();
421        assert!(new_name.is_substituted());
422        assert!(new_name.returns_bool().is_true());
423        assert_eq!(new_name, "emits_eos");
424
425        let new_name = try_rename_bool_getter(&"is_activated").unwrap();
426        assert!(new_name.is_regular());
427        assert!(new_name.returns_bool().is_true());
428        assert_eq!(new_name, "is_activated");
429
430        assert!(try_rename_bool_getter(&"name").is_none());
431    }
432
433    #[test]
434    fn bool_getter_suffix() {
435        let new_name = rename_bool_getter(&"result");
436        assert!(new_name.is_substituted());
437        assert!(new_name.returns_bool().is_true());
438        assert_eq!(new_name, "result");
439
440        let new_name = rename_bool_getter(&"activable");
441        assert!(new_name.is_regular());
442        assert!(new_name.returns_bool().is_true());
443        assert_eq!(new_name, "is_activable");
444
445        let new_name = rename_bool_getter(&"mute");
446        assert!(new_name.is_substituted());
447        assert!(new_name.returns_bool().is_true());
448        assert_eq!(new_name, "is_muted");
449
450        let new_name = rename_bool_getter(&"emit_eos");
451        assert!(new_name.is_substituted());
452        assert!(new_name.returns_bool().is_true());
453        assert_eq!(new_name, "emits_eos");
454
455        let new_name = rename_bool_getter(&"can_acquire");
456        assert!(new_name.is_no_prefix());
457        assert!(new_name.returns_bool().is_true());
458        assert_eq!(new_name, "can_acquire");
459    }
460
461    #[test]
462    fn boolness_guestimation() {
463        assert!(guesstimate_boolness_then_rename(&"result").is_none());
464        assert!(guesstimate_boolness_then_rename(&"name").is_none());
465
466        let new_name = guesstimate_boolness_then_rename(&"mute").unwrap();
467        assert!(new_name.returns_bool().is_true());
468        assert_eq!(new_name, "is_muted");
469
470        let new_name = guesstimate_boolness_then_rename(&"does_ts").unwrap();
471        assert!(new_name.returns_bool().is_true());
472        assert_eq!(new_name, "does_ts");
473
474        let new_name = guesstimate_boolness_then_rename(&"emit_eos").unwrap();
475        assert!(new_name.returns_bool().is_true());
476        assert_eq!(new_name, "emits_eos");
477
478        let new_name = guesstimate_boolness_then_rename(&"emits_eos").unwrap();
479        assert!(new_name.returns_bool().is_true());
480        assert_eq!(new_name, "emits_eos");
481
482        let new_name = guesstimate_boolness_then_rename(&"is_emits_eos").unwrap();
483        assert!(new_name.returns_bool().is_true());
484        assert_eq!(new_name, "emits_eos");
485
486        let new_name = guesstimate_boolness_then_rename(&"is_activated").unwrap();
487        assert!(new_name.returns_bool().is_true());
488        assert_eq!(new_name, "is_activated");
489
490        let new_name = guesstimate_boolness_then_rename(&"activable").unwrap();
491        assert!(new_name.returns_bool().is_true());
492        assert_eq!(new_name, "is_activable");
493    }
494
495    #[test]
496    fn rename_getter_non_bool() {
497        let new_name = try_rename_would_be_getter(&"get_structure", false).unwrap();
498        assert!(new_name.is_regular());
499        assert!(new_name.returns_bool().is_false());
500        assert_eq!(new_name, "structure");
501
502        let new_name = try_rename_would_be_getter(&"get_type", false).unwrap();
503        assert!(new_name.is_substituted());
504        assert!(new_name.returns_bool().is_false());
505        assert_eq!(new_name, "type_");
506
507        // Bool-alike, but not a bool
508        let new_name = try_rename_would_be_getter(&"get_activable", false).unwrap();
509        assert!(new_name.is_regular());
510        assert!(new_name.returns_bool().is_false());
511        assert_eq!(new_name, "activable");
512
513        // Prefix to postfix
514        let new_name = try_rename_would_be_getter(&"get_mut_structure", false).unwrap();
515        assert!(new_name.is_fixed());
516        assert!(new_name.returns_bool().is_false());
517        assert_eq!(new_name, "structure_mut");
518
519        assert!(try_rename_would_be_getter(&"get_mut", false)
520            .unwrap_err()
521            .is_reserved());
522        assert!(try_rename_would_be_getter(&"not_a_getter", false)
523            .unwrap_err()
524            .is_not_get_fn());
525    }
526
527    #[test]
528    fn rename_getter_bool() {
529        let new_name = try_rename_would_be_getter(&"get_structure", true).unwrap();
530        assert!(new_name.is_regular());
531        assert!(new_name.returns_bool().is_true());
532        assert_eq!(new_name, "is_structure");
533
534        let new_name = try_rename_would_be_getter(&"get_type", true).unwrap();
535        assert!(new_name.is_regular());
536        assert!(new_name.returns_bool().is_true());
537        assert_eq!(new_name, "is_type");
538
539        let new_name = try_rename_would_be_getter(&"get_mute", true).unwrap();
540        assert!(new_name.is_substituted());
541        assert!(new_name.returns_bool().is_true());
542        assert_eq!(new_name, "is_muted");
543
544        let new_name = try_rename_would_be_getter(&"get_emit_eos", true).unwrap();
545        assert!(new_name.is_substituted());
546        assert!(new_name.returns_bool().is_true());
547        assert_eq!(new_name, "emits_eos");
548
549        let new_name = try_rename_would_be_getter(&"get_emits_eos", true).unwrap();
550        assert!(new_name.is_no_prefix());
551        assert!(new_name.returns_bool().is_true());
552        assert_eq!(new_name, "emits_eos");
553
554        let new_name = try_rename_would_be_getter(&"get_is_emit_eos", true).unwrap();
555        assert!(new_name.is_substituted());
556        assert!(new_name.returns_bool().is_true());
557        assert_eq!(new_name, "emits_eos");
558
559        let new_name = try_rename_would_be_getter(&"get_is_activated", true).unwrap();
560        assert!(new_name.is_regular());
561        assert!(new_name.returns_bool().is_true());
562        assert_eq!(new_name, "is_activated");
563
564        let new_name = try_rename_would_be_getter(&"get_activable", true).unwrap();
565        assert!(new_name.is_regular());
566        assert!(new_name.returns_bool().is_true());
567        assert_eq!(new_name, "is_activable");
568
569        let new_name = try_rename_would_be_getter(&"get_mut", true).unwrap();
570        assert!(new_name.is_regular());
571        assert!(new_name.returns_bool().is_true());
572        assert_eq!(new_name, "is_mut");
573
574        let new_name = try_rename_would_be_getter(&"get_overwrite", true).unwrap();
575        assert!(new_name.is_substituted());
576        assert!(new_name.returns_bool().is_true());
577        assert_eq!(new_name, "overwrites");
578
579        let new_name = try_rename_would_be_getter(&"get_overwrite_mode", true).unwrap();
580        assert!(new_name.is_regular());
581        assert!(new_name.returns_bool().is_true());
582        assert_eq!(new_name, "is_overwrite_mode");
583
584        assert!(try_rename_would_be_getter(&"not_a_getter", true)
585            .unwrap_err()
586            .is_not_get_fn());
587    }
588
589    #[test]
590    fn rename_getter_maybe_bool() {
591        let new_name = try_rename_would_be_getter(&"get_structure", ReturnsBool::Maybe).unwrap();
592        assert!(new_name.is_regular());
593        assert!(new_name.returns_bool().is_maybe());
594        assert_eq!(new_name, "structure");
595
596        let new_name = try_rename_would_be_getter(&"get_type", ReturnsBool::Maybe).unwrap();
597        assert!(new_name.is_substituted());
598        assert!(new_name.returns_bool().is_maybe());
599        assert_eq!(new_name, "type_");
600
601        let new_name = try_rename_would_be_getter(&"get_mute", ReturnsBool::Maybe).unwrap();
602        assert!(new_name.is_substituted());
603        assert!(new_name.returns_bool().is_true());
604        assert_eq!(new_name, "is_muted");
605
606        let new_name = try_rename_would_be_getter(&"get_emit_eos", ReturnsBool::Maybe).unwrap();
607        assert!(new_name.is_substituted());
608        assert!(new_name.returns_bool().is_true());
609        assert_eq!(new_name, "emits_eos");
610
611        let new_name = try_rename_would_be_getter(&"get_emits_eos", ReturnsBool::Maybe).unwrap();
612        assert!(new_name.is_no_prefix());
613        assert!(new_name.returns_bool().is_true());
614        assert_eq!(new_name, "emits_eos");
615
616        let new_name = try_rename_would_be_getter(&"get_is_emit_eos", ReturnsBool::Maybe).unwrap();
617        assert!(new_name.is_substituted());
618        assert!(new_name.returns_bool().is_true());
619        assert_eq!(new_name, "emits_eos");
620
621        let new_name = try_rename_would_be_getter(&"get_is_activated", ReturnsBool::Maybe).unwrap();
622        assert!(new_name.is_regular());
623        assert!(new_name.returns_bool().is_true());
624        assert_eq!(new_name, "is_activated");
625
626        let new_name = try_rename_would_be_getter(&"get_activable", ReturnsBool::Maybe).unwrap();
627        assert!(new_name.is_regular());
628        assert!(new_name.returns_bool().is_true());
629        assert_eq!(new_name, "is_activable");
630
631        assert!(try_rename_would_be_getter(&"get_mut", ReturnsBool::Maybe)
632            .unwrap_err()
633            .is_reserved());
634        assert!(
635            try_rename_would_be_getter(&"not_a_getter", ReturnsBool::Maybe)
636                .unwrap_err()
637                .is_not_get_fn()
638        );
639    }
640}