1/* initializerbuilder.vala
2 *
3 * Copyright (C) 2011  Florian Brosch
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
18 *
19 * Author:
20 * 	Florian Brosch <flo.brosch@gmail.com>
21 */
22
23
24using Valadoc.Content;
25
26private class Valadoc.Api.InitializerBuilder : Vala.CodeVisitor {
27	private Vala.HashMap<Vala.Symbol, Symbol> symbol_map;
28	private SignatureBuilder signature;
29
30	private Symbol? resolve (Vala.Symbol symbol) {
31		return symbol_map.get (symbol);
32	}
33
34	private void write_node (Vala.Symbol vsymbol) {
35		signature.append_symbol (resolve (vsymbol));
36	}
37
38	private void write_type (Vala.DataType vsymbol) {
39		if (vsymbol.type_symbol != null) {
40			write_node (vsymbol.type_symbol);
41		} else {
42			signature.append_literal ("null");
43		}
44
45		var type_args = vsymbol.get_type_arguments ();
46		if (type_args.size > 0) {
47			signature.append ("<");
48			bool first = true;
49			foreach (Vala.DataType type_arg in type_args) {
50				if (!first) {
51					signature.append (",");
52				} else {
53					first = false;
54				}
55				if (!type_arg.value_owned) {
56					signature.append_keyword ("weak");
57				}
58				signature.append (type_arg.to_qualified_string (null));
59			}
60			signature.append (">");
61		}
62
63		if (vsymbol.nullable) {
64			signature.append ("?");
65		}
66	}
67
68	/**
69	 * {@inheritDoc}
70	 */
71	public override void visit_array_creation_expression (Vala.ArrayCreationExpression expr) {
72		signature.append_keyword ("new");
73		write_type (expr.element_type);
74		signature.append ("[", false);
75
76		bool first = true;
77		foreach (Vala.Expression size in expr.get_sizes ()) {
78			if (!first) {
79				signature.append (", ", false);
80			}
81			size.accept (this);
82			first = false;
83		}
84
85		signature.append ("]", false);
86
87		if (expr.initializer_list != null) {
88			signature.append (" ", false);
89			expr.initializer_list.accept (this);
90		}
91	}
92
93	public InitializerBuilder (SignatureBuilder signature, Vala.HashMap<Vala.Symbol, Symbol> symbol_map) {
94		this.symbol_map = symbol_map;
95		this.signature = signature;
96	}
97
98	/**
99	 * {@inheritDoc}
100	 */
101	public override void visit_binary_expression (Vala.BinaryExpression expr) {
102		expr.left.accept (this);
103		if (expr.operator == Vala.BinaryOperator.IN) {
104			signature.append_keyword (Vala.BinaryOperator.IN.to_string ());
105		} else {
106			signature.append (expr.operator.to_string ());
107		}
108		signature.append (" ");
109		expr.right.accept (this);
110	}
111
112	/**
113	 * {@inheritDoc}
114	 */
115	public override void visit_unary_expression (Vala.UnaryExpression expr) {
116		if (expr.operator == Vala.UnaryOperator.REF || expr.operator == Vala.UnaryOperator.OUT) {
117			signature.append_keyword (expr.operator.to_string ());
118		} else {
119			signature.append (expr.operator.to_string ());
120		}
121		expr.inner.accept (this);
122	}
123
124	/**
125	 * {@inheritDoc}
126	 */
127	public override void visit_assignment (Vala.Assignment a) {
128		a.left.accept (this);
129		signature.append (a.operator.to_string ());
130		a.right.accept (this);
131	}
132
133	/**
134	 * {@inheritDoc}
135	 */
136	public override void visit_cast_expression (Vala.CastExpression expr) {
137		if (expr.is_non_null_cast) {
138			signature.append ("(!)");
139			expr.inner.accept (this);
140			return;
141		}
142
143		if (!expr.is_silent_cast) {
144			signature.append ("(", false);
145			write_type (expr.type_reference);
146			signature.append (")", false);
147		}
148
149		expr.inner.accept (this);
150
151		if (expr.is_silent_cast) {
152			signature.append_keyword ("as");
153			write_type (expr.type_reference);
154		}
155	}
156
157	/**
158	 * {@inheritDoc}
159	 */
160	public override void visit_initializer_list (Vala.InitializerList list) {
161		signature.append ("{", false);
162
163		bool first = true;
164		foreach (Vala.Expression initializer in list.get_initializers ()) {
165			if (!first) {
166				signature.append (", ", false);
167			}
168			first = false;
169			initializer.accept (this);
170		}
171
172		signature.append ("}", false);
173	}
174
175	/**
176	 * {@inheritDoc}
177	 */
178	public override void visit_member_access (Vala.MemberAccess expr) {
179		if (expr.symbol_reference != null) {
180			expr.symbol_reference.accept (this);
181		} else {
182			signature.append (expr.member_name);
183		}
184	}
185
186	/**
187	 * {@inheritDoc}
188	 */
189	public override void visit_element_access (Vala.ElementAccess expr) {
190		expr.container.accept (this);
191		signature.append ("[", false);
192
193		bool first = true;
194		foreach (Vala.Expression index in expr.get_indices ()) {
195			if (!first) {
196				signature.append (", ", false);
197			}
198			first = false;
199
200			index.accept (this);
201		}
202
203		signature.append ("]", false);
204	}
205
206	/**
207	 * {@inheritDoc}
208	 */
209	public override void visit_pointer_indirection (Vala.PointerIndirection expr) {
210		signature.append ("*", false);
211		expr.inner.accept (this);
212	}
213
214	/**
215	 * {@inheritDoc}
216	 */
217	public override void visit_addressof_expression (Vala.AddressofExpression expr) {
218		signature.append ("&", false);
219		expr.inner.accept (this);
220	}
221
222	/**
223	 * {@inheritDoc}
224	 */
225	public override void visit_reference_transfer_expression (Vala.ReferenceTransferExpression expr) {
226		signature.append ("(", false).append_keyword ("owned", false).append (")", false);
227		expr.inner.accept (this);
228	}
229
230	/**
231	 * {@inheritDoc}
232	 */
233	public override void visit_type_check (Vala.TypeCheck expr) {
234		expr.expression.accept (this);
235		signature.append_keyword ("is");
236		write_type (expr.type_reference);
237	}
238
239	/**
240	 * {@inheritDoc}
241	 */
242	public override void visit_method_call (Vala.MethodCall expr) {
243		// symbol-name:
244		expr.call.symbol_reference.accept (this);
245
246		// parameters:
247		signature.append (" (", false);
248		bool first = true;
249		foreach (Vala.Expression literal in expr.get_argument_list ()) {
250			if (!first) {
251				signature.append (", ", false);
252			}
253
254			literal.accept (this);
255			first = false;
256		}
257		signature.append (")", false);
258	}
259
260	/**
261	 * {@inheritDoc}
262	 */
263	public override void visit_slice_expression (Vala.SliceExpression expr) {
264		expr.container.accept (this);
265		signature.append ("[", false);
266		expr.start.accept (this);
267		signature.append (":", false);
268		expr.stop.accept (this);
269		signature.append ("]", false);
270	}
271
272	/**
273	 * {@inheritDoc}
274	 */
275	public override void visit_base_access (Vala.BaseAccess expr) {
276		signature.append_keyword ("base", false);
277	}
278
279	/**
280	 * {@inheritDoc}
281	 */
282	public override void visit_postfix_expression (Vala.PostfixExpression expr) {
283		expr.inner.accept (this);
284		if (expr.increment) {
285			signature.append ("++", false);
286		} else {
287			signature.append ("--", false);
288		}
289	}
290
291	/**
292	 * {@inheritDoc}
293	 */
294	public override void visit_object_creation_expression (Vala.ObjectCreationExpression expr) {
295		if (!expr.struct_creation) {
296			signature.append_keyword ("new");
297		}
298
299		signature.append_symbol (resolve (expr.symbol_reference));
300
301		signature.append (" (", false);
302
303		//TODO: rm conditional space
304		bool first = true;
305		foreach (Vala.Expression arg in expr.get_argument_list ()) {
306			if (!first) {
307				signature.append (", ", false);
308			}
309			arg.accept (this);
310			first = false;
311		}
312
313		signature.append (")", false);
314	}
315
316	/**
317	 * {@inheritDoc}
318	 */
319	public override void visit_sizeof_expression (Vala.SizeofExpression expr) {
320		signature.append_keyword ("sizeof", false).append (" (", false);
321		write_type (expr.type_reference);
322		signature.append (")", false);
323	}
324
325	/**
326	 * {@inheritDoc}
327	 */
328	public override void visit_typeof_expression (Vala.TypeofExpression expr) {
329		signature.append_keyword ("typeof", false).append (" (", false);
330		write_type (expr.type_reference);
331		signature.append (")", false);
332	}
333
334	/**
335	 * {@inheritDoc}
336	 */
337	public override void visit_lambda_expression (Vala.LambdaExpression expr) {
338		signature.append ("(", false);
339
340		bool first = true;
341		foreach (Vala.Parameter param in expr.get_parameters ()) {
342			if (!first) {
343				signature.append (", ", false);
344			}
345			signature.append (param.name, false);
346			first = false;
347		}
348
349
350		signature.append (") => {", false);
351		signature.append_highlighted (" [...] ", false);
352		signature.append ("}", false);
353	}
354
355
356
357	/**
358	 * {@inheritDoc}
359	 */
360	public override void visit_boolean_literal (Vala.BooleanLiteral lit) {
361		signature.append_literal (lit.to_string (), false);
362	}
363
364	/**
365	 * {@inheritDoc}
366	 */
367	public override void visit_character_literal (Vala.CharacterLiteral lit) {
368		signature.append_literal (lit.to_string (), false);
369	}
370
371	/**
372	 * {@inheritDoc}
373	 */
374	public override void visit_integer_literal (Vala.IntegerLiteral lit) {
375		signature.append_literal (lit.to_string (), false);
376	}
377
378	/**
379	 * {@inheritDoc}
380	 */
381	public override void visit_real_literal (Vala.RealLiteral lit) {
382		signature.append_literal (lit.to_string (), false);
383	}
384
385	/**
386	 * {@inheritDoc}
387	 */
388	public override void visit_regex_literal (Vala.RegexLiteral lit) {
389		signature.append_literal (lit.to_string (), false);
390	}
391
392	/**
393	 * {@inheritDoc}
394	 */
395	public override void visit_string_literal (Vala.StringLiteral lit) {
396		signature.append_literal (lit.to_string (), false);
397	}
398
399	/**
400	 * {@inheritDoc}
401	 */
402	public override void visit_null_literal (Vala.NullLiteral lit) {
403		signature.append_literal (lit.to_string (), false);
404	}
405
406
407
408	/**
409	 * {@inheritDoc}
410	 */
411	public override void visit_field (Vala.Field field) {
412		write_node (field);
413	}
414
415	/**
416	 * {@inheritDoc}
417	 */
418	public override void visit_constant (Vala.Constant constant) {
419		write_node (constant);
420	}
421
422	/**
423	 * {@inheritDoc}
424	 */
425	public override void visit_enum_value (Vala.EnumValue ev) {
426		write_node (ev);
427	}
428
429	/**
430	 * {@inheritDoc}
431	 */
432	public override void visit_error_code (Vala.ErrorCode ec) {
433		write_node (ec);
434	}
435
436	/**
437	 * {@inheritDoc}
438	 */
439	public override void visit_delegate (Vala.Delegate d) {
440		write_node (d);
441	}
442
443	/**
444	 * {@inheritDoc}
445	 */
446	public override void visit_method (Vala.Method m) {
447		write_node (m);
448	}
449
450	/**
451	 * {@inheritDoc}
452	 */
453	public override void visit_creation_method (Vala.CreationMethod m) {
454		write_node (m);
455	}
456
457	/**
458	 * {@inheritDoc}
459	 */
460	public override void visit_signal (Vala.Signal sig) {
461		write_node (sig);
462	}
463
464	/**
465	 * {@inheritDoc}
466	 */
467	public override void visit_class (Vala.Class c) {
468		write_node (c);
469	}
470
471	/**
472	 * {@inheritDoc}
473	 */
474	public override void visit_struct (Vala.Struct s) {
475		write_node (s);
476	}
477
478	/**
479	 * {@inheritDoc}
480	 */
481	public override void visit_interface (Vala.Interface i) {
482		write_node (i);
483	}
484
485	/**
486	 * {@inheritDoc}
487	 */
488	public override void visit_enum (Vala.Enum en) {
489		write_node (en);
490	}
491
492	/**
493	 * {@inheritDoc}
494	 */
495	public override void visit_error_domain (Vala.ErrorDomain ed) {
496		write_node (ed);
497	}
498
499	/**
500	 * {@inheritDoc}
501	 */
502	public override void visit_property (Vala.Property prop) {
503		write_node (prop);
504	}
505}
506
507