Line data Source code
1 : /* valacodewriter.vala
2 : *
3 : * Copyright (C) 2006-2014 Jürg Billeter
4 : * Copyright (C) 2006-2008 Raffaele Sandrini
5 : * Copyright (C) 2014 Richard Wiedenhöft
6 : *
7 : * This library is free software; you can redistribute it and/or
8 : * modify it under the terms of the GNU Lesser General Public
9 : * License as published by the Free Software Foundation; either
10 : * version 2.1 of the License, or (at your option) any later version.
11 :
12 : * This library is distributed in the hope that it will be useful,
13 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 : * Lesser General Public License for more details.
16 :
17 : * You should have received a copy of the GNU Lesser General Public
18 : * License along with this library; if not, write to the Free Software
19 : * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 : *
21 : * Author:
22 : * Jürg Billeter <j@bitron.ch>
23 : * Raffaele Sandrini <raffaele@sandrini.ch>
24 : */
25 :
26 :
27 : /**
28 : * Code visitor generating Vala API file for the public interface.
29 : */
30 78 : public class Vala.CodeWriter : CodeVisitor {
31 : static GLib.Regex fix_indent_regex;
32 :
33 78 : private CodeContext context;
34 :
35 78 : FileStream stream;
36 :
37 : int indent;
38 : /* at begin of line */
39 78 : bool bol = true;
40 :
41 78 : Scope current_scope;
42 :
43 : CodeWriterType type;
44 :
45 78 : string? override_header = null;
46 78 : string? header_to_override = null;
47 :
48 156 : public CodeWriter (CodeWriterType type = CodeWriterType.EXTERNAL) {
49 78 : this.type = type;
50 : }
51 :
52 : /**
53 : * Allows overriding of a specific cheader in the output
54 : * @param original original cheader to override
55 : * @param replacement cheader to replace original with
56 : */
57 0 : public void set_cheader_override (string original, string replacement)
58 : {
59 0 : header_to_override = original;
60 0 : override_header = replacement;
61 : }
62 :
63 : /**
64 : * Writes the public interface of the specified code context into the
65 : * specified file.
66 : *
67 : * @param context a code context
68 : * @param filename a relative or absolute filename
69 : */
70 156 : public void write_file (CodeContext context, string filename) {
71 78 : var file_exists = FileUtils.test (filename, FileTest.EXISTS);
72 78 : var temp_filename = "%s.valatmp".printf (filename);
73 78 : this.context = context;
74 :
75 78 : if (file_exists) {
76 28 : stream = FileStream.open (temp_filename, "w");
77 : } else {
78 50 : stream = FileStream.open (filename, "w");
79 : }
80 :
81 78 : if (stream == null) {
82 0 : Report.error (null, "unable to open `%s' for writing", filename);
83 0 : return;
84 : }
85 :
86 156 : var header = context.version_header ?
87 0 : "/* %s generated by %s %s, do not modify. */".printf (Path.get_basename (filename), Environment.get_prgname (), Vala.BUILD_VERSION) :
88 78 : "/* %s generated by %s, do not modify. */".printf (Path.get_basename (filename), Environment.get_prgname ());
89 78 : write_string (header);
90 78 : write_newline ();
91 78 : write_newline ();
92 :
93 3142 : current_scope = context.root.scope;
94 :
95 78 : context.accept (this);
96 :
97 78 : current_scope = null;
98 :
99 78 : stream = null;
100 :
101 78 : if (file_exists) {
102 28 : var changed = true;
103 :
104 28 : try {
105 28 : var old_file = new MappedFile (filename, false);
106 28 : var new_file = new MappedFile (temp_filename, false);
107 28 : var len = old_file.get_length ();
108 28 : if (len == new_file.get_length ()) {
109 28 : if (Memory.cmp (old_file.get_contents (), new_file.get_contents (), len) == 0) {
110 28 : changed = false;
111 : }
112 : }
113 28 : old_file = null;
114 28 : new_file = null;
115 : } catch (FileError e) {
116 : // assume changed if mmap comparison doesn't work
117 : }
118 :
119 28 : if (changed) {
120 0 : FileUtils.rename (temp_filename, filename);
121 : } else {
122 28 : FileUtils.unlink (temp_filename);
123 : }
124 : }
125 :
126 : }
127 :
128 356 : public override void visit_using_directive (UsingDirective ns) {
129 8779 : if (type == CodeWriterType.FAST) {
130 1 : write_string ("using ");
131 :
132 1 : var symbols = new GLib.List<UnresolvedSymbol> ();
133 8818 : var sym = (UnresolvedSymbol) ns.namespace_symbol;
134 2 : symbols.prepend (sym);
135 :
136 1 : while ((sym = sym.inner) != null) {
137 0 : symbols.prepend (sym);
138 : }
139 :
140 1 : write_string (symbols.nth_data (0).name);
141 :
142 1 : for (int i = 1; i < symbols.length (); i++) {
143 0 : write_string (".");
144 0 : write_string (symbols.nth_data (i).name);
145 : }
146 :
147 1 : write_string (";\n");
148 : }
149 : }
150 :
151 517 : public override void visit_namespace (Namespace ns) {
152 420 : if (ns.external_package) {
153 : return;
154 : }
155 :
156 175 : if (ns.name == null) {
157 78 : ns.accept_children (this);
158 78 : return;
159 : }
160 :
161 1014 : var comments = ns.get_comments ();
162 97 : if (context.vapi_comments && comments.size > 0) {
163 0 : bool first = true;
164 0 : SourceReference? first_reference = null;
165 0 : foreach (Comment comment in comments) {
166 0 : if (comment.source_reference.file.file_type == SourceFileType.SOURCE) {
167 0 : if (first) {
168 0 : write_comment (comment);
169 0 : first = false;
170 30 : first_reference = comment.source_reference;
171 : } else {
172 0 : Report.warning (comment.source_reference, "Comment describes namespace, that was already described by another comment.");
173 0 : Report.notice (first_reference, "Previous comment was here.");
174 : }
175 : }
176 : }
177 : }
178 :
179 97 : write_attributes (ns);
180 :
181 97 : write_indent ();
182 97 : write_string ("namespace ");
183 97 : write_identifier (ns.name);
184 97 : write_begin_block ();
185 :
186 194 : current_scope = ns.scope;
187 :
188 97 : visit_sorted (ns.get_namespaces ());
189 97 : visit_sorted (ns.get_classes ());
190 97 : visit_sorted (ns.get_interfaces ());
191 97 : visit_sorted (ns.get_structs ());
192 97 : visit_sorted (ns.get_enums ());
193 97 : visit_sorted (ns.get_error_domains ());
194 97 : visit_sorted (ns.get_delegates ());
195 97 : visit_sorted (ns.get_fields ());
196 97 : visit_sorted (ns.get_constants ());
197 97 : visit_sorted (ns.get_methods ());
198 :
199 194 : current_scope = current_scope.parent_scope;
200 :
201 97 : write_end_block ();
202 97 : write_newline ();
203 : }
204 :
205 7294 : private string get_cheaders (Symbol sym) {
206 7294 : string cheaders = "";
207 14588 : if (type != CodeWriterType.FAST && !sym.external_package) {
208 7294 : cheaders = sym.get_attribute_string ("CCode", "cheader_filename") ?? "";
209 7294 : if (cheaders == "" && sym.parent_symbol != null && sym.parent_symbol != context.root) {
210 1478 : cheaders = get_cheaders (sym.parent_symbol);
211 : }
212 7294 : if (cheaders == "" && sym.source_reference != null && !sym.external_package) {
213 1296 : cheaders = sym.source_reference.file.get_cinclude_filename ();
214 : }
215 :
216 7294 : if (header_to_override != null) {
217 0 : var cheaders_array = cheaders.split (",");
218 0 : for (int i = 0; i < cheaders_array.length; i++) {
219 0 : if (cheaders_array[i] == header_to_override) {
220 0 : cheaders_array[i] = override_header;
221 : }
222 : }
223 0 : cheaders = string.joinv (",", cheaders_array);
224 : }
225 : }
226 : return cheaders;
227 : }
228 :
229 3363 : public override void visit_class (Class cl) {
230 2494 : if (cl.external_package) {
231 : return;
232 : }
233 :
234 877 : if (!check_accessibility (cl)) {
235 : return;
236 : }
237 :
238 869 : if (context.vapi_comments && cl.comment != null) {
239 0 : write_comment (cl.comment);
240 : }
241 :
242 869 : write_attributes (cl);
243 :
244 869 : write_indent ();
245 869 : write_accessibility (cl);
246 869 : if (cl.is_abstract) {
247 34 : write_string ("abstract ");
248 : }
249 869 : if (cl.is_sealed) {
250 4 : write_string ("sealed ");
251 : }
252 869 : write_string ("class ");
253 869 : write_identifier (cl.name);
254 :
255 869 : write_type_parameters (cl.get_type_parameters ());
256 :
257 869 : var base_types = cl.get_base_types ();
258 869 : if (base_types.size > 0) {
259 539 : write_string (" : ");
260 :
261 539 : bool first = true;
262 2571 : foreach (DataType base_type in base_types) {
263 1016 : if (!first) {
264 477 : write_string (", ");
265 : } else {
266 : first = false;
267 : }
268 1016 : write_type (base_type);
269 : }
270 : }
271 869 : write_begin_block ();
272 :
273 1738 : current_scope = cl.scope;
274 :
275 869 : visit_sorted (cl.get_classes ());
276 869 : visit_sorted (cl.get_interfaces ());
277 869 : visit_sorted (cl.get_structs ());
278 869 : visit_sorted (cl.get_enums ());
279 869 : visit_sorted (cl.get_delegates ());
280 869 : visit_sorted (cl.get_fields ());
281 869 : visit_sorted (cl.get_constants ());
282 869 : visit_sorted (cl.get_methods ());
283 869 : visit_sorted (cl.get_properties ());
284 869 : visit_sorted (cl.get_signals ());
285 :
286 869 : if (cl.constructor != null) {
287 3 : cl.constructor.accept (this);
288 : }
289 :
290 869 : if (cl.class_constructor != null) {
291 0 : cl.class_constructor.accept (this);
292 : }
293 :
294 869 : if (cl.static_constructor != null) {
295 1 : cl.static_constructor.accept (this);
296 : }
297 :
298 869 : if (cl.destructor != null) {
299 1 : cl.destructor.accept (this);
300 : }
301 :
302 869 : if (cl.static_destructor != null) {
303 0 : cl.static_destructor.accept (this);
304 : }
305 :
306 869 : if (cl.class_destructor != null) {
307 0 : cl.class_destructor.accept (this);
308 : }
309 :
310 1738 : current_scope = current_scope.parent_scope;
311 :
312 869 : write_end_block ();
313 869 : write_newline ();
314 : }
315 :
316 20746 : void visit_sorted (List<Symbol> symbols) {
317 10401 : if (type != CodeWriterType.EXTERNAL && type != CodeWriterType.VAPIGEN) {
318 : // order of virtual methods matters for fast vapis
319 108 : foreach (Symbol sym in symbols) {
320 26 : sym.accept (this);
321 : }
322 : return;
323 : }
324 :
325 10345 : var sorted_symbols = new ArrayList<Symbol> ();
326 10345 : sorted_symbols.add_all (symbols);
327 57585 : sorted_symbols.sort ((a, b) => strcmp (a.name, b.name));
328 57775 : foreach (Symbol sym in sorted_symbols) {
329 23715 : sym.accept (this);
330 : }
331 : }
332 :
333 2793 : public override void visit_struct (Struct st) {
334 2793 : if (st.external_package) {
335 : return;
336 : }
337 :
338 90 : if (!check_accessibility (st)) {
339 : return;
340 : }
341 :
342 87 : if (context.vapi_comments && st.comment != null) {
343 0 : write_comment (st.comment);
344 : }
345 :
346 87 : write_attributes (st);
347 :
348 87 : write_indent ();
349 87 : write_accessibility (st);
350 87 : write_string ("struct ");
351 87 : write_identifier (st.name);
352 :
353 87 : write_type_parameters (st.get_type_parameters ());
354 :
355 87 : if (st.base_type != null) {
356 6 : write_string (" : ");
357 6 : write_type (st.base_type);
358 : }
359 :
360 87 : write_begin_block ();
361 :
362 174 : current_scope = st.scope;
363 :
364 879 : foreach (Field field in st.get_fields ()) {
365 396 : field.accept (this);
366 : }
367 87 : visit_sorted (st.get_constants ());
368 87 : visit_sorted (st.get_methods ());
369 87 : visit_sorted (st.get_properties ());
370 :
371 174 : current_scope = current_scope.parent_scope;
372 :
373 87 : write_end_block ();
374 87 : write_newline ();
375 : }
376 :
377 195 : public override void visit_interface (Interface iface) {
378 147 : if (iface.external_package) {
379 : return;
380 : }
381 :
382 48 : if (!check_accessibility (iface)) {
383 : return;
384 : }
385 :
386 48 : if (context.vapi_comments && iface.comment != null) {
387 0 : write_comment (iface.comment);
388 : }
389 :
390 48 : write_attributes (iface);
391 :
392 48 : write_indent ();
393 48 : write_accessibility (iface);
394 48 : write_string ("interface ");
395 48 : write_identifier (iface.name);
396 :
397 48 : write_type_parameters (iface.get_type_parameters ());
398 :
399 48 : var prerequisites = iface.get_prerequisites ();
400 48 : if (prerequisites.size > 0) {
401 43 : write_string (" : ");
402 :
403 43 : bool first = true;
404 135 : foreach (DataType prerequisite in prerequisites) {
405 46 : if (!first) {
406 3 : write_string (", ");
407 : } else {
408 : first = false;
409 : }
410 46 : write_type (prerequisite);
411 : }
412 : }
413 48 : write_begin_block ();
414 :
415 96 : current_scope = iface.scope;
416 :
417 48 : visit_sorted (iface.get_classes ());
418 48 : visit_sorted (iface.get_interfaces ());
419 48 : visit_sorted (iface.get_structs ());
420 48 : visit_sorted (iface.get_enums ());
421 48 : visit_sorted (iface.get_delegates ());
422 48 : visit_sorted (iface.get_fields ());
423 48 : visit_sorted (iface.get_constants ());
424 48 : visit_sorted (iface.get_methods ());
425 48 : visit_sorted (iface.get_properties ());
426 48 : visit_sorted (iface.get_signals ());
427 :
428 96 : current_scope = current_scope.parent_scope;
429 :
430 48 : write_end_block ();
431 48 : write_newline ();
432 : }
433 :
434 1003 : public override void visit_enum (Enum en) {
435 1003 : if (en.external_package) {
436 : return;
437 : }
438 :
439 418 : if (!check_accessibility (en)) {
440 : return;
441 : }
442 :
443 413 : if (context.vapi_comments && en.comment != null) {
444 0 : write_comment (en.comment);
445 : }
446 :
447 413 : write_attributes (en);
448 :
449 413 : write_indent ();
450 413 : write_accessibility (en);
451 413 : write_string ("enum ");
452 413 : write_identifier (en.name);
453 413 : write_begin_block ();
454 :
455 413 : bool first = true;
456 5307 : foreach (EnumValue ev in en.get_values ()) {
457 2447 : if (first) {
458 : first = false;
459 : } else {
460 2034 : write_string (",");
461 2034 : write_newline ();
462 : }
463 :
464 2447 : if (context.vapi_comments && ev.comment != null) {
465 0 : write_comment (ev.comment);
466 : }
467 :
468 2447 : write_attributes (ev);
469 :
470 2447 : write_indent ();
471 2447 : write_identifier (ev.name);
472 :
473 2447 : if (type == CodeWriterType.FAST && ev.value != null && ev.value.is_constant ()) {
474 1 : write_string(" = ");
475 1 : ev.value.accept (this);
476 : }
477 : }
478 :
479 413 : if (!first) {
480 413 : if (en.get_methods ().size > 0 || en.get_constants ().size > 0) {
481 7 : write_string (";");
482 : }
483 413 : write_newline ();
484 : }
485 :
486 826 : current_scope = en.scope;
487 439 : foreach (Method m in en.get_methods ()) {
488 13 : m.accept (this);
489 : }
490 413 : foreach (Constant c in en.get_constants ()) {
491 0 : c.accept (this);
492 : }
493 826 : current_scope = current_scope.parent_scope;
494 :
495 413 : write_end_block ();
496 413 : write_newline ();
497 : }
498 :
499 62 : public override void visit_error_domain (ErrorDomain edomain) {
500 62 : if (edomain.external_package) {
501 : return;
502 : }
503 :
504 19 : if (!check_accessibility (edomain)) {
505 : return;
506 : }
507 :
508 18 : if (context.vapi_comments && edomain.comment != null) {
509 0 : write_comment (edomain.comment);
510 : }
511 :
512 18 : write_attributes (edomain);
513 :
514 18 : write_indent ();
515 18 : write_accessibility (edomain);
516 18 : write_string ("errordomain ");
517 18 : write_identifier (edomain.name);
518 18 : write_begin_block ();
519 :
520 18 : bool first = true;
521 126 : foreach (ErrorCode ecode in edomain.get_codes ()) {
522 54 : if (first) {
523 : first = false;
524 : } else {
525 36 : write_string (",");
526 36 : write_newline ();
527 : }
528 :
529 54 : if (context.vapi_comments && ecode.comment != null) {
530 0 : write_comment (ecode.comment);
531 : }
532 :
533 54 : write_attributes (ecode);
534 :
535 54 : write_indent ();
536 54 : write_identifier (ecode.name);
537 : }
538 :
539 18 : if (!first) {
540 18 : if (edomain.get_methods ().size > 0) {
541 0 : write_string (";");
542 : }
543 18 : write_newline ();
544 : }
545 :
546 36 : current_scope = edomain.scope;
547 18 : foreach (Method m in edomain.get_methods ()) {
548 0 : m.accept (this);
549 : }
550 36 : current_scope = current_scope.parent_scope;
551 :
552 18 : write_end_block ();
553 18 : write_newline ();
554 : }
555 :
556 3281 : public override void visit_constant (Constant c) {
557 3281 : if (c.external_package) {
558 : return;
559 : }
560 :
561 2717 : if (!check_accessibility (c)) {
562 : return;
563 : }
564 :
565 2656 : if (context.vapi_comments && c.comment != null) {
566 0 : write_comment (c.comment);
567 : }
568 :
569 2656 : write_attributes (c);
570 :
571 2656 : write_indent ();
572 2656 : write_accessibility (c);
573 :
574 2656 : if (c.hides) {
575 0 : write_string ("new ");
576 : }
577 :
578 2656 : write_string ("const ");
579 :
580 2656 : write_type (c.type_reference);
581 :
582 2656 : write_string (" ");
583 2656 : write_identifier (c.name);
584 2656 : write_type_suffix (c.type_reference);
585 2656 : if (type == CodeWriterType.FAST && c.value != null && c.value.is_constant ()) {
586 1 : write_string(" = ");
587 1 : c.value.accept (this);
588 : }
589 2656 : write_string (";");
590 2656 : write_newline ();
591 : }
592 :
593 3322 : public override void visit_field (Field f) {
594 3322 : if (f.external_package) {
595 : return;
596 : }
597 :
598 3215 : if (!check_accessibility (f)) {
599 : return;
600 : }
601 :
602 2555 : if (context.vapi_comments && f.comment != null) {
603 0 : write_comment (f.comment);
604 : }
605 :
606 2555 : write_attributes (f);
607 :
608 2555 : write_indent ();
609 2555 : write_accessibility (f);
610 :
611 2555 : if (f.hides) {
612 0 : write_string ("new ");
613 : }
614 :
615 2555 : if (f.binding == MemberBinding.STATIC) {
616 85 : write_string ("static ");
617 2470 : } else if (f.binding == MemberBinding.CLASS) {
618 1 : write_string ("class ");
619 : }
620 :
621 2555 : if (f.variable_type.is_weak ()) {
622 1088 : write_string ("weak ");
623 : }
624 :
625 2555 : write_type (f.variable_type);
626 :
627 2555 : write_string (" ");
628 2555 : write_identifier (f.name);
629 2555 : write_type_suffix (f.variable_type);
630 2555 : write_string (";");
631 2555 : write_newline ();
632 : }
633 :
634 9806 : private void write_error_domains (List<DataType> error_domains) {
635 9806 : if (error_domains.size > 0) {
636 227 : write_string (" throws ");
637 :
638 227 : bool first = true;
639 683 : foreach (DataType type in error_domains) {
640 228 : if (!first) {
641 1 : write_string (", ");
642 : } else {
643 : first = false;
644 : }
645 :
646 228 : write_type (type);
647 : }
648 : }
649 : }
650 :
651 10293 : private void write_params (List<Parameter> params) {
652 10293 : write_string ("(");
653 :
654 10293 : int i = 1;
655 35825 : foreach (Parameter param in params) {
656 12806 : if (i > 1) {
657 6194 : write_string (", ");
658 : }
659 :
660 12806 : if (param.ellipsis) {
661 80 : write_string ("...");
662 80 : continue;
663 : }
664 :
665 12726 : write_attributes (param);
666 :
667 12726 : if (param.params_array) {
668 0 : write_string ("params ");
669 : }
670 :
671 12726 : if (param.direction == ParameterDirection.IN) {
672 12126 : if (param.variable_type.value_owned) {
673 58 : write_string ("owned ");
674 : }
675 : } else {
676 600 : if (param.direction == ParameterDirection.REF) {
677 77 : write_string ("ref ");
678 523 : } else if (param.direction == ParameterDirection.OUT) {
679 523 : write_string ("out ");
680 : }
681 600 : if (param.variable_type.is_weak ()) {
682 117 : write_string ("unowned ");
683 : }
684 : }
685 :
686 12726 : write_type (param.variable_type);
687 :
688 12726 : write_string (" ");
689 12726 : write_identifier (param.name);
690 12726 : write_type_suffix (param.variable_type);
691 :
692 12726 : if (param.initializer != null) {
693 198 : write_string (" = ");
694 198 : param.initializer.accept (this);
695 : }
696 :
697 12726 : i++;
698 : }
699 :
700 10293 : write_string (")");
701 : }
702 :
703 745 : public override void visit_delegate (Delegate cb) {
704 551 : if (cb.external_package) {
705 : return;
706 : }
707 :
708 196 : if (!check_accessibility (cb)) {
709 : return;
710 : }
711 :
712 194 : if (context.vapi_comments && cb.comment != null) {
713 0 : write_comment (cb.comment);
714 : }
715 :
716 194 : write_attributes (cb);
717 :
718 194 : write_indent ();
719 :
720 194 : write_accessibility (cb);
721 194 : write_string ("delegate ");
722 :
723 194 : write_return_type (cb.return_type);
724 :
725 194 : write_string (" ");
726 194 : write_identifier (cb.name);
727 :
728 194 : write_type_parameters (cb.get_type_parameters ());
729 :
730 194 : write_string (" ");
731 :
732 194 : write_params (cb.get_parameters ());
733 :
734 194 : var error_types = new ArrayList<DataType> ();
735 194 : cb.get_error_types (error_types);
736 194 : write_error_domains (error_types);
737 :
738 194 : write_string (";");
739 :
740 194 : write_newline ();
741 : }
742 :
743 4 : public override void visit_constructor (Constructor c) {
744 4 : if (type != CodeWriterType.DUMP) {
745 : return;
746 : }
747 :
748 0 : if (context.vapi_comments && c.comment != null) {
749 0 : write_comment (c.comment);
750 : }
751 :
752 0 : write_indent ();
753 0 : if (c.binding == MemberBinding.STATIC) {
754 0 : write_string ("static ");
755 0 : } else if (c.binding == MemberBinding.CLASS) {
756 0 : write_string ("class ");
757 : }
758 0 : write_string ("construct");
759 0 : write_code_block (c.body);
760 0 : write_newline ();
761 : }
762 :
763 1 : public override void visit_destructor (Destructor d) {
764 1 : if (type != CodeWriterType.DUMP) {
765 : return;
766 : }
767 :
768 0 : if (context.vapi_comments && d.comment != null) {
769 0 : write_comment (d.comment);
770 : }
771 :
772 0 : write_indent ();
773 0 : if (d.binding == MemberBinding.STATIC) {
774 0 : write_string ("static ");
775 0 : } else if (d.binding == MemberBinding.CLASS) {
776 0 : write_string ("class ");
777 : }
778 0 : write_string ("~");
779 0 : var datatype = (TypeSymbol) d.parent_symbol;
780 0 : write_identifier (datatype.name);
781 0 : write_string (" () ");
782 0 : write_code_block (d.body);
783 0 : write_newline ();
784 : }
785 :
786 20759 : public override void visit_method (Method m) {
787 11147 : if (m.external_package) {
788 : return;
789 : }
790 :
791 : // don't write interface implementation unless it's an abstract or virtual method
792 10230 : if (!check_accessibility (m) || (m.base_interface_method != null && !m.is_abstract && !m.is_virtual)) {
793 618 : if (type != CodeWriterType.DUMP) {
794 : return;
795 : }
796 : }
797 :
798 9612 : if (context.vapi_comments && m.comment != null) {
799 0 : write_comment (m.comment);
800 : }
801 :
802 9612 : write_attributes (m);
803 :
804 9612 : write_indent ();
805 9612 : write_accessibility (m);
806 :
807 10430 : if (m is CreationMethod) {
808 818 : if (m.coroutine) {
809 1 : write_string ("async ");
810 : }
811 :
812 818 : var datatype = (TypeSymbol) m.parent_symbol;
813 818 : write_identifier (datatype.name);
814 818 : if (m.name != ".new") {
815 193 : write_string (".");
816 193 : write_identifier (m.name);
817 : }
818 818 : write_string (" ");
819 : } else {
820 8794 : if (m.hides) {
821 1 : write_string ("new ");
822 : }
823 :
824 8794 : if (m.binding == MemberBinding.STATIC) {
825 2096 : write_string ("static ");
826 6698 : } else if (m.binding == MemberBinding.CLASS) {
827 7 : write_string ("class ");
828 6691 : } else if (m.is_abstract) {
829 210 : write_string ("abstract ");
830 6481 : } else if (m.is_virtual) {
831 389 : write_string ("virtual ");
832 6092 : } else if (m.overrides) {
833 547 : write_string ("override ");
834 : }
835 :
836 8794 : if (m.coroutine) {
837 21 : write_string ("async ");
838 : }
839 :
840 8794 : write_return_type (m.return_type);
841 8794 : write_string (" ");
842 :
843 8794 : write_identifier (m.name);
844 :
845 8794 : write_type_parameters (m.get_type_parameters ());
846 :
847 8794 : write_string (" ");
848 : }
849 :
850 9612 : write_params (m.get_parameters ());
851 :
852 9612 : var error_types = new ArrayList<DataType> ();
853 9612 : m.get_error_types (error_types);
854 9612 : write_error_domains (error_types);
855 :
856 9612 : write_code_block (m.body);
857 :
858 9612 : write_newline ();
859 : }
860 :
861 842 : public override void visit_creation_method (CreationMethod m) {
862 842 : visit_method (m);
863 : }
864 :
865 1809 : public override void visit_property (Property prop) {
866 1809 : if (!check_accessibility (prop) || (prop.base_interface_property != null && !prop.is_abstract && !prop.is_virtual)) {
867 26 : return;
868 : }
869 :
870 1783 : if (context.vapi_comments && prop.comment != null) {
871 0 : write_comment (prop.comment);
872 : }
873 :
874 1783 : write_attributes (prop);
875 :
876 1783 : write_indent ();
877 1783 : write_accessibility (prop);
878 :
879 1783 : if (prop.hides) {
880 0 : write_string ("new ");
881 : }
882 :
883 1783 : if (prop.binding == MemberBinding.STATIC) {
884 0 : write_string ("static ");
885 1783 : } else if (prop.is_abstract) {
886 11 : write_string ("abstract ");
887 1772 : } else if (prop.is_virtual) {
888 0 : write_string ("virtual ");
889 1772 : } else if (prop.overrides) {
890 20 : write_string ("override ");
891 : }
892 :
893 1783 : if (prop.property_type.is_weak ()) {
894 13 : write_string ("weak ");
895 : }
896 :
897 1783 : write_type (prop.property_type);
898 :
899 1783 : write_string (" ");
900 1783 : write_identifier (prop.name);
901 1783 : write_string (" {");
902 1783 : if (prop.get_accessor != null) {
903 1723 : write_attributes (prop.get_accessor);
904 :
905 1723 : write_property_accessor_accessibility (prop.get_accessor);
906 :
907 1723 : if (prop.get_accessor.value_type.value_owned) {
908 207 : write_string (" owned");
909 : }
910 :
911 1723 : write_string (" get");
912 1723 : write_code_block (prop.get_accessor.body);
913 : }
914 1783 : if (prop.set_accessor != null) {
915 1578 : write_attributes (prop.set_accessor);
916 :
917 1578 : write_property_accessor_accessibility (prop.set_accessor);
918 :
919 1578 : if (prop.set_accessor.value_type.value_owned) {
920 0 : write_string (" owned");
921 : }
922 :
923 1578 : if (prop.set_accessor.writable) {
924 1469 : write_string (" set");
925 : }
926 1578 : if (prop.set_accessor.construction) {
927 194 : write_string (" construct");
928 : }
929 1578 : write_code_block (prop.set_accessor.body);
930 : }
931 1783 : write_string (" }");
932 1783 : write_newline ();
933 : }
934 :
935 487 : public override void visit_signal (Signal sig) {
936 487 : if (!check_accessibility (sig)) {
937 : return;
938 : }
939 :
940 487 : if (context.vapi_comments && sig.comment != null) {
941 0 : write_comment (sig.comment);
942 : }
943 :
944 487 : write_attributes (sig);
945 :
946 487 : write_indent ();
947 487 : write_accessibility (sig);
948 :
949 487 : if (sig.hides) {
950 0 : write_string ("new ");
951 : }
952 :
953 487 : if (sig.is_virtual) {
954 437 : write_string ("virtual ");
955 : }
956 :
957 487 : write_string ("signal ");
958 :
959 487 : write_return_type (sig.return_type);
960 :
961 487 : write_string (" ");
962 487 : write_identifier (sig.name);
963 :
964 487 : write_string (" ");
965 :
966 487 : write_params (sig.get_parameters ());
967 :
968 487 : write_string (";");
969 :
970 487 : write_newline ();
971 : }
972 :
973 0 : public override void visit_block (Block b) {
974 0 : write_begin_block ();
975 :
976 0 : foreach (Statement stmt in b.get_statements ()) {
977 0 : stmt.accept (this);
978 : }
979 :
980 0 : write_end_block ();
981 0 : if (b.parent_node is Block) {
982 0 : write_newline ();
983 : }
984 : }
985 :
986 0 : public override void visit_empty_statement (EmptyStatement stmt) {
987 : }
988 :
989 0 : public override void visit_declaration_statement (DeclarationStatement stmt) {
990 0 : write_indent ();
991 0 : stmt.declaration.accept (this);
992 0 : write_string (";");
993 0 : write_newline ();
994 : }
995 :
996 0 : public override void visit_local_variable (LocalVariable local) {
997 0 : if (local.variable_type.is_weak ()) {
998 0 : write_string ("unowned ");
999 : }
1000 0 : write_type (local.variable_type);
1001 0 : write_string (" ");
1002 0 : write_identifier (local.name);
1003 0 : write_type_suffix (local.variable_type);
1004 0 : if (local.initializer != null) {
1005 0 : write_string (" = ");
1006 0 : local.initializer.accept (this);
1007 : }
1008 : }
1009 :
1010 0 : public override void visit_initializer_list (InitializerList list) {
1011 0 : write_string ("{");
1012 :
1013 0 : bool first = true;
1014 0 : foreach (Expression initializer in list.get_initializers ()) {
1015 0 : if (!first) {
1016 0 : write_string (", ");
1017 : } else {
1018 0 : write_string (" ");
1019 : }
1020 0 : first = false;
1021 0 : initializer.accept (this);
1022 : }
1023 0 : write_string (" }");
1024 : }
1025 :
1026 0 : public override void visit_expression_statement (ExpressionStatement stmt) {
1027 0 : write_indent ();
1028 0 : stmt.expression.accept (this);
1029 0 : write_string (";");
1030 0 : write_newline ();
1031 : }
1032 :
1033 0 : public override void visit_if_statement (IfStatement stmt) {
1034 0 : write_indent ();
1035 0 : write_string ("if (");
1036 0 : stmt.condition.accept (this);
1037 0 : write_string (")");
1038 0 : stmt.true_statement.accept (this);
1039 0 : if (stmt.false_statement != null) {
1040 0 : write_string (" else");
1041 0 : stmt.false_statement.accept (this);
1042 : }
1043 0 : write_newline ();
1044 : }
1045 :
1046 0 : public override void visit_switch_statement (SwitchStatement stmt) {
1047 0 : write_indent ();
1048 0 : write_string ("switch (");
1049 0 : stmt.expression.accept (this);
1050 0 : write_string (") {");
1051 0 : write_newline ();
1052 :
1053 0 : foreach (SwitchSection section in stmt.get_sections ()) {
1054 0 : section.accept (this);
1055 : }
1056 :
1057 0 : write_indent ();
1058 0 : write_string ("}");
1059 0 : write_newline ();
1060 : }
1061 :
1062 0 : public override void visit_switch_section (SwitchSection section) {
1063 0 : foreach (SwitchLabel label in section.get_labels ()) {
1064 0 : label.accept (this);
1065 : }
1066 :
1067 0 : visit_block (section);
1068 : }
1069 :
1070 0 : public override void visit_switch_label (SwitchLabel label) {
1071 0 : if (label.expression != null) {
1072 0 : write_indent ();
1073 0 : write_string ("case ");
1074 0 : label.expression.accept (this);
1075 0 : write_string (":");
1076 0 : write_newline ();
1077 : } else {
1078 0 : write_indent ();
1079 0 : write_string ("default:");
1080 0 : write_newline ();
1081 : }
1082 : }
1083 :
1084 0 : public override void visit_loop_statement (LoopStatement stmt) {
1085 0 : write_indent ();
1086 0 : write_string ("while (");
1087 0 : stmt.condition.accept (this);
1088 0 : write_string (")");
1089 0 : stmt.body.accept (this);
1090 0 : write_newline ();
1091 : }
1092 :
1093 0 : public override void visit_while_statement (WhileStatement stmt) {
1094 0 : write_indent ();
1095 0 : write_string ("while (");
1096 0 : stmt.condition.accept (this);
1097 0 : write_string (")");
1098 0 : stmt.body.accept (this);
1099 0 : write_newline ();
1100 : }
1101 :
1102 0 : public override void visit_do_statement (DoStatement stmt) {
1103 0 : write_indent ();
1104 0 : write_string ("do");
1105 0 : stmt.body.accept (this);
1106 0 : write_string ("while (");
1107 0 : stmt.condition.accept (this);
1108 0 : write_string (");");
1109 0 : write_newline ();
1110 : }
1111 :
1112 0 : public override void visit_for_statement (ForStatement stmt) {
1113 0 : write_indent ();
1114 0 : write_string ("for (");
1115 :
1116 0 : bool first = true;
1117 0 : foreach (Expression initializer in stmt.get_initializer ()) {
1118 0 : if (!first) {
1119 0 : write_string (", ");
1120 : }
1121 0 : first = false;
1122 0 : initializer.accept (this);
1123 : }
1124 0 : write_string ("; ");
1125 :
1126 0 : stmt.condition.accept (this);
1127 0 : write_string ("; ");
1128 :
1129 0 : first = true;
1130 0 : foreach (Expression iterator in stmt.get_iterator ()) {
1131 0 : if (!first) {
1132 0 : write_string (", ");
1133 : }
1134 0 : first = false;
1135 0 : iterator.accept (this);
1136 : }
1137 :
1138 0 : write_string (")");
1139 0 : stmt.body.accept (this);
1140 0 : write_newline ();
1141 : }
1142 :
1143 0 : public override void visit_foreach_statement (ForeachStatement stmt) {
1144 0 : write_indent ();
1145 0 : write_string ("foreach (");
1146 0 : write_type (stmt.type_reference);
1147 0 : write_string (" ");
1148 0 : write_string (stmt.variable_name);
1149 0 : write_string (" in ");
1150 0 : stmt.collection.accept (this);
1151 0 : write_string (")");
1152 0 : stmt.body.accept (this);
1153 : }
1154 :
1155 0 : public override void visit_break_statement (BreakStatement stmt) {
1156 0 : write_indent ();
1157 0 : write_string ("break;");
1158 0 : write_newline ();
1159 : }
1160 :
1161 0 : public override void visit_continue_statement (ContinueStatement stmt) {
1162 0 : write_indent ();
1163 0 : write_string ("continue;");
1164 0 : write_newline ();
1165 : }
1166 :
1167 0 : public override void visit_return_statement (ReturnStatement stmt) {
1168 0 : write_indent ();
1169 0 : write_string ("return");
1170 0 : if (stmt.return_expression != null) {
1171 0 : write_string (" ");
1172 0 : stmt.return_expression.accept (this);
1173 : }
1174 0 : write_string (";");
1175 0 : write_newline ();
1176 : }
1177 :
1178 0 : public override void visit_with_statement (WithStatement stmt) {
1179 0 : write_indent ();
1180 0 : write_string ("with (");
1181 0 : stmt.expression.accept (this);
1182 0 : write_string (")");
1183 0 : stmt.body.accept (this);
1184 0 : write_newline ();
1185 : }
1186 :
1187 0 : public override void visit_yield_statement (YieldStatement y) {
1188 0 : write_indent ();
1189 0 : write_string ("yield");
1190 0 : write_string (";");
1191 0 : write_newline ();
1192 : }
1193 :
1194 0 : public override void visit_throw_statement (ThrowStatement stmt) {
1195 0 : write_indent ();
1196 0 : write_string ("throw");
1197 0 : if (stmt.error_expression != null) {
1198 0 : write_string (" ");
1199 0 : stmt.error_expression.accept (this);
1200 : }
1201 0 : write_string (";");
1202 0 : write_newline ();
1203 : }
1204 :
1205 0 : public override void visit_try_statement (TryStatement stmt) {
1206 0 : write_indent ();
1207 0 : write_string ("try");
1208 0 : stmt.body.accept (this);
1209 0 : foreach (var clause in stmt.get_catch_clauses ()) {
1210 0 : clause.accept (this);
1211 : }
1212 0 : if (stmt.finally_body != null) {
1213 0 : write_string (" finally");
1214 0 : stmt.finally_body.accept (this);
1215 : }
1216 0 : write_newline ();
1217 : }
1218 :
1219 0 : public override void visit_catch_clause (CatchClause clause) {
1220 0 : if (clause.variable_name != null) {
1221 0 : var type_name = clause.error_type == null ? "GLib.Error" : clause.error_type.to_string ();
1222 0 : write_string (" catch (%s %s)".printf (type_name, clause.variable_name));
1223 : } else {
1224 0 : write_string (" catch");
1225 : }
1226 0 : clause.body.accept (this);
1227 : }
1228 :
1229 0 : public override void visit_lock_statement (LockStatement stmt) {
1230 0 : write_indent ();
1231 0 : write_string ("lock (");
1232 0 : stmt.resource.accept (this);
1233 0 : write_string (")");
1234 0 : if (stmt.body == null) {
1235 0 : write_string (";");
1236 : } else {
1237 0 : stmt.body.accept (this);
1238 : }
1239 0 : write_newline ();
1240 : }
1241 :
1242 0 : public override void visit_unlock_statement (UnlockStatement stmt) {
1243 0 : write_indent ();
1244 0 : write_string ("unlock (");
1245 0 : stmt.resource.accept (this);
1246 0 : write_string (");");
1247 0 : write_newline ();
1248 : }
1249 :
1250 0 : public override void visit_delete_statement (DeleteStatement stmt) {
1251 0 : write_indent ();
1252 0 : write_string ("delete ");
1253 0 : stmt.expression.accept (this);
1254 0 : write_string (";");
1255 0 : write_newline ();
1256 : }
1257 :
1258 0 : public override void visit_array_creation_expression (ArrayCreationExpression expr) {
1259 0 : write_string ("new ");
1260 0 : write_type (expr.element_type);
1261 0 : write_string ("[");
1262 :
1263 0 : bool first = true;
1264 0 : foreach (Expression size in expr.get_sizes ()) {
1265 0 : if (!first) {
1266 0 : write_string (", ");
1267 : }
1268 0 : first = false;
1269 :
1270 0 : size.accept (this);
1271 : }
1272 :
1273 0 : write_string ("]");
1274 :
1275 0 : if (expr.initializer_list != null) {
1276 0 : write_string (" ");
1277 0 : expr.initializer_list.accept (this);
1278 : }
1279 : }
1280 :
1281 46 : public override void visit_boolean_literal (BooleanLiteral lit) {
1282 46 : write_string (lit.value.to_string ());
1283 : }
1284 :
1285 0 : public override void visit_character_literal (CharacterLiteral lit) {
1286 0 : write_string (lit.value);
1287 : }
1288 :
1289 26 : public override void visit_integer_literal (IntegerLiteral lit) {
1290 26 : write_string (lit.value);
1291 : }
1292 :
1293 3 : public override void visit_real_literal (RealLiteral lit) {
1294 3 : write_string (lit.value);
1295 : }
1296 :
1297 3 : public override void visit_string_literal (StringLiteral lit) {
1298 3 : write_string (lit.value);
1299 : }
1300 :
1301 124 : public override void visit_null_literal (NullLiteral lit) {
1302 124 : write_string ("null");
1303 : }
1304 :
1305 10 : public override void visit_member_access (MemberAccess expr) {
1306 10 : if (expr.inner != null) {
1307 6 : expr.inner.accept (this);
1308 6 : write_string (".");
1309 : }
1310 10 : write_identifier (expr.member_name);
1311 : }
1312 :
1313 0 : public override void visit_method_call (MethodCall expr) {
1314 0 : if (expr.is_yield_expression) {
1315 0 : write_string ("yield ");
1316 : }
1317 :
1318 0 : expr.call.accept (this);
1319 0 : write_string (" (");
1320 :
1321 0 : bool first = true;
1322 0 : foreach (Expression arg in expr.get_argument_list ()) {
1323 0 : if (!first) {
1324 0 : write_string (", ");
1325 : }
1326 0 : first = false;
1327 :
1328 0 : arg.accept (this);
1329 : }
1330 :
1331 0 : write_string (")");
1332 : }
1333 :
1334 0 : public override void visit_element_access (ElementAccess expr) {
1335 0 : expr.container.accept (this);
1336 0 : write_string ("[");
1337 :
1338 0 : bool first = true;
1339 0 : foreach (Expression index in expr.get_indices ()) {
1340 0 : if (!first) {
1341 0 : write_string (", ");
1342 : }
1343 0 : first = false;
1344 :
1345 0 : index.accept (this);
1346 : }
1347 :
1348 0 : write_string ("]");
1349 : }
1350 :
1351 0 : public override void visit_slice_expression (SliceExpression expr) {
1352 0 : expr.container.accept (this);
1353 0 : write_string ("[");
1354 0 : expr.start.accept (this);
1355 0 : write_string (":");
1356 0 : expr.stop.accept (this);
1357 0 : write_string ("]");
1358 : }
1359 :
1360 0 : public override void visit_base_access (BaseAccess expr) {
1361 0 : write_string ("base");
1362 : }
1363 :
1364 0 : public override void visit_postfix_expression (PostfixExpression expr) {
1365 0 : expr.inner.accept (this);
1366 0 : if (expr.increment) {
1367 0 : write_string ("++");
1368 : } else {
1369 0 : write_string ("--");
1370 : }
1371 : }
1372 :
1373 0 : public override void visit_object_creation_expression (ObjectCreationExpression expr) {
1374 0 : if (expr.is_yield_expression) {
1375 0 : write_string ("yield ");
1376 : }
1377 :
1378 0 : if (!expr.struct_creation) {
1379 0 : write_string ("new ");
1380 : }
1381 :
1382 0 : write_type (expr.type_reference);
1383 :
1384 0 : if (expr.symbol_reference.name != ".new") {
1385 0 : write_string (".");
1386 0 : write_string (expr.symbol_reference.name);
1387 : }
1388 :
1389 0 : write_string (" (");
1390 :
1391 0 : bool first = true;
1392 0 : foreach (Expression arg in expr.get_argument_list ()) {
1393 0 : if (!first) {
1394 0 : write_string (", ");
1395 : }
1396 0 : first = false;
1397 :
1398 0 : arg.accept (this);
1399 : }
1400 :
1401 0 : write_string (")");
1402 : }
1403 :
1404 0 : public override void visit_sizeof_expression (SizeofExpression expr) {
1405 0 : write_string ("sizeof (");
1406 0 : write_type (expr.type_reference);
1407 0 : write_string (")");
1408 : }
1409 :
1410 0 : public override void visit_typeof_expression (TypeofExpression expr) {
1411 0 : write_string ("typeof (");
1412 0 : write_type (expr.type_reference);
1413 0 : write_string (")");
1414 : }
1415 :
1416 0 : public override void visit_unary_expression (UnaryExpression expr) {
1417 0 : write_string (expr.operator.to_string ());
1418 0 : expr.inner.accept (this);
1419 : }
1420 :
1421 0 : public override void visit_cast_expression (CastExpression expr) {
1422 0 : if (expr.is_non_null_cast) {
1423 0 : write_string ("(!) ");
1424 0 : expr.inner.accept (this);
1425 0 : return;
1426 : }
1427 :
1428 0 : if (!expr.is_silent_cast) {
1429 0 : write_string ("(");
1430 0 : write_type (expr.type_reference);
1431 0 : write_string (") ");
1432 : }
1433 :
1434 0 : expr.inner.accept (this);
1435 :
1436 0 : if (expr.is_silent_cast) {
1437 0 : write_string (" as ");
1438 0 : write_type (expr.type_reference);
1439 : }
1440 : }
1441 :
1442 0 : public override void visit_pointer_indirection (PointerIndirection expr) {
1443 0 : write_string ("(*");
1444 0 : expr.inner.accept (this);
1445 0 : write_string (")");
1446 : }
1447 :
1448 0 : public override void visit_addressof_expression (AddressofExpression expr) {
1449 0 : write_string ("(&");
1450 0 : expr.inner.accept (this);
1451 0 : write_string (")");
1452 : }
1453 :
1454 0 : public override void visit_reference_transfer_expression (ReferenceTransferExpression expr) {
1455 0 : write_string ("(owned) ");
1456 0 : expr.inner.accept (this);
1457 : }
1458 :
1459 0 : public override void visit_binary_expression (BinaryExpression expr) {
1460 0 : expr.left.accept (this);
1461 0 : write_string (" ");
1462 0 : write_string (expr.operator.to_string ());
1463 0 : write_string (" ");
1464 0 : expr.right.accept (this);
1465 : }
1466 :
1467 0 : public override void visit_type_check (TypeCheck expr) {
1468 0 : expr.expression.accept (this);
1469 0 : write_string (" is ");
1470 0 : write_type (expr.type_reference);
1471 : }
1472 :
1473 0 : public override void visit_conditional_expression (ConditionalExpression expr) {
1474 0 : expr.condition.accept (this);
1475 0 : write_string ("?");
1476 0 : expr.true_expression.accept (this);
1477 0 : write_string (":");
1478 0 : expr.false_expression.accept (this);
1479 : }
1480 :
1481 0 : public override void visit_lambda_expression (LambdaExpression expr) {
1482 0 : write_string ("(");
1483 0 : var params = expr.get_parameters ();
1484 0 : int i = 1;
1485 0 : foreach (var param in params) {
1486 0 : if (i > 1) {
1487 0 : write_string (", ");
1488 : }
1489 :
1490 0 : if (param.direction == ParameterDirection.REF) {
1491 0 : write_string ("ref ");
1492 0 : } else if (param.direction == ParameterDirection.OUT) {
1493 0 : write_string ("out ");
1494 : }
1495 :
1496 0 : write_identifier (param.name);
1497 :
1498 0 : i++;
1499 : }
1500 0 : write_string (") =>");
1501 0 : if (expr.statement_body != null) {
1502 0 : expr.statement_body.accept (this);
1503 0 : } else if (expr.expression_body != null) {
1504 0 : expr.expression_body.accept (this);
1505 : }
1506 : }
1507 :
1508 0 : public override void visit_assignment (Assignment a) {
1509 0 : a.left.accept (this);
1510 0 : write_string (" = ");
1511 0 : a.right.accept (this);
1512 : }
1513 :
1514 31164 : private void write_indent () {
1515 31164 : if (!bol) {
1516 1 : stream.putc ('\n');
1517 : }
1518 :
1519 31164 : stream.puts (string.nfill (indent, '\t'));
1520 31164 : bol = false;
1521 : }
1522 :
1523 0 : private void write_comment (Comment comment) {
1524 0 : try {
1525 0 : if (fix_indent_regex == null)
1526 0 : fix_indent_regex = new Regex ("\\n[\\t ]*");
1527 : } catch (Error e) {
1528 0 : assert_not_reached ();
1529 : }
1530 :
1531 0 : string replacement = "\n%s ".printf (string.nfill (indent, '\t'));
1532 : string fixed_content;
1533 0 : try {
1534 0 : fixed_content = fix_indent_regex.replace (comment.content, comment.content.length, 0, replacement);
1535 : } catch (Error e) {
1536 0 : assert_not_reached();
1537 : }
1538 :
1539 0 : write_indent ();
1540 0 : write_string ("/*");
1541 0 : write_string (fixed_content);
1542 0 : write_string ("*/");
1543 : }
1544 :
1545 34256 : private void write_identifier (string s) {
1546 34256 : char* id = (char*)s;
1547 34256 : int id_length = (int)s.length;
1548 34256 : if (Vala.Scanner.get_identifier_or_keyword (id, id_length) != Vala.TokenType.IDENTIFIER ||
1549 34136 : s.get_char ().isdigit ()) {
1550 163 : stream.putc ('@');
1551 : }
1552 34256 : write_string (s);
1553 : }
1554 :
1555 9475 : private void write_return_type (DataType type) {
1556 9475 : if (type.is_weak ()) {
1557 1715 : write_string ("unowned ");
1558 : }
1559 :
1560 9475 : write_type (type);
1561 : }
1562 :
1563 30491 : private void write_type (DataType type) {
1564 30491 : write_string (type.to_qualified_string (current_scope));
1565 : }
1566 :
1567 17937 : private void write_type_suffix (DataType type) {
1568 17937 : unowned ArrayType? array_type = type as ArrayType;
1569 335 : if (array_type != null && array_type.fixed_length) {
1570 6 : write_string ("[");
1571 6 : array_type.length.accept (this);
1572 6 : var length_type = array_type.length_type.to_qualified_string (current_scope);
1573 6 : if (length_type != "int") {
1574 0 : write_string (":");
1575 0 : write_string (length_type);
1576 : }
1577 6 : write_string ("]");
1578 : }
1579 : }
1580 :
1581 211182 : private void write_string (string s) {
1582 211182 : stream.puts (s);
1583 211182 : bol = false;
1584 : }
1585 :
1586 31320 : private void write_newline () {
1587 31320 : stream.putc ('\n');
1588 31320 : bol = true;
1589 : }
1590 :
1591 12913 : void write_code_block (Block? block) {
1592 12913 : if (block == null || (type != CodeWriterType.DUMP && type != CodeWriterType.VAPIGEN)) {
1593 12913 : write_string (";");
1594 12913 : return;
1595 : }
1596 :
1597 0 : block.accept (this);
1598 : }
1599 :
1600 1532 : private void write_begin_block () {
1601 1532 : if (!bol) {
1602 1532 : stream.putc (' ');
1603 : } else {
1604 0 : write_indent ();
1605 : }
1606 1532 : stream.putc ('{');
1607 1532 : write_newline ();
1608 1532 : indent++;
1609 : }
1610 :
1611 1532 : private void write_end_block () {
1612 1532 : indent--;
1613 1532 : write_indent ();
1614 1532 : stream.putc ('}');
1615 : }
1616 :
1617 20106 : private bool check_accessibility (Symbol sym) {
1618 20106 : switch (type) {
1619 : case CodeWriterType.EXTERNAL:
1620 : case CodeWriterType.VAPIGEN:
1621 20078 : return sym.access == SymbolAccessibility.PUBLIC ||
1622 1576 : sym.access == SymbolAccessibility.PROTECTED;
1623 :
1624 : case CodeWriterType.INTERNAL:
1625 : case CodeWriterType.FAST:
1626 28 : return sym.access == SymbolAccessibility.INTERNAL ||
1627 28 : sym.access == SymbolAccessibility.PUBLIC ||
1628 4 : sym.access == SymbolAccessibility.PROTECTED;
1629 :
1630 : case CodeWriterType.DUMP:
1631 : return true;
1632 :
1633 : default:
1634 0 : assert_not_reached ();
1635 : }
1636 : }
1637 :
1638 7 : private bool skip_since_tag_check (Symbol sym, string since_val) {
1639 7 : Symbol parent_symbol = sym;
1640 :
1641 28 : while (parent_symbol.parent_symbol != null) {
1642 42 : parent_symbol = parent_symbol.parent_symbol;
1643 21 : if (parent_symbol.version.since == since_val) {
1644 0 : return true;
1645 : }
1646 : }
1647 :
1648 7 : return false;
1649 : }
1650 :
1651 74694 : private void write_attributes (CodeNode node) {
1652 37347 : unowned Symbol? sym = node as Symbol;
1653 :
1654 37347 : var need_cheaders = type != CodeWriterType.FAST && sym != null && !(sym is Namespace) && sym.parent_symbol is Namespace;
1655 :
1656 37347 : var attributes = new GLib.Sequence<Attribute> ();
1657 53285 : foreach (var attr in node.attributes) {
1658 16383 : attributes.insert_sorted (attr, (a, b) => strcmp (a.name, b.name));
1659 : }
1660 37347 : if (need_cheaders && !node.has_attribute ("CCode")) {
1661 480 : attributes.insert_sorted (new Attribute ("CCode"), (a, b) => strcmp (a.name, b.name));
1662 : }
1663 :
1664 37347 : var iter = attributes.get_begin_iter ();
1665 54171 : while (!iter.is_end ()) {
1666 8421 : unowned Attribute attr = iter.get ();
1667 8421 : iter = iter.next ();
1668 :
1669 16923 : var keys = new GLib.Sequence<string> ();
1670 32957 : foreach (var key in attr.args.get_keys ()) {
1671 8093 : if (key == "cheader_filename" && sym is Namespace) {
1672 71 : continue;
1673 : }
1674 16044 : keys.insert_sorted (key, (CompareDataFunc<string>) strcmp);
1675 : }
1676 8421 : if (need_cheaders && attr.name == "CCode" && !attr.has_argument ("cheader_filename")) {
1677 480 : keys.insert_sorted ("cheader_filename", (CompareDataFunc<string>) strcmp);
1678 : }
1679 :
1680 8421 : if (attr.name == "CCode" && keys.get_length () == 0) {
1681 : // only cheader_filename on namespace
1682 18 : continue;
1683 : }
1684 :
1685 8403 : if (attr.name == "Source") {
1686 0 : continue;
1687 : }
1688 :
1689 8421 : if (sym != null && attr.args.size == 1 && attr.name == "Version") {
1690 18 : string since_val = attr.get_string ("since");
1691 18 : if (since_val != null && skip_since_tag_check (sym, since_val)) {
1692 0 : continue;
1693 : }
1694 : }
1695 :
1696 8403 : if (node is PropertyAccessor) {
1697 0 : write_string (" ");
1698 8403 : } else if (node is Parameter) {
1699 : // nothing
1700 : } else {
1701 8282 : write_indent ();
1702 : }
1703 :
1704 8403 : stream.printf ("[%s", attr.name);
1705 8403 : if (keys.get_length () > 0) {
1706 6952 : stream.puts (" (");
1707 :
1708 6952 : unowned string separator = "";
1709 6952 : var arg_iter = keys.get_begin_iter ();
1710 15454 : while (!arg_iter.is_end ()) {
1711 8502 : unowned string arg_name = arg_iter.get ();
1712 8502 : arg_iter = arg_iter.next ();
1713 8502 : if (arg_name == "cheader_filename") {
1714 5816 : stream.printf ("%scheader_filename = \"%s\"", separator, get_cheaders (sym));
1715 : } else {
1716 2686 : stream.printf ("%s%s = %s", separator, arg_name, attr.args.get (arg_name));
1717 : }
1718 : separator = ", ";
1719 : }
1720 :
1721 6952 : stream.puts (")");
1722 : }
1723 8403 : stream.puts ("]");
1724 8403 : if (node is PropertyAccessor) {
1725 : // nothing
1726 8403 : } else if (node is Parameter) {
1727 121 : write_string (" ");
1728 : } else {
1729 8282 : write_newline ();
1730 : }
1731 : }
1732 :
1733 37347 : if (type == CodeWriterType.FAST && !(node is Parameter || node is PropertyAccessor)) {
1734 30 : var source_reference = node.source_reference;
1735 37377 : if (source_reference != null) {
1736 30 : write_indent ();
1737 30 : string filename = source_reference.file.filename;
1738 30 : if (filename.has_prefix (context.basedir)) {
1739 30 : filename = filename.substring (context.basedir.length + 1);
1740 : }
1741 30 : stream.puts ("[Source (filename = \"%s\", line = %i, column = %i)]".printf (filename, source_reference.begin.line, source_reference.begin.column));
1742 30 : write_newline ();
1743 : }
1744 : }
1745 : }
1746 :
1747 18722 : private void write_accessibility (Symbol sym) {
1748 18722 : write_string (sym.access.to_string ());
1749 18722 : write_string (" ");
1750 :
1751 18722 : if (type != CodeWriterType.EXTERNAL && type != CodeWriterType.VAPIGEN && sym.external && !sym.external_package) {
1752 0 : write_string ("extern ");
1753 : }
1754 : }
1755 :
1756 3301 : void write_property_accessor_accessibility (Symbol sym) {
1757 3301 : if (sym.access == SymbolAccessibility.PUBLIC) {
1758 : return;
1759 : }
1760 :
1761 78 : write_string (" ");
1762 78 : write_string (sym.access.to_string ());
1763 : }
1764 :
1765 9992 : void write_type_parameters (List<TypeParameter> type_params) {
1766 9992 : if (type_params.size > 0) {
1767 4 : write_string ("<");
1768 4 : bool first = true;
1769 18 : foreach (TypeParameter type_param in type_params) {
1770 7 : if (first) {
1771 : first = false;
1772 : } else {
1773 3 : write_string (",");
1774 : }
1775 7 : write_identifier (type_param.name);
1776 : }
1777 4 : write_string (">");
1778 : }
1779 : }
1780 : }
1781 :
1782 : public enum Vala.CodeWriterType {
1783 : EXTERNAL,
1784 : INTERNAL,
1785 : FAST,
1786 : DUMP,
1787 : VAPIGEN
1788 : }
|