rstgen/swift/
method.rs

1//! Data structure for methods.
2
3use swift::argument::Argument;
4use swift::comment::BlockComment;
5use swift::modifier::Modifier;
6use swift::{Swift, VOID};
7use {Cons, IntoTokens, Tokens};
8
9/// Model for Swift Methods.
10#[derive(Debug, Clone)]
11pub struct Method<'el> {
12    /// Method modifiers.
13    pub modifiers: Vec<Modifier>,
14    /// Arguments for the constructor.
15    pub arguments: Vec<Argument<'el>>,
16    /// Body of the constructor.
17    pub body: Tokens<'el, Swift<'el>>,
18    /// Return type.
19    pub returns: Option<Swift<'el>>,
20    /// Generic parameters.
21    pub parameters: Tokens<'el, Swift<'el>>,
22    /// Comments associated with this method.
23    pub comments: Vec<Cons<'el>>,
24    /// Exception thrown by the method.
25    pub throws: bool,
26    /// Annotations for the constructor.
27    attributes: Tokens<'el, Swift<'el>>,
28    /// Name of the method.
29    name: Cons<'el>,
30}
31
32impl<'el> Method<'el> {
33    /// Build a new empty constructor.
34    pub fn new<N>(name: N) -> Method<'el>
35    where
36        N: Into<Cons<'el>>,
37    {
38        use self::Modifier::*;
39
40        Method {
41            modifiers: vec![Public],
42            arguments: vec![],
43            body: Tokens::new(),
44            returns: None,
45            parameters: Tokens::new(),
46            comments: Vec::new(),
47            throws: false,
48            attributes: Tokens::new(),
49            name: name.into(),
50        }
51    }
52
53    /// Push an annotation.
54    pub fn attribute<A>(&mut self, attribute: A)
55    where
56        A: IntoTokens<'el, Swift<'el>>,
57    {
58        self.attributes.push(attribute.into_tokens());
59    }
60    /// Set returns of the method.
61    pub fn returns(&mut self, returns: Swift<'el>) {
62        self.returns = Some(returns)
63    }
64
65    /// Name of method.
66    pub fn name(&self) -> Cons<'el> {
67        self.name.clone()
68    }
69}
70
71into_tokens_impl_from!(Method<'el>, Swift<'el>);
72
73impl<'el> IntoTokens<'el, Swift<'el>> for Method<'el> {
74    fn into_tokens(self) -> Tokens<'el, Swift<'el>> {
75        let mut sig = Tokens::new();
76
77        sig.extend(self.modifiers.into_tokens());
78
79        sig.append({
80            let mut n = Tokens::new();
81
82            n.append("func ");
83            n.append(self.name);
84
85            if !self.parameters.is_empty() {
86                n.append(toks!["<", self.parameters.join(", "), ">"]);
87            }
88
89            let args: Vec<Tokens<Swift>> = self
90                .arguments
91                .into_iter()
92                .map(IntoTokens::into_tokens)
93                .collect();
94
95            let args: Tokens<Swift> = args.into_tokens();
96
97            n.append(toks!["(", args.join(", "), ")"]);
98
99            n
100        });
101
102        if let Some(returns) = self.returns {
103            if returns != VOID {
104                sig.append("->");
105                sig.append(returns);
106            }
107        }
108
109        if self.throws {
110            sig.append("throws");
111        }
112
113        let mut s = Tokens::new();
114
115        s.push_unless_empty(BlockComment(self.comments));
116        s.push_unless_empty(self.attributes);
117
118        let sig = sig.join_spacing();
119
120        if self.body.is_empty() {
121            s.push(toks![sig, ";"]);
122        } else {
123            s.push(toks![sig, " {"]);
124            s.nested(self.body);
125            s.push("}");
126        }
127
128        s
129    }
130}
131
132#[cfg(test)]
133mod tests {
134    use super::Method;
135    use swift::local;
136    use tokens::Tokens;
137
138    fn build_method() -> Method<'static> {
139        let mut c = Method::new("foo");
140        c.parameters.append("T");
141        c
142    }
143
144    fn build_return_method() -> Method<'static> {
145        let mut c = Method::new("foo");
146        c.parameters.append("T");
147        c.returns(local("Int"));
148        c
149    }
150
151    #[test]
152    fn test_with_comments() {
153        let mut c = build_method();
154        c.comments.push("Hello World".into());
155        let t = Tokens::from(c);
156        assert_eq!(
157            Ok(String::from(
158                "/**\n * Hello World\n */\npublic func foo<T>();",
159            )),
160            t.to_string()
161        );
162    }
163
164    #[test]
165    fn test_no_comments() {
166        let t = Tokens::from(build_method());
167        assert_eq!(Ok(String::from("public func foo<T>();")), t.to_string());
168    }
169
170    #[test]
171    fn test_throws() {
172        let mut m = build_method();
173        m.throws = true;
174
175        let t = Tokens::from(m);
176        assert_eq!(
177            Ok(String::from("public func foo<T>() throws;")),
178            t.to_string()
179        );
180    }
181
182    #[test]
183    fn test_returns() {
184        let t = Tokens::from(build_return_method());
185        assert_eq!(
186            Ok(String::from("public func foo<T>() -> Int;")),
187            t.to_string()
188        );
189    }
190}