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
use crate::{CodeBuffer, Expression, ExpressionStatement, Literal, Semi, Statement};

/// An element with statements.
pub trait WithStatements: Sized {
    /// Gets the statements.
    fn statements(&self) -> &[Box<dyn Statement>];

    /// Adds the literal statement.
    fn add_literal<L>(&mut self, literal: L)
    where
        L: Into<Literal>,
    {
        self.add_expression_statement(literal.into());
    }

    /// Adds the literal statement.
    fn with_literal<L>(self, literal: L) -> Self
    where
        L: Into<Literal>,
    {
        self.with_expression_statement(literal.into())
    }

    /// Adds the semicolon ended statement.
    fn add_semi<L>(&mut self, literal: L)
    where
        L: Into<Literal>,
    {
        self.add_statement(Semi::from(literal.into()))
    }

    /// Adds the semicolon ended statement.
    fn with_semi<L>(self, literal: L) -> Self
    where
        L: Into<Literal>,
    {
        self.with_statement(Semi::from(literal.into()))
    }

    /// Adds the statement.
    fn with_statement<S>(self, statement: S) -> Self
    where
        S: 'static + Statement,
    {
        self.with_boxed_statement(Box::new(statement))
    }

    /// Adds the statement.
    fn add_statement<S>(&mut self, statement: S)
    where
        S: 'static + Statement,
    {
        self.add_boxed_statement(Box::new(statement));
    }

    /// Adds the boxed statement.
    fn with_boxed_statement(mut self, statement: Box<dyn Statement>) -> Self {
        self.add_boxed_statement(statement);
        self
    }

    /// Adds the boxed statement.
    fn add_boxed_statement(&mut self, statement: Box<dyn Statement>);

    /// Adds the expression as a statement.
    fn with_expression_statement<E>(self, expression: E) -> Self
    where
        E: 'static + Expression,
    {
        self.with_statement(ExpressionStatement::from(expression))
    }

    /// Adds the expression as a statement.
    fn add_expression_statement<E>(&mut self, expression: E)
    where
        E: 'static + Expression,
    {
        self.add_statement(ExpressionStatement::from(expression));
    }

    /// Writes the statements.
    fn write_statements(&self, b: &mut CodeBuffer, level: usize) {
        for statement in self.statements() {
            statement.write(b, level);
        }
    }

    /// Writes the curly-bracketed statement block. (`level` is the outer level)
    fn write_curly_statement_block(&self, b: &mut CodeBuffer, level: usize) {
        b.write("{");
        if self.statements().is_empty() {
            b.write("}");
        } else {
            b.end_line();
            self.write_statements(b, level + 1);
            b.indent(level);
            b.write("}");
        }
    }
}