shadowplay/puppet_pp_printer/
resource.rs

1use crate::puppet_pp_printer::Printer;
2use pretty::RcDoc;
3
4impl<EXTRA> Printer for crate::puppet_lang::resource_collection::SearchExpression<EXTRA> {
5    fn to_doc(&self) -> RcDoc<()> {
6        match &self.value {
7            crate::puppet_lang::resource_collection::ExpressionVariant::Equal((left, right)) => {
8                crate::puppet_pp_printer::expression::infix_to_doc(
9                    RcDoc::text(&left.name),
10                    crate::puppet_pp_printer::term::to_doc(right, false),
11                    "==",
12                )
13            }
14            crate::puppet_lang::resource_collection::ExpressionVariant::NotEqual((left, right)) => {
15                crate::puppet_pp_printer::expression::infix_to_doc(
16                    RcDoc::text(&left.name),
17                    crate::puppet_pp_printer::term::to_doc(right, false),
18                    "!=",
19                )
20            }
21            crate::puppet_lang::resource_collection::ExpressionVariant::And((left, right)) => {
22                crate::puppet_pp_printer::expression::infix_to_doc(
23                    left.to_doc(),
24                    right.to_doc(),
25                    "and",
26                )
27            }
28            crate::puppet_lang::resource_collection::ExpressionVariant::Or((left, right)) => {
29                crate::puppet_pp_printer::expression::infix_to_doc(
30                    left.to_doc(),
31                    right.to_doc(),
32                    "or",
33                )
34            }
35            crate::puppet_lang::resource_collection::ExpressionVariant::Parens(v) => {
36                RcDoc::text("(")
37                    .append(v.to_doc().nest(2))
38                    .append(RcDoc::text(")"))
39                    .group()
40            }
41        }
42    }
43}
44
45impl<EXTRA> Printer for crate::puppet_lang::resource_collection::ResourceCollection<EXTRA> {
46    fn to_doc(&self) -> RcDoc<()> {
47        let search_expression = match &self.search_expression {
48            Some(v) => RcDoc::softline()
49                .append(RcDoc::text("<|"))
50                .append(RcDoc::softline())
51                .append(v.to_doc())
52                .nest(2)
53                .append(RcDoc::softline())
54                .append(RcDoc::text("|>")),
55            None => RcDoc::nil(),
56        };
57
58        crate::puppet_pp_printer::comment::comment_or(
59            &self.comment,
60            RcDoc::hardline(),
61            RcDoc::nil(),
62        )
63        .append(self.type_specification.to_doc())
64        .append(search_expression)
65    }
66}
67
68impl<EXTRA> Printer for crate::puppet_lang::statement::ResourceAttribute<EXTRA> {
69    fn to_doc(&self) -> RcDoc<()> {
70        let value = match &self.value {
71            crate::puppet_lang::statement::ResourceAttributeVariant::Name((k, v)) => {
72                RcDoc::text(&k.data)
73                    .append(RcDoc::column(|w| {
74                        let offset = (w / crate::puppet_pp_printer::ARROW_STEP + 1)
75                            * crate::puppet_pp_printer::ARROW_STEP;
76                        RcDoc::text(format!("{}=>", " ".repeat(offset - w)))
77                    }))
78                    .append(RcDoc::softline())
79                    .append(crate::puppet_pp_printer::expression::to_doc(v, false))
80                    .group()
81                    .nest(2)
82            }
83            crate::puppet_lang::statement::ResourceAttributeVariant::Group(v) => RcDoc::text("*")
84                .append(RcDoc::softline())
85                .append(RcDoc::column(|w| {
86                    let offset = (w / crate::puppet_pp_printer::ARROW_STEP + 1)
87                        * crate::puppet_pp_printer::ARROW_STEP;
88                    RcDoc::text(format!("{}=>", " ".repeat(offset - w)))
89                }))
90                .append(RcDoc::softline())
91                .append(crate::puppet_pp_printer::term::to_doc(v, false))
92                .group()
93                .nest(2),
94        };
95
96        crate::puppet_pp_printer::comment::comment_or(
97            &self.comment,
98            RcDoc::hardline(),
99            RcDoc::nil(),
100        )
101        .append(value)
102    }
103}
104
105impl<EXTRA> Printer for crate::puppet_lang::statement::Resource<EXTRA> {
106    fn to_doc(&self) -> RcDoc<()> {
107        let inner = if self.attributes.value.is_empty() {
108            RcDoc::nil()
109        } else {
110            RcDoc::hardline().append(RcDoc::intersperse(
111                self.attributes.value.iter().map(|elt| elt.to_doc()),
112                RcDoc::text(",").append(RcDoc::hardline()),
113            ))
114        };
115
116        let inner = inner.append(crate::puppet_pp_printer::comment::to_doc(
117            &self.attributes.last_comment,
118        ));
119
120        crate::puppet_pp_printer::expression::to_doc(&self.title, false)
121            .append(RcDoc::text(":"))
122            .append(inner)
123            .nest(2)
124    }
125}
126
127impl<EXTRA> Printer for crate::puppet_lang::statement::ResourceSet<EXTRA> {
128    fn to_doc(&self) -> RcDoc<()> {
129        let is_virtual = if self.is_virtual {
130            RcDoc::text("@")
131        } else {
132            RcDoc::nil()
133        };
134
135        // just one-liner
136        if self.list.value.len() == 1
137            && self.list.value.first().unwrap().attributes.value.is_empty()
138            && self
139                .list
140                .value
141                .first()
142                .unwrap()
143                .attributes
144                .last_comment
145                .is_empty()
146        {
147            return crate::puppet_pp_printer::comment::comment_or(
148                &self.comment,
149                RcDoc::hardline(),
150                RcDoc::nil(),
151            )
152            .append(is_virtual)
153            .append(self.name.to_doc())
154            .append(RcDoc::softline())
155            .append(RcDoc::text("{"))
156            .append(RcDoc::softline())
157            .append(RcDoc::intersperse(
158                self.list.value.iter().map(|elt| elt.to_doc()),
159                RcDoc::nil(),
160            ))
161            .nest(2)
162            .append(RcDoc::softline())
163            .append(RcDoc::text("}"));
164        }
165
166        let inner = RcDoc::intersperse(
167            self.list.value.iter().map(|elt| elt.to_doc()),
168            RcDoc::text(";").append(RcDoc::hardline()),
169        )
170        .append(crate::puppet_pp_printer::comment::to_doc(
171            &self.list.last_comment,
172        ));
173
174        crate::puppet_pp_printer::comment::comment_or(
175            &self.comment,
176            RcDoc::hardline(),
177            RcDoc::nil(),
178        )
179        .append(is_virtual)
180        .append(self.name.to_doc())
181        .append(RcDoc::softline())
182        .append(RcDoc::text("{"))
183        .append(RcDoc::softline())
184        .append(inner)
185        .nest(2)
186        .append(RcDoc::hardline())
187        .append(RcDoc::text("}"))
188    }
189}
190
191impl<EXTRA> Printer for crate::puppet_lang::statement::RelationEltVariant<EXTRA> {
192    fn to_doc(&self) -> RcDoc<()> {
193        match self {
194            crate::puppet_lang::statement::RelationEltVariant::ResourceSet(v) => v.to_doc(),
195            crate::puppet_lang::statement::RelationEltVariant::ResourceCollection(v) => v.to_doc(),
196        }
197    }
198}
199
200impl<EXTRA> Printer for crate::puppet_lang::statement::RelationElt<EXTRA> {
201    fn to_doc(&self) -> RcDoc<()> {
202        if self.data.value.len() == 1 && self.data.last_comment.is_empty() {
203            return self.data.value.first().unwrap().to_doc();
204        }
205
206        let inner = RcDoc::intersperse(
207            self.data
208                .value
209                .iter()
210                .map(|x| x.to_doc().append(RcDoc::text(","))),
211            RcDoc::softline(),
212        )
213        .group()
214        .append(crate::puppet_pp_printer::comment::to_doc(
215            &self.data.last_comment,
216        ));
217
218        RcDoc::text("[")
219            .append(RcDoc::softline())
220            .append(inner)
221            .nest(2)
222            .append(RcDoc::softline())
223            .append(RcDoc::text("]"))
224    }
225}
226
227impl<EXTRA> Printer for crate::puppet_lang::statement::RelationType<EXTRA> {
228    fn to_doc(&self) -> RcDoc<()> {
229        match self.variant {
230            crate::puppet_lang::statement::RelationVariant::ExecOrderRight => RcDoc::text("->"),
231            crate::puppet_lang::statement::RelationVariant::NotifyRight => RcDoc::text("~>"),
232            crate::puppet_lang::statement::RelationVariant::ExecOrderLeft => RcDoc::text("<-"),
233            crate::puppet_lang::statement::RelationVariant::NotifyLeft => RcDoc::text("<~"),
234        }
235    }
236}
237
238impl<EXTRA> Printer for crate::puppet_lang::statement::Relation<EXTRA> {
239    fn to_doc(&self) -> RcDoc<()> {
240        crate::puppet_pp_printer::comment::comment_or(
241            &self.comment,
242            RcDoc::hardline(),
243            RcDoc::nil(),
244        )
245        .append(self.relation_type.to_doc())
246        .append(RcDoc::space())
247        .append(self.relation_to.to_doc())
248    }
249}
250
251impl<EXTRA> Printer for crate::puppet_lang::statement::RelationList<EXTRA> {
252    fn to_doc(&self) -> RcDoc<()> {
253        let head = self.head.to_doc();
254        match &self.tail {
255            None => head,
256            Some(v) => head.append(RcDoc::softline()).append(v.to_doc()),
257        }
258    }
259}
260
261#[test]
262fn test_idempotence_short() {
263    let cases = vec![
264        "Class[ a ] -> Class[ b::c ]",
265        "[ Class[ a ], Class[ b ], ] -> Class[ b::c ]",
266        "Class[ a ] -> ClassB <| (abc != 1) and c == test or (c == notest and abc == 1) |>",
267        "file { '/etc/passwd':\n    ensure                     => file,\n    mode                       => '0644'\n}",
268        "file { '/etc/passwd':\n    ensure                     => file,\n    mode                       => '0644';\n  '/etc/group':\n    ensure                     => file\n}",
269        // keyword test
270        "file { '/etc/passwd':\n    unless                     => true\n}",
271    ];
272
273    for case in cases {
274        let (_, v) = crate::puppet_parser::statement::parse_statement_list(
275            crate::puppet_parser::Span::new(case),
276        )
277        .unwrap();
278
279        let mut w = Vec::new();
280        crate::puppet_pp_printer::statement::statement_block_to_doc(&v, false)
281            .render(100, &mut w)
282            .unwrap();
283        let generated = String::from_utf8(w).unwrap();
284        println!("{} ==>\n------\n{}\n------", case, generated);
285
286        assert_eq!(&generated, case)
287    }
288}