1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
//! Data structure for constructors

use super::argument::Argument;
use super::modifier::Modifier;
use con_::Con::Owned;
use cons::Cons;
use csharp::Csharp;
use element::Element;
use into_tokens::IntoTokens;
use tokens::Tokens;

/// Model for Csharp Constructors.
#[derive(Debug, Clone)]
pub struct Constructor<'el> {
    /// Constructor modifiers.
    pub modifiers: Vec<Modifier>,
    /// Arguments for the constructor.
    pub arguments: Vec<Argument<'el>>,
    /// Body of the constructor.
    pub body: Tokens<'el, Csharp<'el>>,
    /// Base call
    pub base: Option<Tokens<'el, Csharp<'el>>>,
    /// attributes for the constructor.
    attributes: Tokens<'el, Csharp<'el>>,
}

impl<'el> Constructor<'el> {
    /// Build a new empty constructor.
    pub fn new() -> Constructor<'el> {
        Constructor {
            modifiers: vec![Modifier::Public],
            arguments: Vec::new(),
            body: Tokens::new(),
            base: None,
            attributes: Tokens::new(),
        }
    }

    /// Push a attribute.
    pub fn attribute<T>(&mut self, attribute: T)
    where
        T: IntoTokens<'el, Csharp<'el>>,
    {
        self.attributes.push(attribute.into_tokens());
    }
}

into_tokens_impl_from!((Cons<'el>, Constructor<'el>), Csharp<'el>);

impl<'el> IntoTokens<'el, Csharp<'el>> for (Cons<'el>, Constructor<'el>) {
    fn into_tokens(self) -> Tokens<'el, Csharp<'el>> {
        use self::Element::*;

        let (name, mut c) = self;

        let args: Vec<Tokens<Csharp>> = c.arguments.into_iter().map(|a| a.into_tokens()).collect();
        let args: Tokens<Csharp> = args.into_tokens();

        let mut sig: Tokens<Csharp> = Tokens::new();

        c.modifiers.sort();
        sig.extend(c.modifiers.into_iter().map(Into::into));

        if !args.is_empty() {
            let sep = toks![",", PushSpacing];
            let args = args.join(sep);

            sig.append(toks![name, "(", Nested(Owned(args)), ")",]);
        } else {
            sig.append(toks![name, "()"]);
        }

        if let Some(base) = c.base {
            sig.append(":");
            sig.append(base);
        }

        let mut s = Tokens::new();

        if !c.attributes.is_empty() {
            s.push(c.attributes);
        }

        s.push(toks![sig.join_spacing(), " {"]);
        s.nested(c.body);
        s.push("}");

        s
    }
}

#[cfg(test)]
mod tests {
    use super::Constructor;
    use cons::Cons;
    use csharp::Csharp;
    use tokens::Tokens;

    #[test]
    fn test_vec() {
        let c = Constructor::new();
        let t: Tokens<Csharp> = (Cons::Borrowed("Foo"), c).into();

        let s = t.to_string();
        let out = s.as_ref().map(|s| s.as_str());
        assert_eq!(Ok("public Foo() {\n}"), out);
    }
}