1use swift::argument::Argument;
4use swift::comment::BlockComment;
5use swift::modifier::Modifier;
6use swift::{Swift, VOID};
7use {Cons, IntoTokens, Tokens};
8
9#[derive(Debug, Clone)]
11pub struct Method<'el> {
12 pub modifiers: Vec<Modifier>,
14 pub arguments: Vec<Argument<'el>>,
16 pub body: Tokens<'el, Swift<'el>>,
18 pub returns: Option<Swift<'el>>,
20 pub parameters: Tokens<'el, Swift<'el>>,
22 pub comments: Vec<Cons<'el>>,
24 pub throws: bool,
26 attributes: Tokens<'el, Swift<'el>>,
28 name: Cons<'el>,
30}
31
32impl<'el> Method<'el> {
33 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 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 pub fn returns(&mut self, returns: Swift<'el>) {
62 self.returns = Some(returns)
63 }
64
65 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}