fix_getters_utils/
getter.rs

1//! `Getter` helper.
2
3#[cfg(feature = "log")]
4use log::{debug, trace};
5
6use std::{
7    error::Error,
8    fmt::{self, Display},
9    path::Path,
10};
11
12use rules::{self, NewName, RenameError, ReturnsBool};
13
14/// `Getter` helper.
15///
16/// A `Getter` is a function for which the renaming rules defined in crate
17/// [`fix-getters-rules`](../../fix_getters_rules/function/index.html) hold.
18#[derive(Debug)]
19pub struct Getter {
20    pub name: String,
21    pub new_name: NewName,
22    pub line: usize,
23}
24
25#[derive(Debug)]
26pub struct GetterError {
27    pub name: String,
28    pub err: RenameError,
29    pub line: usize,
30}
31
32impl GetterError {
33    /// Logs details about the getter creation failure at the appropriate log level.
34    #[cfg(feature = "log")]
35    pub fn log(&self, scope: &dyn Display) {
36        if !self.err.is_not_get_fn() {
37            debug!("* {} {}", scope, self);
38        } else {
39            trace!("* {} {}", scope, self);
40        }
41    }
42}
43
44impl Display for GetterError {
45    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
46        write!(f, "@ {}: skipping {}() {}", self.line, self.name, self.err)
47    }
48}
49
50impl Error for GetterError {}
51
52impl Getter {
53    /// Attempts to build a `Getter` from the provided data.
54    pub fn try_new(
55        name: String,
56        returns_bool: impl Into<ReturnsBool> + Copy,
57        line: usize,
58    ) -> Result<Self, GetterError> {
59        match rules::try_rename_would_be_getter(&name, returns_bool) {
60            Ok(new_name) => Ok(Getter {
61                name,
62                new_name,
63                line,
64            }),
65            Err(err) => Err(GetterError { name, err, line }),
66        }
67    }
68
69    pub fn returns_bool(&self) -> ReturnsBool {
70        self.new_name.returns_bool()
71    }
72
73    pub fn set_returns_bool(&mut self, returns_bool: impl Into<ReturnsBool>) {
74        let returns_bool = returns_bool.into();
75        if self.new_name.returns_bool() != returns_bool {
76            self.new_name = rules::try_rename_would_be_getter(&self.name, returns_bool)
77                .expect("conformity already checked");
78        }
79    }
80
81    /// Logs details about the getter at the appropriate log level.
82    #[cfg(feature = "log")]
83    pub fn log(&self, _path: &Path, scope: &dyn Display) {
84        if self.new_name.is_regular() {
85            trace!("* {} {}", scope, self);
86        } else {
87            debug!("* {} {}", scope, self);
88        }
89    }
90}
91
92impl Display for Getter {
93    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
94        write!(f, "@ {}: {}() {}()", self.line, self.name, self.new_name,)
95    }
96}
97
98/// Logs the reason for skipping the `name` function.
99#[cfg(feature = "log")]
100pub fn skip(scope: &dyn Display, name: &str, reason: &dyn Display, line: usize) {
101    debug!("* {} @ {}: skipping {}() {}", scope, line, name, reason);
102}
103
104/// Reason for considering a function is not a getter.
105#[derive(Debug, PartialEq)]
106#[non_exhaustive]
107pub enum NonGetterReason {
108    GenericTypeParam,
109    MultipleArgs,
110    NotAGet,
111    NotAMethod,
112    NonSelfUniqueArg,
113    NoArgs,
114}
115
116impl Display for NonGetterReason {
117    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
118        use NonGetterReason::*;
119        match self {
120            GenericTypeParam => f.write_str("generic type parameter(s)"),
121            MultipleArgs => f.write_str("multiple arguments (incl. self)"),
122            NotAGet => f.write_str("not a get function"),
123            NotAMethod => f.write_str("not a method"),
124            NonSelfUniqueArg => f.write_str("unique argument is not self"),
125            NoArgs => f.write_str("no arguments"),
126        }
127    }
128}