use con_::Con;
use element::Element::Spacing;
use swift::comment::BlockComment;
use swift::modifier::Modifier;
use swift::Swift;
use {Cons, Tokens};
use {Element, IntoTokens};
#[derive(Debug, Clone)]
pub struct Field<'el> {
pub modifiers: Vec<Modifier>,
pub comments: Vec<Cons<'el>>,
ty: Swift<'el>,
name: Cons<'el>,
initializer: Option<Tokens<'el, Swift<'el>>>,
mutable: bool,
getter: Option<Tokens<'el, Swift<'el>>>,
setter: Option<Tokens<'el, Swift<'el>>>,
}
impl<'el> Field<'el> {
pub fn new<T, N>(ty: T, name: N) -> Field<'el>
where
T: Into<Swift<'el>>,
N: Into<Cons<'el>>,
{
use self::Modifier::*;
Field {
modifiers: vec![Private],
comments: vec![],
ty: ty.into(),
name: name.into(),
initializer: None,
mutable: false,
getter: None,
setter: None,
}
}
pub fn initializer<I>(&mut self, initializer: I)
where
I: IntoTokens<'el, Swift<'el>>,
{
self.initializer = Some(initializer.into_tokens());
}
pub fn mutable(&mut self, mutable: bool) {
self.mutable = mutable;
}
pub fn var(&self) -> Cons<'el> {
self.name.clone()
}
pub fn ty(&self) -> Swift<'el> {
self.ty.clone()
}
}
into_tokens_impl_from!(Field<'el>, Swift<'el>);
impl<'el> IntoTokens<'el, Swift<'el>> for Field<'el> {
fn into_tokens(self) -> Tokens<'el, Swift<'el>> {
let mut tokens = Tokens::new();
tokens.push_unless_empty(BlockComment(self.comments));
tokens.append({
let mut sig = Tokens::new();
sig.extend(self.modifiers.into_tokens());
if self.mutable {
sig.append("var")
} else {
sig.append("let")
}
sig.append(self.name);
sig.append(":");
sig.append(self.ty);
if let Some(initializer) = self.initializer {
sig.append("=");
sig.append(initializer);
}
sig.join_spacing()
});
if self.getter.is_some() || self.setter.is_some() {
tokens.append(Spacing);
tokens.append("{");
tokens.nested({
let mut body = Tokens::new();
if let Some(getter) = self.getter {
body.push("get");
if !getter.is_empty() {
body.append(Spacing);
body.append("{");
body.push(getter);
body.push("}");
}
}
if let Some(setter) = self.setter {
body.push("set");
if !setter.is_empty() {
body.append(Spacing);
body.append("{");
body.push(setter);
body.push("}");
}
}
body
});
tokens.push("}");
}
tokens
}
}
impl<'el> From<Field<'el>> for Element<'el, Swift<'el>> {
fn from(f: Field<'el>) -> Self {
Element::Append(Con::Owned(f.into_tokens()))
}
}
#[cfg(test)]
mod tests {
use swift::field::Field;
use swift::local;
use tokens::Tokens;
fn field() -> Field<'static> {
Field::new(local("Int"), "foo")
}
#[test]
fn test_with_comments() {
let mut c = field();
c.comments.push("Hello World".into());
let t: Tokens<_> = c.into();
assert_eq!(
Ok(String::from(
"/**\n * Hello World\n */\nprivate let foo : Int",
)),
t.to_string()
);
}
#[test]
fn test_no_comments() {
let t = Tokens::from(field());
assert_eq!(Ok(String::from("private let foo : Int")), t.to_string());
}
#[test]
fn test_field() {
let mut field = Field::new(local("Int"), "foo");
field.mutable = true;
field.initializer("300");
field.getter = Some(Tokens::new());
field.setter = Some(Tokens::new());
let t: Tokens<_> = field.into();
let result = t.to_string();
assert_eq!(
Ok(String::from(
"private var foo : Int = 300 {\n get\n set\n}"
)),
result
);
}
}