Line data Source code
1 : /* valagirwriter.vala
2 : *
3 : * Copyright (C) 2008-2012 Jürg Billeter
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 : * Jürg Billeter <j@bitron.ch>
21 : */
22 :
23 : using GLib;
24 :
25 : /**
26 : * Code visitor generating .gir file for the public interface.
27 : */
28 15 : public class Vala.GIRWriter : CodeVisitor {
29 3 : private CodeContext context;
30 3 : private string directory;
31 3 : private string gir_namespace;
32 3 : private string gir_version;
33 3 : private string gir_shared_library;
34 :
35 8 : protected virtual string? get_interface_comment (Interface iface) {
36 : return null;
37 : }
38 :
39 8 : protected virtual string? get_struct_comment (Struct st) {
40 : return null;
41 : }
42 :
43 14 : protected virtual string? get_enum_comment (Enum en) {
44 : return null;
45 : }
46 :
47 30 : protected virtual string? get_class_comment (Class c) {
48 : return null;
49 : }
50 :
51 14 : protected virtual string? get_error_code_comment (ErrorCode ecode) {
52 : return null;
53 : }
54 :
55 26 : protected virtual string? get_enum_value_comment (EnumValue ev) {
56 : return null;
57 : }
58 :
59 18 : protected virtual string? get_constant_comment (Constant c) {
60 : return null;
61 : }
62 :
63 6 : protected virtual string? get_error_domain_comment (ErrorDomain edomain) {
64 : return null;
65 : }
66 :
67 34 : protected virtual string? get_field_comment (Field f) {
68 : return null;
69 : }
70 :
71 10 : protected virtual string? get_delegate_comment (Delegate cb) {
72 : return null;
73 : }
74 :
75 272 : protected virtual string? get_method_comment (Method m) {
76 : return null;
77 : }
78 :
79 10 : protected virtual string? get_property_comment (Property prop) {
80 : return null;
81 : }
82 :
83 10 : protected virtual string? get_delegate_return_comment (Delegate cb) {
84 : return null;
85 : }
86 :
87 8 : protected virtual string? get_signal_return_comment (Signal sig) {
88 : return null;
89 : }
90 :
91 272 : protected virtual string? get_method_return_comment (Method m) {
92 : return null;
93 : }
94 :
95 8 : protected virtual string? get_signal_comment (Signal sig) {
96 : return null;
97 : }
98 :
99 358 : protected virtual string? get_parameter_comment (Parameter param) {
100 : return null;
101 : }
102 :
103 6 : StringBuilder buffer = new StringBuilder();
104 3 : FileStream stream;
105 6 : Vala.HashSet<Namespace> unannotated_namespaces = new Vala.HashSet<Namespace>();
106 6 : Vala.HashSet<Namespace> our_namespaces = new Vala.HashSet<Namespace>();
107 6 : Vala.ArrayList<Vala.Symbol> hierarchy = new Vala.ArrayList<Vala.Symbol>();
108 6 : Vala.ArrayList<Vala.CodeNode> deferred = new Vala.ArrayList<Vala.CodeNode>();
109 :
110 : int indent;
111 :
112 3 : private TypeSymbol gobject_type;
113 3 : private TypeSymbol ginitiallyunowned_type;
114 3 : private TypeSymbol gtypeinterface_type;
115 3 : private TypeSymbol gtypeinstance_type;
116 3 : private TypeSymbol gtype_type;
117 :
118 90 : private struct GIRNamespace {
119 533 : public GIRNamespace (string ns, string version) {
120 1599 : this.ns = ns; this.version = version;
121 : }
122 1084 : public string ns;
123 1084 : public string version;
124 1179 : public bool equal (GIRNamespace g) {
125 1179 : return ((ns == g.ns) && (version == g.version));
126 : }
127 :
128 12 : public static GIRNamespace for_symbol (Symbol sym) {
129 24 : while (sym.parent_symbol != null && sym.parent_symbol.name != null) {
130 12 : sym = sym.parent_symbol;
131 : }
132 12 : assert (sym is Namespace);
133 12 : string gir_namespace = sym.get_attribute_string ("CCode", "gir_namespace");
134 12 : string gir_version = sym.get_attribute_string ("CCode", "gir_version");
135 12 : return GIRNamespace (gir_namespace, gir_version);
136 : }
137 : }
138 :
139 6 : private ArrayList<GIRNamespace?> externals = new ArrayList<GIRNamespace?> ((EqualFunc<GIRNamespace>) GIRNamespace.equal);
140 :
141 3 : public void write_includes() {
142 19 : foreach (var i in externals) {
143 9 : if (i.ns != this.gir_namespace) {
144 7 : write_indent_stream ();
145 7 : stream.printf ("<include name=\"%s\" version=\"%s\"/>\n", i.ns, i.version);
146 : }
147 : }
148 : }
149 :
150 :
151 : /**
152 : * Writes the public interface of the specified code context into the
153 : * specified file.
154 : *
155 : * @param context a code context
156 : * @param gir_filename a relative or absolute filename
157 : */
158 6 : public void write_file (CodeContext context, string directory, string gir_filename, string gir_namespace, string gir_version, string package, string? gir_shared_library = null) {
159 3 : this.context = context;
160 6 : this.directory = directory;
161 6 : this.gir_namespace = gir_namespace;
162 6 : this.gir_version = gir_version;
163 6 : this.gir_shared_library = gir_shared_library;
164 :
165 2158 : var root_symbol = context.root;
166 3 : var glib_ns = root_symbol.scope.lookup ("GLib");
167 3 : gobject_type = (TypeSymbol) glib_ns.scope.lookup ("Object");
168 3 : ginitiallyunowned_type = (TypeSymbol) glib_ns.scope.lookup ("InitiallyUnowned");
169 3 : gtypeinterface_type = (TypeSymbol) glib_ns.scope.lookup ("TypeInterface");
170 3 : gtypeinstance_type = (TypeSymbol) glib_ns.scope.lookup ("TypeInstance");
171 3 : gtype_type = (TypeSymbol) glib_ns.scope.lookup ("Type");
172 :
173 3 : write_package (package);
174 :
175 : // Make sure to initialize external files with their gir_namespace/version
176 29 : foreach (var file in context.get_source_files ()) {
177 13 : file.accept (this);
178 : }
179 :
180 3 : context.accept (this);
181 :
182 3 : indent--;
183 3 : buffer.append_printf ("</repository>\n");
184 :
185 3 : string filename = "%s%c%s".printf (directory, Path.DIR_SEPARATOR, gir_filename);
186 3 : var file_exists = FileUtils.test (filename, FileTest.EXISTS);
187 3 : var temp_filename = "%s.valatmp".printf (filename);
188 :
189 3 : if (file_exists) {
190 0 : stream = FileStream.open (temp_filename, "w");
191 : } else {
192 3 : stream = FileStream.open (filename, "w");
193 : }
194 :
195 3 : if (stream == null) {
196 0 : Report.error (null, "unable to open `%s' for writing", filename);
197 0 : this.context = null;
198 0 : return;
199 : }
200 :
201 3 : stream.printf ("<?xml version=\"1.0\"?>\n");
202 :
203 6 : var header = context.version_header ?
204 0 : "<!-- %s generated by %s %s, do not modify. -->".printf (Path.get_basename (filename), Environment.get_prgname (), Vala.BUILD_VERSION) :
205 3 : "<!-- %s generated by %s, do not modify. -->".printf (Path.get_basename (filename), Environment.get_prgname ());
206 3 : stream.printf ("%s\n", header);
207 :
208 3 : stream.printf ("<repository version=\"1.2\"");
209 3 : stream.printf (" xmlns=\"http://www.gtk.org/introspection/core/1.0\"");
210 3 : stream.printf (" xmlns:c=\"http://www.gtk.org/introspection/c/1.0\"");
211 3 : stream.printf (" xmlns:glib=\"http://www.gtk.org/introspection/glib/1.0\"");
212 3 : stream.printf (">\n");
213 3 : indent++;
214 :
215 3 : write_includes();
216 3 : indent--;
217 :
218 3 : stream.puts (buffer.str);
219 3 : stream = null;
220 :
221 3 : if (file_exists) {
222 0 : var changed = true;
223 :
224 0 : try {
225 0 : var old_file = new MappedFile (filename, false);
226 0 : var new_file = new MappedFile (temp_filename, false);
227 0 : var len = old_file.get_length ();
228 0 : if (len == new_file.get_length ()) {
229 0 : if (Memory.cmp (old_file.get_contents (), new_file.get_contents (), len) == 0) {
230 0 : changed = false;
231 : }
232 : }
233 0 : old_file = null;
234 0 : new_file = null;
235 : } catch (FileError e) {
236 : // assume changed if mmap comparison doesn't work
237 : }
238 :
239 0 : if (changed) {
240 0 : FileUtils.rename (temp_filename, filename);
241 : } else {
242 0 : FileUtils.unlink (temp_filename);
243 : }
244 : }
245 :
246 6 : foreach (var ns in unannotated_namespaces) {
247 0 : if (!our_namespaces.contains(ns)) {
248 0 : Report.warning (ns.source_reference, "Namespace `%s' does not have a GIR namespace and version annotation", ns.name);
249 : }
250 : }
251 12 : foreach (var ns in our_namespaces) {
252 3 : ns.source_reference.file.gir_namespace = gir_namespace;
253 3 : ns.source_reference.file.gir_version = gir_version;
254 : }
255 :
256 3 : if (our_namespaces.size == 0) {
257 0 : Report.error (null, "No suitable namespace found to export for GIR");
258 : }
259 :
260 3 : this.context = null;
261 : }
262 :
263 812 : private void write_doc (string? comment, Comment? symbol = null) {
264 812 : if (comment != null) {
265 0 : write_indent ();
266 0 : if (symbol != null) {
267 0 : var filename = symbol.source_reference.file.get_relative_filename();
268 0 : var line = symbol.source_reference.begin.line;
269 0 : var column = symbol.source_reference.begin.column;
270 :
271 0 : buffer.append_printf ("<doc xml:space=\"preserve\" filename=\"%s\" line=\"%d\" column=\"%d\">", filename, line, column);
272 : } else {
273 0 : buffer.append ("<doc xml:space=\"preserve\">");
274 : }
275 0 : buffer.append (comment);
276 0 : buffer.append ("</doc>\n");
277 : }
278 : }
279 :
280 3 : private void write_package (string package) {
281 3 : write_indent ();
282 3 : buffer.append_printf ("<package name=\"%s\"/>\n", package);
283 : }
284 :
285 6 : private void write_c_includes (Namespace ns) {
286 : // Collect C header filenames
287 3 : Set<string> header_filenames = new HashSet<string> (str_hash, str_equal);
288 15 : foreach (unowned string c_header_filename in get_ccode_header_filenames (ns).split (",")) {
289 3 : header_filenames.add (c_header_filename);
290 : }
291 122 : foreach (Symbol symbol in ns.scope.get_symbol_table ().get_values ()) {
292 58 : if (symbol.external_package) {
293 0 : continue;
294 : }
295 290 : foreach (unowned string c_header_filename in get_ccode_header_filenames (symbol).split (",")) {
296 58 : header_filenames.add (c_header_filename);
297 : }
298 : }
299 :
300 : // Generate c:include tags
301 6 : foreach (string c_header_filename in header_filenames) {
302 3 : write_c_include (c_header_filename);
303 : }
304 : }
305 :
306 3 : private void write_c_include (string name) {
307 3 : write_indent ();
308 3 : buffer.append_printf ("<c:include name=\"%s\"/>\n", name);
309 : }
310 :
311 26 : public override void visit_source_file (SourceFile source_file) {
312 26 : if (source_file.file_type != SourceFileType.PACKAGE) {
313 : return;
314 : }
315 :
316 : // Populate gir_namespace/version of source-file like in Namespace.check()
317 18144 : foreach (var node in source_file.get_nodes ()) {
318 9070 : if (node is Namespace && ((Namespace) node).parent_symbol == context.root) {
319 8 : var a = node.get_attribute ("CCode");
320 16 : if (a != null && a.has_argument ("gir_namespace")) {
321 8 : var new_gir = a.get_string ("gir_namespace");
322 8 : var old_gir = source_file.gir_namespace;
323 8 : if (old_gir != null && old_gir != new_gir) {
324 1 : source_file.gir_ambiguous = true;
325 : }
326 8 : source_file.gir_namespace = new_gir;
327 : }
328 8 : if (a != null && a.has_argument ("gir_version")) {
329 8 : source_file.gir_version = a.get_string ("gir_version");
330 : }
331 8 : break;
332 : }
333 : }
334 : }
335 :
336 17 : public override void visit_namespace (Namespace ns) {
337 14 : if (ns.external_package) {
338 : return;
339 : }
340 :
341 8 : if (!is_visibility (ns)) {
342 : return;
343 : }
344 :
345 8 : if (ns.name == null) {
346 : // global namespace
347 3 : hierarchy.insert (0, ns);
348 3 : ns.accept_children (this);
349 3 : hierarchy.remove_at (0);
350 3 : return;
351 : }
352 :
353 5 : if (ns.parent_symbol.name != null) {
354 2 : ns.accept_children (this);
355 2 : return;
356 : }
357 :
358 3 : if (our_namespaces.size > 0) {
359 0 : Report.error (ns.source_reference, "Secondary top-level namespace `%s' is not supported by GIR format", ns.name);
360 0 : return;
361 : }
362 :
363 : // Use given gir_namespace and gir_version for our top-level namespace
364 3 : var old_gir_namespace = ns.get_attribute_string ("CCode", "gir_namespace");
365 3 : var old_gir_version = ns.get_attribute_string ("CCode", "gir_version");
366 3 : if ((old_gir_namespace != null && old_gir_namespace != gir_namespace)
367 3 : || (old_gir_version != null && old_gir_version != gir_version)) {
368 0 : Report.warning (ns.source_reference, "Replace conflicting CCode.gir_* attributes for namespace `%s'", ns.name);
369 : }
370 3 : ns.set_attribute_string ("CCode", "gir_namespace", gir_namespace);
371 3 : ns.set_attribute_string ("CCode", "gir_version", gir_version);
372 :
373 3 : write_c_includes (ns);
374 :
375 3 : write_indent ();
376 3 : buffer.append_printf ("<namespace name=\"%s\" version=\"%s\"", gir_namespace, gir_version);
377 3 : string? cprefix = get_ccode_prefix (ns);
378 3 : if (gir_shared_library != null) {
379 1 : buffer.append_printf(" shared-library=\"%s\"", gir_shared_library);
380 : }
381 3 : if (cprefix != null) {
382 3 : buffer.append_printf (" c:prefix=\"%s\"", cprefix);
383 3 : buffer.append_printf (" c:identifier-prefixes=\"%s\"", cprefix);
384 : }
385 3 : string? csymbol_prefix = get_ccode_lower_case_suffix (ns);
386 3 : if (csymbol_prefix != null) {
387 3 : buffer.append_printf (" c:symbol-prefixes=\"%s\"", csymbol_prefix);
388 : }
389 3 : buffer.append_printf (">\n");
390 3 : indent++;
391 :
392 3 : hierarchy.insert (0, ns);
393 3 : ns.accept_children (this);
394 3 : hierarchy.remove_at (0);
395 :
396 3 : indent--;
397 3 : write_indent ();
398 3 : buffer.append_printf ("</namespace>\n");
399 3 : our_namespaces.add(ns);
400 :
401 3 : visit_deferred ();
402 : }
403 :
404 284 : private void write_symbol_attributes (Symbol symbol) {
405 284 : if (!is_introspectable (symbol)) {
406 33 : buffer.append_printf (" introspectable=\"0\"");
407 : }
408 284 : if (symbol.version.deprecated) {
409 1 : buffer.append_printf (" deprecated=\"1\"");
410 1 : if (symbol.version.deprecated_since != null) {
411 1 : buffer.append_printf (" deprecated-version=\"%s\"", symbol.version.deprecated_since);
412 : }
413 : }
414 284 : if (symbol.version.since != null) {
415 1 : buffer.append_printf (" version=\"%s\"", symbol.version.since);
416 : }
417 : }
418 :
419 25 : public override void visit_class (Class cl) {
420 25 : if (cl.external_package) {
421 : return;
422 : }
423 :
424 16 : if (!check_accessibility (cl)) {
425 : return;
426 : }
427 :
428 16 : if (!has_namespace (cl)) {
429 : return;
430 : }
431 :
432 15 : if (!(hierarchy[0] is Namespace)) {
433 0 : deferred.add (cl);
434 0 : return;
435 : }
436 :
437 15 : if (!cl.is_compact) {
438 13 : string gtype_struct_name = get_gir_name (cl) + "Class";
439 :
440 13 : write_indent ();
441 13 : buffer.append_printf ("<class name=\"%s\"", get_gir_name (cl));
442 13 : write_gtype_attributes (cl, true);
443 13 : buffer.append_printf (" glib:type-struct=\"%s\"", gtype_struct_name);
444 13 : if (cl.base_class == null) {
445 6 : buffer.append_printf (" glib:fundamental=\"1\"");
446 6 : buffer.append_printf (" glib:ref-func=\"%s\"", get_ccode_ref_function (cl));
447 6 : buffer.append_printf (" glib:unref-func=\"%s\"", get_ccode_unref_function (cl));
448 6 : buffer.append_printf (" glib:set-value-func=\"%s\"", get_ccode_set_value_function (cl));
449 6 : buffer.append_printf (" glib:get-value-func=\"%s\"", get_ccode_get_value_function (cl));
450 : } else {
451 7 : buffer.append_printf (" parent=\"%s\"", gi_type_name (cl.base_class));
452 : }
453 13 : if (cl.is_abstract) {
454 1 : buffer.append_printf (" abstract=\"1\"");
455 : }
456 13 : if (cl.is_sealed) {
457 2 : buffer.append_printf (" final=\"1\"");
458 : }
459 13 : write_symbol_attributes (cl);
460 13 : buffer.append_printf (">\n");
461 13 : indent++;
462 :
463 13 : write_doc (get_class_comment (cl), cl.comment);
464 :
465 : // write implemented interfaces
466 29 : foreach (DataType base_type in cl.get_base_types ()) {
467 8 : var object_type = (ObjectType) base_type;
468 8 : if (object_type.type_symbol is Interface) {
469 1 : write_indent ();
470 1 : buffer.append_printf ("<implements name=\"%s\"/>\n", gi_type_name (object_type.type_symbol));
471 : }
472 : }
473 :
474 13 : write_indent ();
475 13 : buffer.append_printf ("<field name=\"parent_instance\" readable=\"0\" private=\"1\">\n");
476 13 : indent++;
477 13 : write_indent ();
478 13 : if (cl.base_class == null) {
479 6 : buffer.append_printf ("<type name=\"%s\" c:type=\"%s\"/>\n", gi_type_name (gtypeinstance_type), get_ccode_name (gtypeinstance_type));
480 : } else {
481 7 : buffer.append_printf ("<type name=\"%s\" c:type=\"%s\"/>\n", gi_type_name (cl.base_class), get_ccode_name (cl.base_class));
482 : }
483 13 : indent--;
484 13 : write_indent ();
485 13 : buffer.append_printf("</field>\n");
486 :
487 13 : if (cl.base_class == null) {
488 6 : write_indent ();
489 6 : buffer.append_printf ("<field name=\"ref_count\">\n");
490 6 : indent++;
491 6 : write_indent ();
492 6 : buffer.append_printf ("<type name=\"gint\" c:type=\"volatile int\"/>\n");
493 6 : indent--;
494 6 : write_indent ();
495 6 : buffer.append_printf("</field>\n");
496 : }
497 :
498 13 : if (!context.abi_stability) {
499 13 : write_indent ();
500 13 : buffer.append_printf ("<field name=\"priv\" readable=\"0\" private=\"1\">\n");
501 13 : indent++;
502 13 : write_indent ();
503 13 : buffer.append_printf ("<type name=\"%sPrivate\" c:type=\"%sPrivate*\"/>\n", get_gir_name (cl), get_ccode_name (cl));
504 13 : indent--;
505 13 : write_indent ();
506 13 : buffer.append_printf("</field>\n");
507 : }
508 :
509 13 : if (cl.base_class != null && cl.base_class.is_subtype_of (gobject_type)) {
510 9 : foreach (var p in cl.get_type_parameters ()) {
511 2 : write_type_parameter (p, "property");
512 : }
513 : }
514 :
515 13 : hierarchy.insert (0, cl);
516 13 : cl.accept_children (this);
517 13 : hierarchy.remove_at (0);
518 :
519 13 : if (context.abi_stability) {
520 0 : write_indent ();
521 0 : buffer.append_printf ("<field name=\"priv\" readable=\"0\" private=\"1\">\n");
522 0 : indent++;
523 0 : write_indent ();
524 0 : buffer.append_printf ("<type name=\"%sPrivate\" c:type=\"%sPrivate*\"/>\n", get_gir_name (cl), get_ccode_name (cl));
525 0 : indent--;
526 0 : write_indent ();
527 0 : buffer.append_printf("</field>\n");
528 : }
529 :
530 13 : indent--;
531 13 : write_indent ();
532 13 : buffer.append_printf ("</class>\n");
533 :
534 13 : write_indent ();
535 13 : buffer.append_printf ("<record name=\"%s\"", gtype_struct_name);
536 13 : write_ctype_attributes (cl, "Class");
537 13 : buffer.append_printf (" glib:is-gtype-struct-for=\"%s\"", get_gir_name (cl));
538 13 : buffer.append_printf (">\n");
539 13 : indent++;
540 :
541 13 : write_indent ();
542 13 : buffer.append_printf ("<field name=\"parent_class\" readable=\"0\" private=\"1\">\n");
543 13 : indent++;
544 13 : write_indent ();
545 13 : if (cl.base_class == null) {
546 : //FIXME GObject.TypeClass vs GType
547 6 : buffer.append_printf ("<type name=\"%sClass\" c:type=\"%sClass\"/>\n", "GObject.Type", get_ccode_name (gtype_type));
548 : } else {
549 7 : buffer.append_printf ("<type name=\"%sClass\" c:type=\"%sClass\"/>\n", gi_type_name (cl.base_class), get_ccode_name (cl.base_class));
550 : }
551 13 : indent--;
552 13 : write_indent ();
553 13 : buffer.append_printf ("</field>\n");
554 :
555 153 : foreach (Method m in cl.get_methods ()) {
556 70 : if (m.is_abstract || m.is_virtual) {
557 23 : if (m.coroutine) {
558 5 : string finish_name = m.name;
559 5 : if (finish_name.has_suffix ("_async")) {
560 3 : finish_name = finish_name.substring (0, finish_name.length - "_async".length);
561 : }
562 5 : finish_name += "_finish";
563 :
564 5 : write_indent ();
565 5 : buffer.append_printf("<field name=\"%s\"", m.name);
566 5 : write_symbol_attributes (m);
567 5 : buffer.append_printf (">\n");
568 5 : indent++;
569 5 : do_write_signature (m, "callback", true, m.name, get_ccode_name (m), m.get_async_begin_parameters (), new VoidType (), false, false, false);
570 5 : indent--;
571 5 : write_indent ();
572 5 : buffer.append_printf ("</field>\n");
573 :
574 5 : write_indent ();
575 5 : buffer.append_printf("<field name=\"%s\"", finish_name);
576 5 : write_symbol_attributes (m);
577 5 : buffer.append_printf (">\n");
578 5 : indent++;
579 5 : do_write_signature (m, "callback", true, finish_name, get_ccode_finish_name (m), m.get_async_end_parameters (), m.return_type, m.tree_can_fail, false, false);
580 5 : indent--;
581 5 : write_indent ();
582 5 : buffer.append_printf ("</field>\n");
583 : } else {
584 13 : write_indent ();
585 13 : buffer.append_printf("<field name=\"%s\"", m.name);
586 13 : write_symbol_attributes (m);
587 13 : buffer.append_printf (">\n");
588 13 : indent++;
589 13 : do_write_signature (m, "callback", true, m.name, get_ccode_name (m), m.get_parameters (), m.return_type, m.tree_can_fail, false, false);
590 13 : indent--;
591 13 : write_indent ();
592 13 : buffer.append_printf ("</field>\n");
593 : }
594 : }
595 : }
596 :
597 19 : foreach (Signal sig in cl.get_signals ()) {
598 3 : if (sig.default_handler != null) {
599 1 : write_indent ();
600 1 : buffer.append_printf ("<field name=\"%s\"", get_ccode_lower_case_name (sig));
601 1 : write_symbol_attributes (sig);
602 1 : buffer.append_printf (">\n");
603 1 : indent++;
604 1 : write_signature (sig.default_handler, "callback", false, true, false);
605 1 : indent--;
606 1 : write_indent ();
607 1 : buffer.append_printf ("</field>\n");
608 : }
609 : }
610 :
611 13 : indent--;
612 13 : write_indent ();
613 13 : buffer.append_printf ("</record>\n");
614 :
615 13 : write_indent ();
616 13 : buffer.append_printf ("<record name=\"%sPrivate\" c:type=\"%sPrivate\" disguised=\"1\"/>\n", get_gir_name (cl), get_ccode_name (cl));
617 : } else {
618 2 : write_indent ();
619 2 : buffer.append_printf ("<record name=\"%s\"", get_gir_name (cl));
620 2 : write_ctype_attributes (cl);
621 2 : write_symbol_attributes (cl);
622 2 : buffer.append_printf (">\n");
623 2 : indent++;
624 :
625 2 : write_doc (get_class_comment (cl), cl.comment);
626 :
627 2 : hierarchy.insert (0, cl);
628 2 : cl.accept_children (this);
629 2 : hierarchy.remove_at (0);
630 :
631 2 : indent--;
632 2 : write_indent ();
633 2 : buffer.append_printf ("</record>\n");
634 : }
635 :
636 15 : visit_deferred ();
637 : }
638 :
639 104 : public override void visit_struct (Struct st) {
640 104 : if (st.external_package) {
641 : return;
642 : }
643 :
644 5 : if (!check_accessibility (st)) {
645 : return;
646 : }
647 :
648 5 : if (!has_namespace (st)) {
649 : return;
650 : }
651 :
652 4 : if (!(hierarchy[0] is Namespace)) {
653 0 : deferred.add (st);
654 0 : return;
655 : }
656 :
657 4 : write_indent ();
658 4 : buffer.append_printf ("<record name=\"%s\"", get_gir_name (st));
659 4 : if (get_ccode_has_type_id (st)) {
660 3 : write_gtype_attributes (st, true);
661 : } else {
662 1 : write_ctype_attributes (st, "", true);
663 : }
664 4 : write_symbol_attributes (st);
665 4 : buffer.append_printf (">\n");
666 4 : indent++;
667 :
668 4 : write_doc (get_struct_comment (st), st.comment);
669 :
670 4 : hierarchy.insert (0, st);
671 4 : st.accept_children (this);
672 4 : hierarchy.remove_at (0);
673 :
674 4 : indent--;
675 4 : write_indent ();
676 4 : buffer.append_printf ("</record>\n");
677 :
678 4 : visit_deferred ();
679 : }
680 :
681 9 : public override void visit_interface (Interface iface) {
682 5 : if (iface.external_package) {
683 : return;
684 : }
685 :
686 5 : if (!check_accessibility (iface)) {
687 : return;
688 : }
689 :
690 5 : if (!has_namespace (iface)) {
691 : return;
692 : }
693 :
694 4 : if (!(hierarchy[0] is Namespace)) {
695 0 : deferred.add (iface);
696 0 : return;
697 : }
698 :
699 4 : string gtype_struct_name = get_gir_name (iface) + "Iface";
700 :
701 4 : write_indent ();
702 4 : buffer.append_printf ("<interface name=\"%s\"", get_gir_name (iface));
703 4 : write_gtype_attributes (iface, true);
704 4 : buffer.append_printf (" glib:type-struct=\"%s\"", gtype_struct_name);
705 4 : write_symbol_attributes (iface);
706 4 : buffer.append_printf (">\n");
707 4 : indent++;
708 :
709 4 : write_doc (get_interface_comment (iface), iface.comment);
710 :
711 : // write prerequisites
712 4 : if (iface.get_prerequisites ().size > 0) {
713 9 : foreach (DataType base_type in iface.get_prerequisites ()) {
714 3 : write_indent ();
715 3 : buffer.append_printf ("<prerequisite name=\"%s\"/>\n", gi_type_name (((ObjectType) base_type).type_symbol));
716 : }
717 : }
718 :
719 4 : hierarchy.insert (0, iface);
720 4 : iface.accept_children (this);
721 4 : hierarchy.remove_at (0);
722 :
723 4 : indent--;
724 4 : write_indent ();
725 4 : buffer.append_printf ("</interface>\n");
726 :
727 4 : write_indent ();
728 4 : buffer.append_printf ("<record name=\"%s\"", gtype_struct_name);
729 4 : write_ctype_attributes (iface, "Iface");
730 4 : buffer.append_printf (" glib:is-gtype-struct-for=\"%s\"", get_gir_name (iface));
731 4 : buffer.append_printf (">\n");
732 4 : indent++;
733 :
734 4 : write_indent ();
735 4 : buffer.append_printf ("<field name=\"parent_iface\" readable=\"0\" private=\"1\">\n");
736 4 : indent++;
737 4 : write_indent ();
738 4 : buffer.append_printf ("<type name=\"%s\" c:type=\"%s\"/>\n", gi_type_name (gtypeinterface_type), get_ccode_name (gtypeinterface_type));
739 4 : indent--;
740 4 : write_indent ();
741 4 : buffer.append_printf ("</field>\n");
742 :
743 22 : foreach (Method m in iface.get_methods ()) {
744 9 : if (m.is_abstract || m.is_virtual) {
745 11 : if (m.coroutine) {
746 3 : string finish_name = m.name;
747 3 : if (finish_name.has_suffix ("_async")) {
748 2 : finish_name = finish_name.substring (0, finish_name.length - "_async".length);
749 : }
750 3 : finish_name += "_finish";
751 :
752 3 : write_indent ();
753 3 : buffer.append_printf("<field name=\"%s\"", m.name);
754 3 : write_symbol_attributes (m);
755 3 : buffer.append_printf (">\n");
756 3 : indent++;
757 3 : do_write_signature (m, "callback", true, m.name, get_ccode_name (m), m.get_async_begin_parameters (), new VoidType (), false, false, false);
758 3 : indent--;
759 3 : write_indent ();
760 3 : buffer.append_printf ("</field>\n");
761 :
762 3 : write_indent ();
763 3 : buffer.append_printf("<field name=\"%s\"", finish_name);
764 3 : write_symbol_attributes (m);
765 3 : buffer.append_printf (">\n");
766 3 : indent++;
767 3 : do_write_signature (m, "callback", true, finish_name, get_ccode_finish_name (m), m.get_async_end_parameters (), m.return_type, m.tree_can_fail, false, false);
768 3 : indent--;
769 3 : write_indent ();
770 3 : buffer.append_printf ("</field>\n");
771 : } else {
772 5 : write_indent ();
773 5 : buffer.append_printf("<field name=\"%s\"", m.name);
774 5 : write_symbol_attributes (m);
775 5 : buffer.append_printf (">\n");
776 5 : indent++;
777 5 : do_write_signature (m, "callback", true, m.name, get_ccode_name (m), m.get_parameters (), m.return_type, m.tree_can_fail, false, false);
778 5 : indent--;
779 5 : write_indent ();
780 5 : buffer.append_printf ("</field>\n");
781 : }
782 : }
783 : }
784 :
785 8 : foreach (var prop in iface.get_properties ()) {
786 2 : if (prop.is_abstract || prop.is_virtual) {
787 4 : if (prop.get_accessor != null && prop.get_accessor.readable) {
788 2 : var m = prop.get_accessor.get_method ();
789 2 : write_indent ();
790 2 : buffer.append_printf("<field name=\"%s\"", m.name);
791 2 : write_symbol_attributes (m);
792 2 : buffer.append_printf (">\n");
793 2 : indent++;
794 2 : do_write_signature (m, "callback", true, m.name, get_ccode_name (m), m.get_parameters (), m.return_type, m.tree_can_fail, false, false);
795 2 : indent--;
796 2 : write_indent ();
797 2 : buffer.append_printf ("</field>\n");
798 : }
799 :
800 4 : if (prop.set_accessor != null && prop.set_accessor.writable) {
801 2 : var m = prop.set_accessor.get_method ();
802 2 : write_indent ();
803 2 : buffer.append_printf("<field name=\"%s\"", m.name);
804 2 : write_symbol_attributes (m);
805 2 : buffer.append_printf (">\n");
806 2 : indent++;
807 2 : do_write_signature (m, "callback", true, m.name, get_ccode_name (m), m.get_parameters (), m.return_type, m.tree_can_fail, false, false);
808 2 : indent--;
809 2 : write_indent ();
810 2 : buffer.append_printf ("</field>\n");
811 : }
812 : }
813 : }
814 :
815 4 : indent--;
816 4 : write_indent ();
817 4 : buffer.append_printf ("</record>\n");
818 :
819 4 : visit_deferred ();
820 : }
821 :
822 72 : private void visit_deferred () {
823 446 : var nodes = this.deferred;
824 36 : this.deferred = new Vala.ArrayList<Vala.CodeNode>();
825 :
826 36 : foreach (var node in nodes) {
827 0 : node.accept (this);
828 : }
829 : }
830 :
831 107 : private string? get_gir_name (Symbol symbol) {
832 107 : string? gir_name = null;
833 107 : var h0 = hierarchy[0];
834 :
835 565 : for (Symbol? cur_sym = symbol ; cur_sym != null ; cur_sym = cur_sym.parent_symbol) {
836 224 : if (cur_sym == h0) {
837 : break;
838 : }
839 :
840 117 : var cur_name = cur_sym.get_attribute_string ("GIR", "name");
841 117 : if (cur_name == null) {
842 204 : cur_name = cur_sym.name;
843 : }
844 117 : gir_name = cur_name.concat (gir_name);
845 : }
846 :
847 107 : return gir_name;
848 : }
849 :
850 15 : public override void visit_enum (Enum en) {
851 8 : if (en.external_package) {
852 : return;
853 : }
854 :
855 8 : if (!check_accessibility (en)) {
856 : return;
857 : }
858 :
859 8 : if (!has_namespace (en)) {
860 : return;
861 : }
862 :
863 7 : if (!(hierarchy[0] is Namespace)) {
864 0 : deferred.add (en);
865 0 : return;
866 : }
867 :
868 7 : string element_name = (en.is_flags) ? "bitfield" : "enumeration";
869 :
870 7 : write_indent ();
871 7 : buffer.append_printf ("<%s name=\"%s\"", element_name, get_gir_name (en));
872 7 : if (get_ccode_has_type_id (en)) {
873 6 : write_gtype_attributes (en);
874 : } else {
875 1 : write_ctype_attributes (en);
876 : }
877 7 : write_symbol_attributes (en);
878 7 : buffer.append_printf (">\n");
879 7 : indent++;
880 :
881 7 : write_doc (get_enum_comment (en), en.comment);
882 :
883 7 : enum_value = 0;
884 7 : hierarchy.insert (0, en);
885 7 : en.accept_children (this);
886 7 : hierarchy.remove_at (0);
887 :
888 7 : indent--;
889 7 : write_indent ();
890 7 : buffer.append_printf ("</%s>\n", element_name);
891 :
892 7 : visit_deferred ();
893 : }
894 :
895 : private int enum_value;
896 :
897 26 : public override void visit_enum_value (EnumValue ev) {
898 13 : write_indent ();
899 13 : var en = (Enum) hierarchy[0];
900 13 : buffer.append_printf ("<member name=\"%s\" c:identifier=\"%s\"", ev.name.ascii_down (), get_ccode_name (ev));
901 15 : if (ev.value != null) {
902 2 : string value = literal_expression_to_value_string (ev.value);
903 2 : buffer.append_printf (" value=\"%s\"", value);
904 : } else {
905 11 : if (en.is_flags) {
906 5 : buffer.append_printf (" value=\"%d\"", 1 << enum_value++);
907 : } else {
908 6 : buffer.append_printf (" value=\"%d\"", enum_value++);
909 : }
910 : }
911 13 : write_symbol_attributes (ev);
912 :
913 13 : string? comment = get_enum_value_comment (ev);
914 13 : if (comment == null) {
915 13 : buffer.append_printf ("/>\n");
916 : } else {
917 0 : buffer.append_printf (">\n");
918 0 : indent++;
919 :
920 0 : write_doc (comment, ev.comment);
921 :
922 0 : indent--;
923 0 : write_indent ();
924 0 : buffer.append_printf ("</member>\n");
925 : }
926 : }
927 :
928 4 : public override void visit_error_domain (ErrorDomain edomain) {
929 4 : if (edomain.external_package) {
930 : return;
931 : }
932 :
933 4 : if (!check_accessibility (edomain)) {
934 : return;
935 : }
936 :
937 4 : if (!has_namespace (edomain)) {
938 : return;
939 : }
940 :
941 3 : write_indent ();
942 3 : buffer.append_printf ("<enumeration name=\"%s\"", get_gir_name (edomain));
943 3 : if (get_ccode_has_type_id (edomain)) {
944 2 : write_gtype_attributes (edomain);
945 : } else {
946 1 : write_ctype_attributes (edomain);
947 : }
948 3 : buffer.append_printf (" glib:error-domain=\"%s\"", get_ccode_quark_name (edomain));
949 3 : write_symbol_attributes (edomain);
950 3 : buffer.append_printf (">\n");
951 3 : indent++;
952 :
953 3 : write_doc (get_error_domain_comment (edomain), edomain.comment);
954 :
955 3 : enum_value = 0;
956 3 : hierarchy.insert (0, edomain);
957 3 : edomain.accept_children (this);
958 3 : hierarchy.remove_at (0);
959 :
960 3 : indent--;
961 3 : write_indent ();
962 3 : buffer.append_printf ("</enumeration>\n");
963 :
964 3 : visit_deferred ();
965 : }
966 :
967 14 : public override void visit_error_code (ErrorCode ecode) {
968 7 : write_indent ();
969 7 : buffer.append_printf ("<member name=\"%s\" c:identifier=\"%s\"", ecode.name.ascii_down (), get_ccode_name (ecode));
970 9 : if (ecode.value != null) {
971 2 : string value = literal_expression_to_value_string (ecode.value);
972 2 : buffer.append_printf (" value=\"%s\"", value);
973 : } else {
974 5 : buffer.append_printf (" value=\"%d\"", enum_value++);
975 : }
976 7 : write_symbol_attributes (ecode);
977 :
978 7 : string? comment = get_error_code_comment (ecode);
979 7 : if (comment == null) {
980 7 : buffer.append_printf ("/>\n");
981 : } else {
982 0 : buffer.append_printf (">\n");
983 0 : indent++;
984 :
985 0 : write_doc (comment, ecode.comment);
986 :
987 0 : indent--;
988 0 : write_indent ();
989 0 : buffer.append_printf ("</member>\n");
990 : }
991 : }
992 :
993 25 : public override void visit_constant (Constant c) {
994 16 : if (c.external_package) {
995 : return;
996 : }
997 :
998 10 : if (!check_accessibility (c)) {
999 : return;
1000 : }
1001 :
1002 10 : if (!has_namespace (c)) {
1003 : return;
1004 : }
1005 :
1006 : //TODO Add better constant evaluation
1007 9 : var initializer = c.value;
1008 9 : string value = literal_expression_to_value_string (initializer);
1009 :
1010 9 : write_indent ();
1011 9 : buffer.append_printf ("<constant name=\"%s\" c:identifier=\"%s\"", get_gir_name (c), get_ccode_name (c));
1012 9 : buffer.append_printf (" value=\"%s\"", value);
1013 9 : write_symbol_attributes (c);
1014 9 : buffer.append_printf (">\n");
1015 9 : indent++;
1016 :
1017 9 : write_doc (get_constant_comment (c), c.comment);
1018 :
1019 9 : write_type (initializer.value_type);
1020 :
1021 9 : indent--;
1022 9 : write_indent ();
1023 9 : buffer.append_printf ("</constant>\n");
1024 : }
1025 :
1026 31 : public override void visit_field (Field f) {
1027 31 : if (f.external_package) {
1028 : return;
1029 : }
1030 :
1031 28 : if (!check_accessibility (f)) {
1032 : return;
1033 : }
1034 :
1035 18 : if (!has_namespace (f)) {
1036 : return;
1037 : }
1038 :
1039 17 : write_indent ();
1040 17 : buffer.append_printf ("<field name=\"%s\" writable=\"1\"", get_ccode_name (f));
1041 17 : if (f.variable_type.nullable) {
1042 1 : buffer.append_printf (" nullable=\"1\"");
1043 : }
1044 17 : write_symbol_attributes (f);
1045 17 : buffer.append_printf (">\n");
1046 17 : indent++;
1047 :
1048 17 : write_doc (get_field_comment (f), f.comment);
1049 :
1050 17 : write_type (f.variable_type);
1051 :
1052 17 : indent--;
1053 17 : write_indent ();
1054 17 : buffer.append_printf ("</field>\n");
1055 :
1056 19 : if (f.variable_type is ArrayType && get_ccode_array_length (f)) {
1057 2 : var array_type = (ArrayType) f.variable_type;
1058 2 : if (!array_type.fixed_length) {
1059 2 : for (var i = 0; i < array_type.rank; i++) {
1060 1 : write_indent ();
1061 1 : buffer.append_printf ("<field name=\"%s_length%i\"", get_ccode_name (f), i + 1);
1062 1 : write_symbol_attributes (f);
1063 1 : buffer.append_printf (">\n");
1064 1 : indent++;
1065 1 : write_type (array_type.length_type);
1066 1 : indent--;
1067 1 : write_indent ();
1068 1 : buffer.append_printf ("</field>\n");
1069 : }
1070 : }
1071 16 : } else if (f.variable_type is DelegateType) {
1072 1 : var deleg_type = (DelegateType) f.variable_type;
1073 1 : if (deleg_type.delegate_symbol.has_target) {
1074 1 : write_indent ();
1075 1 : buffer.append_printf ("<field name=\"%s\"", get_ccode_delegate_target_name (f));
1076 1 : write_symbol_attributes (f);
1077 1 : buffer.append_printf (">\n");
1078 1 : indent++;
1079 1 : write_indent ();
1080 1 : buffer.append_printf ("<type name=\"gpointer\" c:type=\"gpointer\"/>\n");
1081 1 : indent--;
1082 1 : write_indent ();
1083 1 : buffer.append_printf ("</field>\n");
1084 1 : if (deleg_type.is_disposable ()) {
1085 1 : write_indent ();
1086 1 : buffer.append_printf ("<field name=\"%s\"", get_ccode_delegate_target_destroy_notify_name (f));
1087 1 : write_symbol_attributes (f);
1088 1 : buffer.append_printf (">\n");
1089 1 : indent++;
1090 1 : write_indent ();
1091 1 : buffer.append_printf ("<type name=\"GLib.DestroyNotify\" c:type=\"GDestroyNotify\"/>\n");
1092 1 : indent--;
1093 1 : write_indent ();
1094 1 : buffer.append_printf ("</field>\n");
1095 : }
1096 : }
1097 : }
1098 : }
1099 :
1100 343 : private void write_implicit_params (DataType? type, ref int index, bool has_array_length, string? name, ParameterDirection direction) {
1101 343 : if (type is ArrayType && has_array_length) {
1102 48 : for (var i = 0; i < ((ArrayType) type).rank; i++) {
1103 24 : write_param_or_return (((ArrayType) type).length_type, "parameter", ref index, has_array_length, "%s_length%i".printf (name, i + 1), null, null, direction);
1104 : }
1105 358 : } else if (type is DelegateType) {
1106 39 : var deleg_type = (DelegateType) type;
1107 77 : if (deleg_type.delegate_symbol.has_target) {
1108 38 : var data_type = new PointerType (new VoidType ());
1109 38 : write_param_or_return (data_type, "parameter", ref index, false, "%s_target".printf (name), null, null, direction);
1110 52 : if (deleg_type.is_disposable ()) {
1111 14 : var notify_type = new DelegateType (context.root.scope.lookup ("GLib").scope.lookup ("DestroyNotify") as Delegate);
1112 14 : write_param_or_return (notify_type, "parameter", ref index, false, "%s_target_destroy_notify".printf (name), null, null, direction);
1113 : }
1114 : }
1115 : }
1116 : }
1117 :
1118 320 : void skip_implicit_params (DataType? type, ref int index, bool has_array_length) {
1119 320 : if (type is ArrayType && has_array_length) {
1120 24 : index += ((ArrayType) type).rank;
1121 335 : } else if (type is DelegateType) {
1122 39 : index++;
1123 39 : var deleg_type = (DelegateType) type;
1124 39 : if (deleg_type.is_disposable ()) {
1125 14 : index++;
1126 : }
1127 : }
1128 : }
1129 :
1130 11 : private void write_type_parameter (TypeParameter type_parameter, string tag_type) {
1131 11 : write_indent ();
1132 11 : if (tag_type == "property") {
1133 2 : buffer.append_printf ("<%s name=\"%s\" writable=\"1\" construct-only=\"1\">\n", tag_type, get_ccode_type_id (type_parameter).replace ("_", "-"));
1134 : } else {
1135 9 : buffer.append_printf ("<%s name=\"%s\" transfer-ownership=\"none\">\n", tag_type, get_ccode_type_id (type_parameter));
1136 : }
1137 11 : indent++;
1138 11 : write_indent ();
1139 11 : buffer.append_printf ("<type name=\"GType\" c:type=\"GType\"/>\n");
1140 11 : indent--;
1141 11 : write_indent ();
1142 11 : buffer.append_printf ("</%s>\n", tag_type);
1143 11 : write_indent ();
1144 11 : if (tag_type == "property") {
1145 2 : buffer.append_printf ("<%s name=\"%s\" writable=\"1\" construct-only=\"1\">\n", tag_type, get_ccode_copy_function (type_parameter).replace ("_", "-"));
1146 : } else {
1147 9 : buffer.append_printf ("<%s name=\"%s\" transfer-ownership=\"none\">\n", tag_type, get_ccode_copy_function (type_parameter));
1148 : }
1149 11 : indent++;
1150 11 : write_indent ();
1151 11 : buffer.append_printf ("<type name=\"GObject.BoxedCopyFunc\" c:type=\"GBoxedCopyFunc\"/>\n");
1152 11 : indent--;
1153 11 : write_indent ();
1154 11 : buffer.append_printf ("</%s>\n", tag_type);
1155 11 : write_indent ();
1156 11 : if (tag_type == "property") {
1157 2 : buffer.append_printf ("<%s name=\"%s\" writable=\"1\" construct-only=\"1\">\n", tag_type, get_ccode_destroy_function (type_parameter).replace ("_", "-"));
1158 : } else {
1159 9 : buffer.append_printf ("<%s name=\"%s\" transfer-ownership=\"none\">\n", tag_type, get_ccode_destroy_function (type_parameter));
1160 : }
1161 11 : indent++;
1162 11 : write_indent ();
1163 11 : buffer.append_printf ("<type name=\"GLib.DestroyNotify\" c:type=\"GDestroyNotify\"/>\n");
1164 11 : indent--;
1165 11 : write_indent ();
1166 11 : buffer.append_printf ("</%s>\n", tag_type);
1167 : }
1168 :
1169 197 : private void write_params_and_return (Callable symbol, string tag_name, List<Parameter> params, List<TypeParameter>? type_params, DataType? return_type, bool return_array_length, string? return_comment = null, bool constructor = false, Parameter? instance_param = null, bool user_data = false) {
1170 197 : int last_index = 0;
1171 197 : bool ret_is_struct = return_type != null && return_type.is_real_non_null_struct_type ();
1172 :
1173 197 : if (params.size != 0 || (return_type is ArrayType && return_array_length) || (return_type is DelegateType) || ret_is_struct) {
1174 147 : int index = 0;
1175 :
1176 505 : foreach (Parameter param in params) {
1177 179 : index++;
1178 :
1179 179 : skip_implicit_params (param.variable_type, ref index, get_ccode_array_length (param));
1180 : }
1181 :
1182 147 : if (ret_is_struct) {
1183 6 : index++;
1184 : } else {
1185 141 : skip_implicit_params (return_type, ref index, return_array_length);
1186 141 : if (return_type is ArrayType && return_array_length) {
1187 6 : index -= ((ArrayType) return_type).rank - 1;
1188 : }
1189 : }
1190 :
1191 147 : last_index = index - 1;
1192 : }
1193 :
1194 197 : if (return_type != null && !ret_is_struct) {
1195 191 : write_param_or_return (return_type, "return-value", ref last_index, return_array_length, null, symbol.comment, return_comment, ParameterDirection.IN, constructor);
1196 6 : } else if (ret_is_struct) {
1197 6 : write_param_or_return (new VoidType (), "return-value", ref last_index, false, null, symbol.comment, return_comment, ParameterDirection.IN);
1198 : }
1199 :
1200 197 : if (params.size != 0 || (type_params != null && type_params.size > 0) || instance_param != null || (return_type is ArrayType && return_array_length) || (return_type is DelegateType) || ret_is_struct) {
1201 177 : write_indent ();
1202 177 : buffer.append_printf ("<parameters>\n");
1203 177 : indent++;
1204 177 : int index = 0;
1205 :
1206 322 : if (instance_param != null) {
1207 145 : var type = instance_param.variable_type.copy ();
1208 145 : unowned Struct? st = type.type_symbol as Struct;
1209 6 : if (st != null && !st.is_simple_type ()) {
1210 6 : type.nullable = true;
1211 : }
1212 145 : int skip = 0;
1213 145 : if (tag_name == "callback") {
1214 39 : write_param_or_return (type, "parameter", ref skip, false, "self");
1215 39 : index++;
1216 : } else {
1217 106 : write_param_or_return (type, "instance-parameter", ref skip, false, "self");
1218 : }
1219 : }
1220 :
1221 177 : if (constructor && ret_is_struct) {
1222 : // struct constructor has a caller-allocates / out-parameter as instance
1223 4 : write_param_or_return (return_type, "instance-parameter", ref index, false, "self", symbol.comment, return_comment, ParameterDirection.OUT, constructor, true);
1224 : }
1225 :
1226 177 : if (type_params != null) {
1227 187 : foreach (var p in type_params) {
1228 9 : write_type_parameter (p, "parameter");
1229 9 : index += 3;
1230 : }
1231 : }
1232 :
1233 535 : foreach (Parameter param in params) {
1234 179 : write_param_or_return (param.variable_type, "parameter", ref index, get_ccode_array_length (param), get_ccode_name (param), param.parent_symbol.comment, get_parameter_comment (param), param.direction, false, false, param.ellipsis || param.params_array);
1235 :
1236 179 : write_implicit_params (param.variable_type, ref index, get_ccode_array_length (param), get_ccode_name (param), param.direction);
1237 : }
1238 :
1239 177 : if (!constructor && ret_is_struct) {
1240 : // struct returns are converted to parameters
1241 2 : write_param_or_return (return_type, "parameter", ref index, false, "result", symbol.comment, return_comment, ParameterDirection.OUT, constructor, true);
1242 175 : } else if (!constructor) {
1243 164 : write_implicit_params (return_type, ref index, return_array_length, "result", ParameterDirection.OUT);
1244 : }
1245 :
1246 177 : if (user_data) {
1247 2 : write_indent ();
1248 2 : buffer.append_printf ("<parameter name=\"user_data\" transfer-ownership=\"none\" closure=\"%d\">\n", index);
1249 2 : indent++;
1250 2 : write_indent ();
1251 2 : buffer.append_printf ("<type name=\"gpointer\" c:type=\"void*\"/>\n");
1252 2 : indent--;
1253 2 : write_indent ();
1254 2 : buffer.append_printf ("</parameter>\n");
1255 : }
1256 :
1257 177 : indent--;
1258 177 : write_indent ();
1259 177 : buffer.append_printf ("</parameters>\n");
1260 : }
1261 : }
1262 :
1263 6 : public override void visit_delegate (Delegate cb) {
1264 6 : if (cb.external_package) {
1265 : return;
1266 : }
1267 :
1268 6 : if (!check_accessibility (cb)) {
1269 : return;
1270 : }
1271 :
1272 6 : if (!has_namespace (cb)) {
1273 : return;
1274 : }
1275 :
1276 5 : write_indent ();
1277 5 : buffer.append_printf ("<callback name=\"%s\"", get_gir_name (cb));
1278 5 : buffer.append_printf (" c:type=\"%s\"", get_ccode_name (cb));
1279 5 : if (cb.tree_can_fail) {
1280 1 : buffer.append_printf (" throws=\"1\"");
1281 : }
1282 5 : write_symbol_attributes (cb);
1283 5 : buffer.append_printf (">\n");
1284 5 : indent++;
1285 :
1286 5 : write_doc (get_delegate_comment (cb), cb.comment);
1287 :
1288 5 : write_params_and_return (cb, "callback", cb.get_parameters (), cb.get_type_parameters (), cb.return_type, get_ccode_array_length (cb), get_delegate_return_comment (cb), false, null, cb.has_target);
1289 :
1290 5 : indent--;
1291 5 : write_indent ();
1292 5 : buffer.append_printf ("</callback>\n");
1293 : }
1294 :
1295 181 : public override void visit_method (Method m) {
1296 91 : if (m.external_package) {
1297 : return;
1298 : }
1299 :
1300 : // don't write interface implementation unless it's an abstract or virtual method
1301 91 : if (!check_accessibility (m) || m.overrides || (m.base_interface_method != null && !m.is_abstract && !m.is_virtual)) {
1302 0 : return;
1303 : }
1304 :
1305 91 : if (!has_namespace (m)) {
1306 : return;
1307 : }
1308 :
1309 90 : string tag_name = "method";
1310 90 : var parent = this.hierarchy.get (0);
1311 90 : if (parent is Enum) {
1312 0 : deferred.add (m);
1313 0 : return;
1314 : }
1315 :
1316 90 : if (parent is Namespace || m.binding == MemberBinding.STATIC || parent != m.parent_symbol) {
1317 20 : tag_name = "function";
1318 : }
1319 :
1320 90 : if (!get_ccode_no_wrapper (m) && m.signal_reference == null) {
1321 83 : write_signature (m, tag_name, true);
1322 : }
1323 :
1324 90 : if (m.is_abstract || m.is_virtual) {
1325 29 : write_signature (m, "virtual-method", true, false);
1326 : }
1327 : }
1328 :
1329 323 : bool is_type_introspectable (DataType type) {
1330 : // gobject-introspection does not currently support va_list parameters
1331 323 : if (get_ccode_name (type) == "va_list") {
1332 : return false;
1333 : }
1334 :
1335 : return true;
1336 : }
1337 :
1338 187 : bool is_method_introspectable (Method m) {
1339 187 : if (!is_type_introspectable (m.return_type)) {
1340 10 : return false;
1341 : }
1342 443 : foreach (var param in m.get_parameters ()) {
1343 138 : if (param.ellipsis || param.params_array || !is_type_introspectable (param.variable_type)) {
1344 10 : return false;
1345 : }
1346 : }
1347 187 : return true;
1348 : }
1349 :
1350 284 : bool is_introspectable (Symbol sym) {
1351 284 : if (sym is Method && !is_method_introspectable ((Method) sym)) {
1352 10 : return false;
1353 : }
1354 :
1355 274 : return is_visibility (sym);
1356 : }
1357 :
1358 226 : private void write_signature (Method m, string tag_name, bool write_doc, bool instance = false, bool write_attributes = true) {
1359 113 : var parent = this.hierarchy.get (0);
1360 : string name;
1361 115 : if (m.parent_symbol != parent) {
1362 2 : instance = false;
1363 2 : name = get_ccode_name (m);
1364 2 : var parent_prefix = get_ccode_lower_case_prefix (parent);
1365 2 : if (name.has_prefix (parent_prefix)) {
1366 2 : name = name.substring (parent_prefix.length);
1367 : }
1368 : } else {
1369 222 : name = m.name;
1370 : }
1371 :
1372 113 : if (m.coroutine) {
1373 14 : string finish_name = name;
1374 14 : if (finish_name.has_suffix ("_async")) {
1375 8 : finish_name = finish_name.substring (0, finish_name.length - "_async".length);
1376 : }
1377 14 : finish_name += "_finish";
1378 14 : do_write_signature (m, tag_name, instance, name, get_ccode_name (m), m.get_async_begin_parameters (), new VoidType (), false, true, write_attributes);
1379 14 : do_write_signature (m, tag_name, instance, finish_name, get_ccode_finish_name (m), m.get_async_end_parameters (), m.return_type, m.tree_can_fail, false, write_attributes);
1380 : } else {
1381 99 : do_write_signature (m, tag_name, instance, name, get_ccode_name (m), m.get_parameters (), m.return_type, m.tree_can_fail, true, write_attributes);
1382 : }
1383 : }
1384 :
1385 330 : private void do_write_signature (Method m, string tag_name, bool instance, string name, string cname, List<Vala.Parameter> params, DataType return_type, bool can_fail, bool write_comment, bool write_attributes = true) {
1386 165 : write_indent ();
1387 165 : buffer.append_printf ("<%s name=\"%s\"", tag_name, name);
1388 165 : if (tag_name == "virtual-method") {
1389 37 : if (!get_ccode_no_wrapper (m)) {
1390 28 : buffer.append_printf (" invoker=\"%s\"", name);
1391 : }
1392 128 : } else if (tag_name == "callback") {
1393 : /* this is only used for vfuncs */
1394 39 : buffer.append_printf (" c:type=\"%s\"", name);
1395 : } else {
1396 89 : buffer.append_printf (" c:identifier=\"%s\"", cname);
1397 : }
1398 165 : if (can_fail) {
1399 10 : buffer.append_printf (" throws=\"1\"");
1400 : }
1401 165 : if (write_attributes) {
1402 126 : write_symbol_attributes (m);
1403 : }
1404 165 : buffer.append_printf (">\n");
1405 165 : indent++;
1406 :
1407 165 : string? return_comment = null;
1408 165 : if (write_comment) {
1409 113 : return_comment = get_method_return_comment (m);
1410 113 : write_doc (get_method_comment (m), m.comment);
1411 : }
1412 :
1413 165 : write_params_and_return (m, tag_name, params, m.get_type_parameters (), return_type, get_ccode_array_length (m), return_comment, false, m.this_parameter);
1414 :
1415 165 : indent--;
1416 165 : write_indent ();
1417 165 : buffer.append_printf ("</%s>\n", tag_name);
1418 : }
1419 :
1420 47 : public override void visit_creation_method (CreationMethod m) {
1421 24 : if (m.external_package) {
1422 : return;
1423 : }
1424 :
1425 24 : if (!check_accessibility (m)) {
1426 : return;
1427 : }
1428 :
1429 24 : if (m.parent_symbol is Class && ((Class) m.parent_symbol).is_abstract) {
1430 : return;
1431 : }
1432 :
1433 23 : write_indent ();
1434 :
1435 23 : bool is_struct = m.parent_symbol is Struct;
1436 : // GI doesn't like constructors that return void type
1437 23 : string tag_name = is_struct ? "method" : "constructor";
1438 :
1439 23 : if (m.parent_symbol is Class && m == ((Class)m.parent_symbol).default_construction_method ||
1440 9 : m.parent_symbol is Struct && m == ((Struct)m.parent_symbol).default_construction_method) {
1441 16 : string m_name = is_struct ? "init" : "new";
1442 16 : buffer.append_printf ("<%s name=\"%s\" c:identifier=\"%s\"", tag_name, m_name, get_ccode_name (m));
1443 7 : } else if (is_struct) {
1444 2 : buffer.append_printf ("<%s name=\"init_%s\" c:identifier=\"%s\"", tag_name, m.name, get_ccode_name (m));
1445 : } else {
1446 5 : buffer.append_printf ("<%s name=\"%s\" c:identifier=\"%s\"", tag_name, m.name, get_ccode_name (m));
1447 : }
1448 :
1449 23 : if (m.tree_can_fail) {
1450 1 : buffer.append_printf (" throws=\"1\"");
1451 : }
1452 23 : write_symbol_attributes (m);
1453 23 : buffer.append_printf (">\n");
1454 23 : indent++;
1455 :
1456 23 : write_doc (get_method_comment (m), m.comment);
1457 :
1458 23 : var datatype = SemanticAnalyzer.get_data_type_for_symbol (m.parent_symbol);
1459 23 : List<TypeParameter>? type_params = null;
1460 23 : if (m.parent_symbol is Class) {
1461 19 : type_params = ((Class) m.parent_symbol).get_type_parameters ();
1462 : }
1463 23 : write_params_and_return (m, tag_name, m.get_parameters (), type_params, datatype, false, get_method_return_comment (m), true);
1464 :
1465 23 : indent--;
1466 23 : write_indent ();
1467 23 : buffer.append_printf ("</%s>\n", tag_name);
1468 : }
1469 :
1470 10 : public override void visit_property (Property prop) {
1471 10 : if (!check_accessibility (prop) || prop.overrides || (prop.base_interface_property != null && !prop.is_abstract && !prop.is_virtual)) {
1472 4 : return;
1473 : }
1474 :
1475 6 : if (context.analyzer.is_gobject_property (prop)) {
1476 5 : write_indent ();
1477 5 : buffer.append_printf ("<property name=\"%s\"", get_ccode_name (prop));
1478 5 : if (prop.get_accessor == null) {
1479 2 : buffer.append_printf (" readable=\"0\"");
1480 : }
1481 5 : if (prop.set_accessor != null) {
1482 5 : buffer.append_printf (" writable=\"1\"");
1483 5 : if (prop.set_accessor.construction) {
1484 4 : if (!prop.set_accessor.writable) {
1485 1 : buffer.append_printf (" construct-only=\"1\"");
1486 : } else {
1487 3 : buffer.append_printf (" construct=\"1\"");
1488 : }
1489 : }
1490 : }
1491 5 : write_symbol_attributes (prop);
1492 5 : buffer.append_printf (">\n");
1493 5 : indent++;
1494 :
1495 5 : write_doc (get_property_comment (prop), prop.comment);
1496 :
1497 5 : write_type (prop.property_type);
1498 :
1499 5 : indent--;
1500 5 : write_indent ();
1501 5 : buffer.append_printf ("</property>\n");
1502 : }
1503 :
1504 10 : if (prop.get_accessor != null && prop.get_accessor.readable) {
1505 4 : var m = prop.get_accessor.get_method ();
1506 4 : if (m != null) {
1507 4 : visit_method (m);
1508 : }
1509 : }
1510 :
1511 11 : if (prop.set_accessor != null && prop.set_accessor.writable) {
1512 5 : var m = prop.set_accessor.get_method ();
1513 5 : if (m != null) {
1514 5 : visit_method (m);
1515 : }
1516 : }
1517 : }
1518 :
1519 4 : public override void visit_signal (Signal sig) {
1520 4 : if (!check_accessibility (sig)) {
1521 : return;
1522 : }
1523 :
1524 4 : if (sig.emitter != null) {
1525 1 : sig.emitter.accept (this);
1526 : }
1527 :
1528 4 : if (sig.default_handler != null) {
1529 1 : sig.default_handler.accept (this);
1530 : }
1531 :
1532 4 : write_indent ();
1533 4 : buffer.append_printf ("<glib:signal name=\"%s\"", get_ccode_name (sig));
1534 4 : write_symbol_attributes (sig);
1535 4 : buffer.append_printf (">\n");
1536 4 : indent++;
1537 :
1538 4 : write_doc (get_signal_comment (sig), sig.comment);
1539 :
1540 4 : write_params_and_return (sig, "glib:signal", sig.get_parameters (), null, sig.return_type, false, get_signal_return_comment (sig));
1541 :
1542 4 : indent--;
1543 4 : write_indent ();
1544 4 : buffer.append_printf ("</glib:signal>\n");
1545 : }
1546 :
1547 3207 : private void write_indent () {
1548 : int i;
1549 :
1550 14327 : for (i = 0; i < indent; i++) {
1551 25447 : buffer.append_c ('\t');
1552 : }
1553 : }
1554 :
1555 7 : private void write_indent_stream () {
1556 : int i;
1557 :
1558 7 : for (i = 0; i < indent; i++) {
1559 0 : stream.putc ('\t');
1560 : }
1561 : }
1562 :
1563 :
1564 603 : private void write_param_or_return (DataType? type, string tag, ref int index, bool has_array_length, string? name = null, Comment? parent_comment = null, string? comment = null, ParameterDirection direction = ParameterDirection.IN, bool constructor = false, bool caller_allocates = false, bool ellipsis = false) {
1565 603 : write_indent ();
1566 603 : buffer.append_printf ("<%s", tag);
1567 603 : if (ellipsis) {
1568 : name = "...";
1569 : }
1570 601 : if (name != null) {
1571 406 : buffer.append_printf (" name=\"%s\"", name);
1572 : }
1573 603 : if (direction == ParameterDirection.REF) {
1574 7 : buffer.append_printf (" direction=\"inout\"");
1575 596 : } else if (direction == ParameterDirection.OUT) {
1576 39 : buffer.append_printf (" direction=\"out\"");
1577 : }
1578 :
1579 603 : unowned DelegateType? delegate_type = type as DelegateType;
1580 603 : unowned ArrayType? array_type = type as ArrayType;
1581 :
1582 603 : if (type != null && ((type.value_owned && delegate_type == null) || (constructor
1583 23 : && !(type.type_symbol is Struct || type.type_symbol.is_subtype_of (ginitiallyunowned_type))))) {
1584 171 : var any_owned = false;
1585 185 : foreach (var generic_arg in type.get_type_arguments ()) {
1586 7 : any_owned |= generic_arg.value_owned;
1587 : }
1588 171 : if (type.has_type_arguments () && !any_owned) {
1589 1 : buffer.append_printf (" transfer-ownership=\"container\"");
1590 170 : } else if (array_type != null && !array_type.element_type.value_owned) {
1591 1 : buffer.append_printf (" transfer-ownership=\"container\"");
1592 : } else {
1593 169 : buffer.append_printf (" transfer-ownership=\"full\"");
1594 : }
1595 : } else {
1596 432 : buffer.append_printf (" transfer-ownership=\"none\"");
1597 : }
1598 603 : if (caller_allocates) {
1599 6 : buffer.append_printf (" caller-allocates=\"1\"");
1600 : }
1601 603 : if (type != null && type.nullable) {
1602 72 : if (tag == "parameter"
1603 64 : && (direction == ParameterDirection.OUT || direction == ParameterDirection.REF)) {
1604 4 : buffer.append_printf (" optional=\"1\"");
1605 : } else {
1606 68 : buffer.append_printf (" nullable=\"1\"");
1607 : }
1608 : }
1609 :
1610 603 : if (delegate_type != null && delegate_type.delegate_symbol.has_target) {
1611 38 : int closure_index = tag == "parameter" ?
1612 38 : index + 1 : (type.value_owned ? index - 1 : index);
1613 38 : buffer.append_printf (" closure=\"%i\"", closure_index);
1614 38 : if (delegate_type.is_called_once) {
1615 22 : buffer.append (" scope=\"async\"");
1616 16 : } else if (type.value_owned) {
1617 14 : buffer.append_printf (" scope=\"notified\" destroy=\"%i\"", closure_index + 1);
1618 : } else {
1619 2 : buffer.append (" scope=\"call\"");
1620 : }
1621 565 : } else if (delegate_type != null) {
1622 15 : buffer.append (" scope=\"call\"");
1623 : }
1624 :
1625 603 : buffer.append_printf (">\n");
1626 603 : indent++;
1627 :
1628 603 : write_doc (comment, parent_comment);
1629 :
1630 603 : if (ellipsis) {
1631 2 : write_indent ();
1632 2 : buffer.append ("<varargs/>\n");
1633 601 : } else if (type != null) {
1634 601 : int length_param_index = -1;
1635 601 : if (has_array_length) {
1636 369 : length_param_index = tag == "parameter" ? index + 1 : index;
1637 : }
1638 :
1639 601 : bool additional_indirection = direction != ParameterDirection.IN;
1640 601 : if (!additional_indirection && tag == "parameter" && !type.nullable) {
1641 : // pass non-simple structs always by reference
1642 192 : unowned Struct? st = type.type_symbol as Struct;
1643 81 : if (st != null && !st.is_simple_type ()) {
1644 601 : additional_indirection = true;
1645 : }
1646 : }
1647 :
1648 601 : write_type (type, length_param_index, additional_indirection);
1649 : }
1650 :
1651 603 : indent--;
1652 603 : write_indent ();
1653 603 : buffer.append_printf ("</%s>\n", tag);
1654 603 : index++;
1655 : }
1656 :
1657 50 : private void write_ctype_attributes (TypeSymbol symbol, string suffix = "", bool symbol_prefix = false) {
1658 50 : buffer.append_printf (" c:type=\"%s%s\"", get_ccode_name (symbol), suffix);
1659 50 : if (symbol_prefix) {
1660 21 : buffer.append_printf (" c:symbol-prefix=\"%s\"", get_ccode_lower_case_suffix (symbol));
1661 : }
1662 : }
1663 :
1664 28 : private void write_gtype_attributes (TypeSymbol symbol, bool symbol_prefix = false) {
1665 28 : write_ctype_attributes(symbol, "", symbol_prefix);
1666 28 : buffer.append_printf (" glib:type-name=\"%s\"", get_ccode_name (symbol));
1667 28 : buffer.append_printf (" glib:get-type=\"%sget_type\"", get_ccode_lower_case_prefix (symbol));
1668 : }
1669 :
1670 670 : private void write_type (DataType type, int index = -1, bool additional_indirection = false) {
1671 696 : if (type is ArrayType) {
1672 26 : var array_type = (ArrayType) type;
1673 :
1674 26 : write_indent ();
1675 26 : buffer.append_printf ("<array");
1676 27 : if (array_type.fixed_length && array_type.length is IntegerLiteral) {
1677 1 : var lit = (IntegerLiteral) array_type.length;
1678 1 : buffer.append_printf (" fixed-size=\"%i\"", int.parse (lit.value));
1679 25 : } else if (index != -1) {
1680 24 : buffer.append_printf (" length=\"%i\"", index);
1681 : }
1682 26 : buffer.append_printf (" c:type=\"%s%s\"", get_ccode_name (array_type.element_type), !additional_indirection ? "*" : "**");
1683 26 : buffer.append_printf (">\n");
1684 26 : indent++;
1685 :
1686 26 : write_type (array_type.element_type);
1687 :
1688 26 : indent--;
1689 26 : write_indent ();
1690 26 : buffer.append_printf ("</array>\n");
1691 644 : } else if (type is VoidType) {
1692 145 : write_indent ();
1693 145 : buffer.append_printf ("<type name=\"none\" c:type=\"void\"/>\n");
1694 499 : } else if (type is PointerType) {
1695 40 : write_indent ();
1696 40 : buffer.append_printf ("<type name=\"gpointer\" c:type=\"%s%s\"/>\n", get_ccode_name (type), !additional_indirection ? "" : "*");
1697 459 : } else if (type is GenericType) {
1698 : // generic type parameters not supported in GIR
1699 14 : write_indent ();
1700 14 : buffer.append ("<type name=\"gpointer\" c:type=\"gpointer\"/>\n");
1701 499 : } else if (type is DelegateType) {
1702 54 : var deleg_type = (DelegateType) type;
1703 54 : write_indent ();
1704 54 : buffer.append_printf ("<type name=\"%s\" c:type=\"%s%s\"/>\n", gi_type_name (deleg_type.delegate_symbol), get_ccode_name (type), !additional_indirection ? "" : "*");
1705 782 : } else if (type.type_symbol != null) {
1706 391 : write_indent ();
1707 391 : string type_name = gi_type_name (type.type_symbol);
1708 391 : bool is_array = false;
1709 391 : if ((type_name == "GLib.Array") || (type_name == "GLib.PtrArray")) {
1710 : is_array = true;
1711 : }
1712 391 : buffer.append_printf ("<%s name=\"%s\" c:type=\"%s%s\"", is_array ? "array" : "type", gi_type_name (type.type_symbol), get_ccode_name (type), !additional_indirection ? "" : "*");
1713 :
1714 391 : List<DataType> type_arguments = type.get_type_arguments ();
1715 391 : if (type_arguments.size == 0) {
1716 385 : buffer.append_printf ("/>\n");
1717 : } else {
1718 6 : buffer.append_printf (">\n");
1719 6 : indent++;
1720 :
1721 28 : foreach (DataType type_argument in type_arguments) {
1722 11 : write_type (type_argument);
1723 : }
1724 :
1725 6 : indent--;
1726 6 : write_indent ();
1727 6 : buffer.append_printf ("</%s>\n", is_array ? "array" : "type");
1728 : }
1729 : } else {
1730 0 : write_indent ();
1731 0 : buffer.append_printf ("<type name=\"%s\"/>\n", type.to_string ());
1732 : }
1733 : }
1734 :
1735 676 : private string? get_full_gir_name (Symbol sym) {
1736 676 : string? gir_fullname = sym.get_attribute_string ("GIR", "fullname");
1737 676 : if (gir_fullname != null) {
1738 676 : return gir_fullname;
1739 : }
1740 :
1741 676 : string? gir_name = sym.get_attribute_string ("GIR", "name");
1742 :
1743 676 : if (gir_name == null && sym is Namespace) {
1744 338 : gir_name = sym.get_attribute_string ("CCode", "gir_namespace");
1745 : }
1746 676 : if (gir_name == null) {
1747 708 : gir_name = sym.name;
1748 : }
1749 :
1750 676 : if (sym.parent_symbol == null) {
1751 338 : return gir_name;
1752 : }
1753 :
1754 338 : if (sym.name == null) {
1755 0 : return get_full_gir_name (sym.parent_symbol);
1756 : }
1757 :
1758 338 : string parent_gir_name = get_full_gir_name (sym.parent_symbol);
1759 338 : if (parent_gir_name == null) {
1760 338 : return gir_name;
1761 : }
1762 :
1763 0 : string self_gir_name = gir_name.has_prefix (".") ? gir_name.substring (1) : gir_name;
1764 0 : if ("." in parent_gir_name) {
1765 0 : return "%s%s".printf (parent_gir_name, self_gir_name);
1766 : } else {
1767 0 : return "%s.%s".printf (parent_gir_name, self_gir_name);
1768 : }
1769 : }
1770 :
1771 871 : private string gi_type_name (TypeSymbol type_symbol) {
1772 871 : Symbol parent = type_symbol.parent_symbol;
1773 1209 : if (parent is Namespace) {
1774 871 : Namespace ns = parent as Namespace;
1775 1742 : var ns_gir_name = ns.get_attribute_string ("GIR", "name") ?? ns.name;
1776 871 : if (ns_gir_name != null) {
1777 533 : unowned SourceFile source_file = type_symbol.source_reference.file;
1778 533 : if (source_file.gir_namespace != null) {
1779 : GIRNamespace external;
1780 533 : if (source_file.gir_ambiguous) {
1781 12 : external = GIRNamespace.for_symbol (type_symbol);
1782 : } else {
1783 521 : external = GIRNamespace (source_file.gir_namespace, source_file.gir_version);
1784 : }
1785 533 : if (!externals.contains (external)) {
1786 9 : externals.add (external);
1787 : }
1788 533 : string? gir_fullname = type_symbol.get_attribute_string ("GIR", "fullname");
1789 533 : if (gir_fullname != null) {
1790 0 : return gir_fullname;
1791 : }
1792 1030 : var type_name = type_symbol.get_attribute_string ("GIR", "name") ?? type_symbol.name;
1793 533 : return "%s.%s".printf (external.ns, type_name);
1794 : } else {
1795 0 : unannotated_namespaces.add(ns);
1796 : }
1797 : }
1798 : }
1799 :
1800 338 : return get_full_gir_name (type_symbol);
1801 : }
1802 :
1803 13 : private string? literal_expression_to_value_string (Expression literal) {
1804 13 : if (literal is StringLiteral) {
1805 1 : var lit = literal as StringLiteral;
1806 1 : if (lit != null) {
1807 1 : return Markup.escape_text (lit.eval ());
1808 : }
1809 12 : } else if (literal is CharacterLiteral) {
1810 1 : return "%c".printf ((char) ((CharacterLiteral) literal).get_char ());
1811 11 : } else if (literal is BooleanLiteral) {
1812 4 : return ((BooleanLiteral) literal).value ? "true" : "false";
1813 9 : } else if (literal is RealLiteral) {
1814 2 : return ((RealLiteral) literal).value;
1815 8 : } else if (literal is IntegerLiteral) {
1816 14 : return ((IntegerLiteral) literal).value;
1817 1 : } else if (literal is UnaryExpression) {
1818 1 : var unary = (UnaryExpression) literal;
1819 1 : if (unary.operator == UnaryOperator.MINUS) {
1820 1 : if (unary.inner is RealLiteral) {
1821 1 : return "-" + ((RealLiteral) unary.inner).value;
1822 0 : } else if (unary.inner is IntegerLiteral) {
1823 0 : return "-" + ((IntegerLiteral) unary.inner).value;
1824 : }
1825 : }
1826 : }
1827 13 : return null;
1828 : }
1829 :
1830 211 : private bool check_accessibility (Symbol sym) {
1831 211 : if (sym.access == SymbolAccessibility.PUBLIC ||
1832 18 : sym.access == SymbolAccessibility.PROTECTED) {
1833 194 : return true;
1834 : }
1835 :
1836 : // internal fields and function pointers in classes/interfaces are public API
1837 17 : if (sym.access == SymbolAccessibility.INTERNAL) {
1838 8 : unowned Symbol? parent = sym.parent_symbol;
1839 8 : if (parent != null
1840 8 : && (parent is Class || parent is Interface)
1841 8 : && ((sym is Field && ((Field) sym).binding == MemberBinding.INSTANCE)
1842 7 : || (sym is Method && ((Method) sym).binding == MemberBinding.INSTANCE && (((Method) sym).is_abstract || ((Method) sym).is_virtual)))) {
1843 4 : return true;
1844 : }
1845 : }
1846 :
1847 211 : return false;
1848 : }
1849 :
1850 282 : private bool is_visibility (Symbol sym) {
1851 282 : return sym.get_attribute_bool ("GIR", "visible", true);
1852 : }
1853 :
1854 163 : bool has_namespace (Symbol sym) {
1855 163 : if (!(sym.parent_symbol is Namespace) || sym.parent_symbol.name != null) {
1856 154 : return true;
1857 : }
1858 :
1859 9 : Report.warning (sym.source_reference, "`%s' must be part of namespace to be included in GIR", sym.name);
1860 9 : return false;
1861 : }
1862 : }
|