3 * Copyright (C) 2008-2012 Jürg Billeter
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.
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.
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
20 * Jürg Billeter <j@bitron.ch>
26 * Code visitor generating .gir file for the public interface.
28 public class Vala.GIRWriter : CodeVisitor {
29 private CodeContext context;
30 private string directory;
31 private string gir_namespace;
32 private string gir_version;
33 private string gir_shared_library;
35 protected virtual string? get_interface_comment (Interface iface) {
39 protected virtual string? get_struct_comment (Struct st) {
43 protected virtual string? get_enum_comment (Enum en) {
47 protected virtual string? get_class_comment (Class c) {
51 protected virtual string? get_error_code_comment (ErrorCode ecode) {
55 protected virtual string? get_enum_value_comment (EnumValue ev) {
59 protected virtual string? get_constant_comment (Constant c) {
63 protected virtual string? get_error_domain_comment (ErrorDomain edomain) {
67 protected virtual string? get_field_comment (Field f) {
71 protected virtual string? get_delegate_comment (Delegate cb) {
75 protected virtual string? get_method_comment (Method m) {
79 protected virtual string? get_property_comment (Property prop) {
83 protected virtual string? get_delegate_return_comment (Delegate cb) {
87 protected virtual string? get_signal_return_comment (Signal sig) {
91 protected virtual string? get_method_return_comment (Method m) {
95 protected virtual string? get_signal_comment (Signal sig) {
99 protected virtual string? get_parameter_comment (Parameter param) {
103 StringBuilder buffer = new StringBuilder();
105 Vala.HashSet<Namespace> unannotated_namespaces = new Vala.HashSet<Namespace>();
106 Vala.HashSet<Namespace> our_namespaces = new Vala.HashSet<Namespace>();
107 Vala.ArrayList<Vala.Symbol> hierarchy = new Vala.ArrayList<Vala.Symbol>();
108 Vala.ArrayList<Vala.CodeNode> deferred = new Vala.ArrayList<Vala.CodeNode>();
112 private TypeSymbol gobject_type;
113 private TypeSymbol ginitiallyunowned_type;
114 private TypeSymbol gtypeinterface_type;
115 private TypeSymbol gtypeinstance_type;
116 private TypeSymbol gtype_type;
118 private struct GIRNamespace {
119 public GIRNamespace (string ns, string version) {
120 this.ns = ns; this.version = version;
123 public string version;
124 public bool equal (GIRNamespace g) {
125 return ((ns == g.ns) && (version == g.version));
128 public static GIRNamespace for_symbol (Symbol sym) {
129 while (sym.parent_symbol != null && sym.parent_symbol.name != null) {
130 sym = sym.parent_symbol;
132 assert (sym is Namespace);
133 string gir_namespace = sym.get_attribute_string ("CCode", "gir_namespace");
134 string gir_version = sym.get_attribute_string ("CCode", "gir_version");
135 return GIRNamespace (gir_namespace, gir_version);
139 private ArrayList<GIRNamespace?> externals = new ArrayList<GIRNamespace?> ((EqualFunc<GIRNamespace>) GIRNamespace.equal);
141 public void write_includes() {
142 foreach (var i in externals) {
143 if (i.ns != this.gir_namespace) {
144 write_indent_stream ();
145 stream.printf ("<include name=\"%s\" version=\"%s\"/>\n", i.ns, i.version);
152 * Writes the public interface of the specified code context into the
155 * @param context a code context
156 * @param gir_filename a relative or absolute filename
158 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 this.context = context;
160 this.directory = directory;
161 this.gir_namespace = gir_namespace;
162 this.gir_version = gir_version;
163 this.gir_shared_library = gir_shared_library;
165 var root_symbol = context.root;
166 var glib_ns = root_symbol.scope.lookup ("GLib");
167 gobject_type = (TypeSymbol) glib_ns.scope.lookup ("Object");
168 ginitiallyunowned_type = (TypeSymbol) glib_ns.scope.lookup ("InitiallyUnowned");
169 gtypeinterface_type = (TypeSymbol) glib_ns.scope.lookup ("TypeInterface");
170 gtypeinstance_type = (TypeSymbol) glib_ns.scope.lookup ("TypeInstance");
171 gtype_type = (TypeSymbol) glib_ns.scope.lookup ("Type");
173 write_package (package);
175 // Make sure to initialize external files with their gir_namespace/version
176 foreach (var file in context.get_source_files ()) {
180 context.accept (this);
183 buffer.append_printf ("</repository>\n");
185 string filename = "%s%c%s".printf (directory, Path.DIR_SEPARATOR, gir_filename);
186 var file_exists = FileUtils.test (filename, FileTest.EXISTS);
187 var temp_filename = "%s.valatmp".printf (filename);
190 stream = FileStream.open (temp_filename, "w");
192 stream = FileStream.open (filename, "w");
195 if (stream == null) {
196 Report.error (null, "unable to open `%s' for writing", filename);
201 stream.printf ("<?xml version=\"1.0\"?>\n");
203 var header = context.version_header ?
204 "<!-- %s generated by %s %s, do not modify. -->".printf (Path.get_basename (filename), Environment.get_prgname (), Vala.BUILD_VERSION) :
205 "<!-- %s generated by %s, do not modify. -->".printf (Path.get_basename (filename), Environment.get_prgname ());
206 stream.printf ("%s\n", header);
208 stream.printf ("<repository version=\"1.2\"");
209 stream.printf (" xmlns=\"http://www.gtk.org/introspection/core/1.0\"");
210 stream.printf (" xmlns:c=\"http://www.gtk.org/introspection/c/1.0\"");
211 stream.printf (" xmlns:glib=\"http://www.gtk.org/introspection/glib/1.0\"");
212 stream.printf (">\n");
218 stream.puts (buffer.str);
225 var old_file = new MappedFile (filename, false);
226 var new_file = new MappedFile (temp_filename, false);
227 var len = old_file.get_length ();
228 if (len == new_file.get_length ()) {
229 if (Memory.cmp (old_file.get_contents (), new_file.get_contents (), len) == 0) {
235 } catch (FileError e) {
236 // assume changed if mmap comparison doesn't work
240 FileUtils.rename (temp_filename, filename);
242 FileUtils.unlink (temp_filename);
246 foreach (var ns in unannotated_namespaces) {
247 if (!our_namespaces.contains(ns)) {
248 Report.warning (ns.source_reference, "Namespace `%s' does not have a GIR namespace and version annotation", ns.name);
251 foreach (var ns in our_namespaces) {
252 ns.source_reference.file.gir_namespace = gir_namespace;
253 ns.source_reference.file.gir_version = gir_version;
256 if (our_namespaces.size == 0) {
257 Report.error (null, "No suitable namespace found to export for GIR");
263 private void write_doc (string? comment) {
264 if (comment != null) {
266 buffer.append ("<doc xml:whitespace=\"preserve\">");
267 buffer.append (comment);
268 buffer.append ("</doc>\n");
272 private void write_package (string package) {
274 buffer.append_printf ("<package name=\"%s\"/>\n", package);
277 private void write_c_includes (Namespace ns) {
278 // Collect C header filenames
279 Set<string> header_filenames = new HashSet<string> (str_hash, str_equal);
280 foreach (unowned string c_header_filename in get_ccode_header_filenames (ns).split (",")) {
281 header_filenames.add (c_header_filename);
283 foreach (Symbol symbol in ns.scope.get_symbol_table ().get_values ()) {
284 if (symbol.external_package) {
287 foreach (unowned string c_header_filename in get_ccode_header_filenames (symbol).split (",")) {
288 header_filenames.add (c_header_filename);
292 // Generate c:include tags
293 foreach (string c_header_filename in header_filenames) {
294 write_c_include (c_header_filename);
298 private void write_c_include (string name) {
300 buffer.append_printf ("<c:include name=\"%s\"/>\n", name);
303 public override void visit_source_file (SourceFile source_file) {
304 if (source_file.file_type != SourceFileType.PACKAGE) {
308 // Populate gir_namespace/version of source-file like in Namespace.check()
309 foreach (var node in source_file.get_nodes ()) {
310 if (node is Namespace && ((Namespace) node).parent_symbol == context.root) {
311 var a = node.get_attribute ("CCode");
312 if (a != null && a.has_argument ("gir_namespace")) {
313 var new_gir = a.get_string ("gir_namespace");
314 var old_gir = source_file.gir_namespace;
315 if (old_gir != null && old_gir != new_gir) {
316 source_file.gir_ambiguous = true;
318 source_file.gir_namespace = new_gir;
320 if (a != null && a.has_argument ("gir_version")) {
321 source_file.gir_version = a.get_string ("gir_version");
328 public override void visit_namespace (Namespace ns) {
329 if (ns.external_package) {
333 if (!is_visibility (ns)) {
337 if (ns.name == null) {
339 hierarchy.insert (0, ns);
340 ns.accept_children (this);
341 hierarchy.remove_at (0);
345 if (ns.parent_symbol.name != null) {
346 ns.accept_children (this);
350 if (our_namespaces.size > 0) {
351 Report.error (ns.source_reference, "Secondary top-level namespace `%s' is not supported by GIR format", ns.name);
355 // Use given gir_namespace and gir_version for our top-level namespace
356 var old_gir_namespace = ns.get_attribute_string ("CCode", "gir_namespace");
357 var old_gir_version = ns.get_attribute_string ("CCode", "gir_version");
358 if ((old_gir_namespace != null && old_gir_namespace != gir_namespace)
359 || (old_gir_version != null && old_gir_version != gir_version)) {
360 Report.warning (ns.source_reference, "Replace conflicting CCode.gir_* attributes for namespace `%s'".printf (ns.name));
362 ns.set_attribute_string ("CCode", "gir_namespace", gir_namespace);
363 ns.set_attribute_string ("CCode", "gir_version", gir_version);
365 write_c_includes (ns);
368 buffer.append_printf ("<namespace name=\"%s\" version=\"%s\"", gir_namespace, gir_version);
369 string? cprefix = get_ccode_prefix (ns);
370 if (gir_shared_library != null) {
371 buffer.append_printf(" shared-library=\"%s\"", gir_shared_library);
373 if (cprefix != null) {
374 buffer.append_printf (" c:prefix=\"%s\"", cprefix);
375 buffer.append_printf (" c:identifier-prefixes=\"%s\"", cprefix);
377 string? csymbol_prefix = get_ccode_lower_case_suffix (ns);
378 if (csymbol_prefix != null) {
379 buffer.append_printf (" c:symbol-prefixes=\"%s\"", csymbol_prefix);
381 buffer.append_printf (">\n");
384 hierarchy.insert (0, ns);
385 ns.accept_children (this);
386 hierarchy.remove_at (0);
390 buffer.append_printf ("</namespace>\n");
391 our_namespaces.add(ns);
396 private void write_symbol_attributes (Symbol symbol) {
397 if (!is_introspectable (symbol)) {
398 buffer.append_printf (" introspectable=\"0\"");
400 if (symbol.version.deprecated) {
401 buffer.append_printf (" deprecated=\"1\"");
402 if (symbol.version.deprecated_since != null) {
403 buffer.append_printf (" deprecated-version=\"%s\"", symbol.version.deprecated_since);
406 if (symbol.version.since != null) {
407 buffer.append_printf (" version=\"%s\"", symbol.version.since);
411 public override void visit_class (Class cl) {
412 if (cl.external_package) {
416 if (!check_accessibility (cl)) {
420 if (!has_namespace (cl)) {
424 if (!(hierarchy[0] is Namespace)) {
429 if (!cl.is_compact) {
430 string gtype_struct_name = get_gir_name (cl) + "Class";
433 buffer.append_printf ("<class name=\"%s\"", get_gir_name (cl));
434 write_gtype_attributes (cl, true);
435 buffer.append_printf (" glib:type-struct=\"%s\"", gtype_struct_name);
436 if (cl.base_class == null) {
437 buffer.append_printf (" glib:fundamental=\"1\"");
438 buffer.append_printf (" glib:ref-func=\"%s\"", get_ccode_ref_function (cl));
439 buffer.append_printf (" glib:unref-func=\"%s\"", get_ccode_unref_function (cl));
440 buffer.append_printf (" glib:set-value-func=\"%s\"", get_ccode_set_value_function (cl));
441 buffer.append_printf (" glib:get-value-func=\"%s\"", get_ccode_get_value_function (cl));
443 buffer.append_printf (" parent=\"%s\"", gi_type_name (cl.base_class));
445 if (cl.is_abstract) {
446 buffer.append_printf (" abstract=\"1\"");
449 buffer.append_printf (" final=\"1\"");
451 write_symbol_attributes (cl);
452 buffer.append_printf (">\n");
455 write_doc (get_class_comment (cl));
457 // write implemented interfaces
458 foreach (DataType base_type in cl.get_base_types ()) {
459 var object_type = (ObjectType) base_type;
460 if (object_type.type_symbol is Interface) {
462 buffer.append_printf ("<implements name=\"%s\"/>\n", gi_type_name (object_type.type_symbol));
467 buffer.append_printf ("<field name=\"parent_instance\" readable=\"0\" private=\"1\">\n");
470 if (cl.base_class == null) {
471 buffer.append_printf ("<type name=\"%s\" c:type=\"%s\"/>\n", gi_type_name (gtypeinstance_type), get_ccode_name (gtypeinstance_type));
473 buffer.append_printf ("<type name=\"%s\" c:type=\"%s\"/>\n", gi_type_name (cl.base_class), get_ccode_name (cl.base_class));
477 buffer.append_printf("</field>\n");
479 if (cl.base_class == null) {
481 buffer.append_printf ("<field name=\"ref_count\">\n");
484 buffer.append_printf ("<type name=\"gint\" c:type=\"volatile int\"/>\n");
487 buffer.append_printf("</field>\n");
490 if (!context.abi_stability) {
492 buffer.append_printf ("<field name=\"priv\" readable=\"0\" private=\"1\">\n");
495 buffer.append_printf ("<type name=\"%sPrivate\" c:type=\"%sPrivate*\"/>\n", get_gir_name (cl), get_ccode_name (cl));
498 buffer.append_printf("</field>\n");
501 if (cl.base_class != null && cl.base_class.is_subtype_of (gobject_type)) {
502 foreach (var p in cl.get_type_parameters ()) {
503 write_type_parameter (p, "property");
507 hierarchy.insert (0, cl);
508 cl.accept_children (this);
509 hierarchy.remove_at (0);
511 if (context.abi_stability) {
513 buffer.append_printf ("<field name=\"priv\" readable=\"0\" private=\"1\">\n");
516 buffer.append_printf ("<type name=\"%sPrivate\" c:type=\"%sPrivate*\"/>\n", get_gir_name (cl), get_ccode_name (cl));
519 buffer.append_printf("</field>\n");
524 buffer.append_printf ("</class>\n");
527 buffer.append_printf ("<record name=\"%s\"", gtype_struct_name);
528 write_ctype_attributes (cl, "Class");
529 buffer.append_printf (" glib:is-gtype-struct-for=\"%s\"", get_gir_name (cl));
530 buffer.append_printf (">\n");
534 buffer.append_printf ("<field name=\"parent_class\" readable=\"0\" private=\"1\">\n");
537 if (cl.base_class == null) {
538 //FIXME GObject.TypeClass vs GType
539 buffer.append_printf ("<type name=\"%sClass\" c:type=\"%sClass\"/>\n", "GObject.Type", get_ccode_name (gtype_type));
541 buffer.append_printf ("<type name=\"%sClass\" c:type=\"%sClass\"/>\n", gi_type_name (cl.base_class), get_ccode_name (cl.base_class));
545 buffer.append_printf ("</field>\n");
547 foreach (Method m in cl.get_methods ()) {
548 if (m.is_abstract || m.is_virtual) {
550 string finish_name = m.name;
551 if (finish_name.has_suffix ("_async")) {
552 finish_name = finish_name.substring (0, finish_name.length - "_async".length);
554 finish_name += "_finish";
557 buffer.append_printf("<field name=\"%s\"", m.name);
558 write_symbol_attributes (m);
559 buffer.append_printf (">\n");
561 do_write_signature (m, "callback", true, m.name, get_ccode_name (m), m.get_async_begin_parameters (), new VoidType (), false, false, false);
564 buffer.append_printf ("</field>\n");
567 buffer.append_printf("<field name=\"%s\"", finish_name);
568 write_symbol_attributes (m);
569 buffer.append_printf (">\n");
571 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);
574 buffer.append_printf ("</field>\n");
577 buffer.append_printf("<field name=\"%s\"", m.name);
578 write_symbol_attributes (m);
579 buffer.append_printf (">\n");
581 do_write_signature (m, "callback", true, m.name, get_ccode_name (m), m.get_parameters (), m.return_type, m.tree_can_fail, false, false);
584 buffer.append_printf ("</field>\n");
589 foreach (Signal sig in cl.get_signals ()) {
590 if (sig.default_handler != null) {
592 buffer.append_printf ("<field name=\"%s\"", get_ccode_lower_case_name (sig));
593 write_symbol_attributes (sig);
594 buffer.append_printf (">\n");
596 write_signature (sig.default_handler, "callback", false, true, false);
599 buffer.append_printf ("</field>\n");
605 buffer.append_printf ("</record>\n");
608 buffer.append_printf ("<record name=\"%sPrivate\" c:type=\"%sPrivate\" disguised=\"1\"/>\n", get_gir_name (cl), get_ccode_name (cl));
611 buffer.append_printf ("<record name=\"%s\"", get_gir_name (cl));
612 write_ctype_attributes (cl);
613 write_symbol_attributes (cl);
614 buffer.append_printf (">\n");
617 write_doc (get_class_comment (cl));
619 hierarchy.insert (0, cl);
620 cl.accept_children (this);
621 hierarchy.remove_at (0);
625 buffer.append_printf ("</record>\n");
631 public override void visit_struct (Struct st) {
632 if (st.external_package) {
636 if (!check_accessibility (st)) {
640 if (!has_namespace (st)) {
644 if (!(hierarchy[0] is Namespace)) {
650 buffer.append_printf ("<record name=\"%s\"", get_gir_name (st));
651 if (get_ccode_has_type_id (st)) {
652 write_gtype_attributes (st, true);
654 write_ctype_attributes (st, "", true);
656 write_symbol_attributes (st);
657 buffer.append_printf (">\n");
660 write_doc (get_struct_comment (st));
662 hierarchy.insert (0, st);
663 st.accept_children (this);
664 hierarchy.remove_at (0);
668 buffer.append_printf ("</record>\n");
673 public override void visit_interface (Interface iface) {
674 if (iface.external_package) {
678 if (!check_accessibility (iface)) {
682 if (!has_namespace (iface)) {
686 if (!(hierarchy[0] is Namespace)) {
687 deferred.add (iface);
691 string gtype_struct_name = get_gir_name (iface) + "Iface";
694 buffer.append_printf ("<interface name=\"%s\"", get_gir_name (iface));
695 write_gtype_attributes (iface, true);
696 buffer.append_printf (" glib:type-struct=\"%s\"", gtype_struct_name);
697 write_symbol_attributes (iface);
698 buffer.append_printf (">\n");
701 write_doc (get_interface_comment (iface));
703 // write prerequisites
704 if (iface.get_prerequisites ().size > 0) {
705 foreach (DataType base_type in iface.get_prerequisites ()) {
707 buffer.append_printf ("<prerequisite name=\"%s\"/>\n", gi_type_name (((ObjectType) base_type).type_symbol));
711 hierarchy.insert (0, iface);
712 iface.accept_children (this);
713 hierarchy.remove_at (0);
717 buffer.append_printf ("</interface>\n");
720 buffer.append_printf ("<record name=\"%s\"", gtype_struct_name);
721 write_ctype_attributes (iface, "Iface");
722 buffer.append_printf (" glib:is-gtype-struct-for=\"%s\"", get_gir_name (iface));
723 buffer.append_printf (">\n");
727 buffer.append_printf ("<field name=\"parent_iface\" readable=\"0\" private=\"1\">\n");
730 buffer.append_printf ("<type name=\"%s\" c:type=\"%s\"/>\n", gi_type_name (gtypeinterface_type), get_ccode_name (gtypeinterface_type));
733 buffer.append_printf ("</field>\n");
735 foreach (Method m in iface.get_methods ()) {
736 if (m.is_abstract || m.is_virtual) {
738 string finish_name = m.name;
739 if (finish_name.has_suffix ("_async")) {
740 finish_name = finish_name.substring (0, finish_name.length - "_async".length);
742 finish_name += "_finish";
745 buffer.append_printf("<field name=\"%s\"", m.name);
746 write_symbol_attributes (m);
747 buffer.append_printf (">\n");
749 do_write_signature (m, "callback", true, m.name, get_ccode_name (m), m.get_async_begin_parameters (), new VoidType (), false, false, false);
752 buffer.append_printf ("</field>\n");
755 buffer.append_printf("<field name=\"%s\"", finish_name);
756 write_symbol_attributes (m);
757 buffer.append_printf (">\n");
759 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);
762 buffer.append_printf ("</field>\n");
765 buffer.append_printf("<field name=\"%s\"", m.name);
766 write_symbol_attributes (m);
767 buffer.append_printf (">\n");
769 do_write_signature (m, "callback", true, m.name, get_ccode_name (m), m.get_parameters (), m.return_type, m.tree_can_fail, false, false);
772 buffer.append_printf ("</field>\n");
777 foreach (var prop in iface.get_properties ()) {
778 if (prop.is_abstract || prop.is_virtual) {
779 if (prop.get_accessor != null) {
780 var m = prop.get_accessor.get_method ();
782 buffer.append_printf("<field name=\"%s\"", m.name);
783 write_symbol_attributes (m);
784 buffer.append_printf (">\n");
786 do_write_signature (m, "callback", true, m.name, get_ccode_name (m), m.get_parameters (), m.return_type, m.tree_can_fail, false, false);
789 buffer.append_printf ("</field>\n");
792 if (prop.set_accessor != null && prop.set_accessor.writable) {
793 var m = prop.set_accessor.get_method ();
795 buffer.append_printf("<field name=\"%s\"", m.name);
796 write_symbol_attributes (m);
797 buffer.append_printf (">\n");
799 do_write_signature (m, "callback", true, m.name, get_ccode_name (m), m.get_parameters (), m.return_type, m.tree_can_fail, false, false);
802 buffer.append_printf ("</field>\n");
809 buffer.append_printf ("</record>\n");
814 private void visit_deferred () {
815 var nodes = this.deferred;
816 this.deferred = new Vala.ArrayList<Vala.CodeNode>();
818 foreach (var node in nodes) {
823 private string? get_gir_name (Symbol symbol) {
824 string? gir_name = null;
825 var h0 = hierarchy[0];
827 for (Symbol? cur_sym = symbol ; cur_sym != null ; cur_sym = cur_sym.parent_symbol) {
832 var cur_name = cur_sym.get_attribute_string ("GIR", "name");
833 if (cur_name == null) {
834 cur_name = cur_sym.name;
836 gir_name = cur_name.concat (gir_name);
842 public override void visit_enum (Enum en) {
843 if (en.external_package) {
847 if (!check_accessibility (en)) {
851 if (!has_namespace (en)) {
855 if (!(hierarchy[0] is Namespace)) {
860 string element_name = (en.is_flags) ? "bitfield" : "enumeration";
863 buffer.append_printf ("<%s name=\"%s\"", element_name, get_gir_name (en));
864 if (get_ccode_has_type_id (en)) {
865 write_gtype_attributes (en);
867 write_ctype_attributes (en);
869 write_symbol_attributes (en);
870 buffer.append_printf (">\n");
873 write_doc (get_enum_comment (en));
876 hierarchy.insert (0, en);
877 en.accept_children (this);
878 hierarchy.remove_at (0);
882 buffer.append_printf ("</%s>\n", element_name);
887 private int enum_value;
889 public override void visit_enum_value (EnumValue ev) {
891 var en = (Enum) hierarchy[0];
892 buffer.append_printf ("<member name=\"%s\" c:identifier=\"%s\"", ev.name.ascii_down (), get_ccode_name (ev));
893 if (ev.value != null) {
894 string value = literal_expression_to_value_string (ev.value);
895 buffer.append_printf (" value=\"%s\"", value);
898 buffer.append_printf (" value=\"%d\"", 1 << enum_value++);
900 buffer.append_printf (" value=\"%d\"", enum_value++);
903 write_symbol_attributes (ev);
905 string? comment = get_enum_value_comment (ev);
906 if (comment == null) {
907 buffer.append_printf ("/>\n");
909 buffer.append_printf (">\n");
916 buffer.append_printf ("</member>\n");
920 public override void visit_error_domain (ErrorDomain edomain) {
921 if (edomain.external_package) {
925 if (!check_accessibility (edomain)) {
929 if (!has_namespace (edomain)) {
934 buffer.append_printf ("<enumeration name=\"%s\"", get_gir_name (edomain));
935 write_ctype_attributes (edomain);
936 buffer.append_printf (" glib:error-domain=\"%s\"", get_ccode_quark_name (edomain));
937 write_symbol_attributes (edomain);
938 buffer.append_printf (">\n");
941 write_doc (get_error_domain_comment (edomain));
944 hierarchy.insert (0, edomain);
945 edomain.accept_children (this);
946 hierarchy.remove_at (0);
950 buffer.append_printf ("</enumeration>\n");
955 public override void visit_error_code (ErrorCode ecode) {
957 buffer.append_printf ("<member name=\"%s\" c:identifier=\"%s\"", ecode.name.ascii_down (), get_ccode_name (ecode));
958 if (ecode.value != null) {
959 string value = literal_expression_to_value_string (ecode.value);
960 buffer.append_printf (" value=\"%s\"", value);
962 buffer.append_printf (" value=\"%d\"", enum_value++);
964 write_symbol_attributes (ecode);
966 string? comment = get_error_code_comment (ecode);
967 if (comment == null) {
968 buffer.append_printf ("/>\n");
970 buffer.append_printf (">\n");
977 buffer.append_printf ("</member>\n");
981 public override void visit_constant (Constant c) {
982 if (c.external_package) {
986 if (!check_accessibility (c)) {
990 if (!has_namespace (c)) {
994 //TODO Add better constant evaluation
995 var initializer = c.value;
996 string value = literal_expression_to_value_string (initializer);
999 buffer.append_printf ("<constant name=\"%s\" c:identifier=\"%s\"", get_gir_name (c), get_ccode_name (c));
1000 buffer.append_printf (" value=\"%s\"", value);
1001 write_symbol_attributes (c);
1002 buffer.append_printf (">\n");
1005 write_doc (get_constant_comment (c));
1007 write_type (initializer.value_type);
1011 buffer.append_printf ("</constant>\n");
1014 public override void visit_field (Field f) {
1015 if (f.external_package) {
1019 if (!check_accessibility (f)) {
1023 if (!has_namespace (f)) {
1028 buffer.append_printf ("<field name=\"%s\" writable=\"1\"", get_ccode_name (f));
1029 if (f.variable_type.nullable) {
1030 buffer.append_printf (" nullable=\"1\"");
1032 write_symbol_attributes (f);
1033 buffer.append_printf (">\n");
1036 write_doc (get_field_comment (f));
1038 write_type (f.variable_type);
1042 buffer.append_printf ("</field>\n");
1044 if (f.variable_type is ArrayType && get_ccode_array_length (f)) {
1045 var array_type = (ArrayType) f.variable_type;
1046 if (!array_type.fixed_length) {
1047 for (var i = 0; i < array_type.rank; i++) {
1049 buffer.append_printf ("<field name=\"%s_length%i\"", get_ccode_name (f), i + 1);
1050 write_symbol_attributes (f);
1051 buffer.append_printf (">\n");
1053 write_type (array_type.length_type);
1056 buffer.append_printf ("</field>\n");
1059 } else if (f.variable_type is DelegateType) {
1060 var deleg_type = (DelegateType) f.variable_type;
1061 if (deleg_type.delegate_symbol.has_target) {
1063 buffer.append_printf ("<field name=\"%s\"", get_ccode_delegate_target_name (f));
1064 write_symbol_attributes (f);
1065 buffer.append_printf (">\n");
1068 buffer.append_printf ("<type name=\"gpointer\" c:type=\"gpointer\"/>\n");
1071 buffer.append_printf ("</field>\n");
1072 if (deleg_type.is_disposable ()) {
1074 buffer.append_printf ("<field name=\"%s\"", get_ccode_delegate_target_destroy_notify_name (f));
1075 write_symbol_attributes (f);
1076 buffer.append_printf (">\n");
1079 buffer.append_printf ("<type name=\"GLib.DestroyNotify\" c:type=\"GDestroyNotify\"/>\n");
1082 buffer.append_printf ("</field>\n");
1088 private void write_implicit_params (DataType? type, ref int index, bool has_array_length, string? name, ParameterDirection direction) {
1089 if (type is ArrayType && has_array_length) {
1090 for (var i = 0; i < ((ArrayType) type).rank; i++) {
1091 write_param_or_return (((ArrayType) type).length_type, "parameter", ref index, has_array_length, "%s_length%i".printf (name, i + 1), null, direction);
1093 } else if (type is DelegateType) {
1094 var deleg_type = (DelegateType) type;
1095 if (deleg_type.delegate_symbol.has_target) {
1096 var data_type = new PointerType (new VoidType ());
1097 write_param_or_return (data_type, "parameter", ref index, false, "%s_target".printf (name), null, direction);
1098 if (deleg_type.is_disposable ()) {
1099 var notify_type = new DelegateType (context.root.scope.lookup ("GLib").scope.lookup ("DestroyNotify") as Delegate);
1100 write_param_or_return (notify_type, "parameter", ref index, false, "%s_target_destroy_notify".printf (name), null, direction);
1106 void skip_implicit_params (DataType? type, ref int index, bool has_array_length) {
1107 if (type is ArrayType && has_array_length) {
1108 index += ((ArrayType) type).rank;
1109 } else if (type is DelegateType) {
1111 var deleg_type = (DelegateType) type;
1112 if (deleg_type.is_disposable ()) {
1118 private void write_type_parameter (TypeParameter type_parameter, string tag_type) {
1120 if (tag_type == "property") {
1121 buffer.append_printf ("<%s name=\"%s\" writable=\"1\" construct-only=\"1\">\n", tag_type, get_ccode_type_id (type_parameter).replace ("_", "-"));
1123 buffer.append_printf ("<%s name=\"%s\" transfer-ownership=\"none\">\n", tag_type, get_ccode_type_id (type_parameter));
1127 buffer.append_printf ("<type name=\"GType\" c:type=\"GType\"/>\n");
1130 buffer.append_printf ("</%s>\n", tag_type);
1132 if (tag_type == "property") {
1133 buffer.append_printf ("<%s name=\"%s\" writable=\"1\" construct-only=\"1\">\n", tag_type, get_ccode_copy_function (type_parameter).replace ("_", "-"));
1135 buffer.append_printf ("<%s name=\"%s\" transfer-ownership=\"none\">\n", tag_type, get_ccode_copy_function (type_parameter));
1139 buffer.append_printf ("<type name=\"GObject.BoxedCopyFunc\" c:type=\"GBoxedCopyFunc\"/>\n");
1142 buffer.append_printf ("</%s>\n", tag_type);
1144 if (tag_type == "property") {
1145 buffer.append_printf ("<%s name=\"%s\" writable=\"1\" construct-only=\"1\">\n", tag_type, get_ccode_destroy_function (type_parameter).replace ("_", "-"));
1147 buffer.append_printf ("<%s name=\"%s\" transfer-ownership=\"none\">\n", tag_type, get_ccode_destroy_function (type_parameter));
1151 buffer.append_printf ("<type name=\"GLib.DestroyNotify\" c:type=\"GDestroyNotify\"/>\n");
1154 buffer.append_printf ("</%s>\n", tag_type);
1157 private void write_params_and_return (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) {
1159 bool ret_is_struct = return_type != null && return_type.is_real_non_null_struct_type ();
1161 if (params.size != 0 || (return_type is ArrayType && return_array_length) || (return_type is DelegateType) || ret_is_struct) {
1164 foreach (Parameter param in params) {
1167 skip_implicit_params (param.variable_type, ref index, get_ccode_array_length (param));
1170 if (ret_is_struct) {
1173 skip_implicit_params (return_type, ref index, return_array_length);
1174 if (return_type is ArrayType && return_array_length) {
1175 index -= ((ArrayType) return_type).rank - 1;
1179 last_index = index - 1;
1182 if (return_type != null && !ret_is_struct) {
1183 write_param_or_return (return_type, "return-value", ref last_index, return_array_length, null, return_comment, ParameterDirection.IN, constructor);
1184 } else if (ret_is_struct) {
1185 write_param_or_return (new VoidType (), "return-value", ref last_index, false, null, return_comment, ParameterDirection.IN);
1188 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) {
1190 buffer.append_printf ("<parameters>\n");
1194 if (instance_param != null) {
1195 var type = instance_param.variable_type.copy ();
1196 unowned Struct? st = type.type_symbol as Struct;
1197 if (st != null && !st.is_simple_type ()) {
1198 type.nullable = true;
1201 if (tag_name == "callback") {
1202 write_param_or_return (type, "parameter", ref skip, false, "self");
1205 write_param_or_return (type, "instance-parameter", ref skip, false, "self");
1209 if (constructor && ret_is_struct) {
1210 // struct constructor has a caller-allocates / out-parameter as instance
1211 write_param_or_return (return_type, "instance-parameter", ref index, false, "self", return_comment, ParameterDirection.OUT, constructor, true);
1214 if (type_params != null) {
1215 foreach (var p in type_params) {
1216 write_type_parameter (p, "parameter");
1221 foreach (Parameter param in params) {
1222 write_param_or_return (param.variable_type, "parameter", ref index, get_ccode_array_length (param), get_ccode_name (param), get_parameter_comment (param), param.direction, false, false, param.ellipsis || param.params_array);
1224 write_implicit_params (param.variable_type, ref index, get_ccode_array_length (param), get_ccode_name (param), param.direction);
1227 if (!constructor && ret_is_struct) {
1228 // struct returns are converted to parameters
1229 write_param_or_return (return_type, "parameter", ref index, false, "result", return_comment, ParameterDirection.OUT, constructor, true);
1230 } else if (!constructor) {
1231 write_implicit_params (return_type, ref index, return_array_length, "result", ParameterDirection.OUT);
1236 buffer.append_printf ("<parameter name=\"user_data\" transfer-ownership=\"none\" closure=\"%d\">\n", index);
1239 buffer.append_printf ("<type name=\"gpointer\" c:type=\"void*\"/>\n");
1242 buffer.append_printf ("</parameter>\n");
1247 buffer.append_printf ("</parameters>\n");
1251 public override void visit_delegate (Delegate cb) {
1252 if (cb.external_package) {
1256 if (!check_accessibility (cb)) {
1260 if (!has_namespace (cb)) {
1265 buffer.append_printf ("<callback name=\"%s\"", get_gir_name (cb));
1266 buffer.append_printf (" c:type=\"%s\"", get_ccode_name (cb));
1267 if (cb.tree_can_fail) {
1268 buffer.append_printf (" throws=\"1\"");
1270 write_symbol_attributes (cb);
1271 buffer.append_printf (">\n");
1274 write_doc (get_delegate_comment (cb));
1276 write_params_and_return ("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);
1280 buffer.append_printf ("</callback>\n");
1283 public override void visit_method (Method m) {
1284 if (m.external_package) {
1288 // don't write interface implementation unless it's an abstract or virtual method
1289 if (!check_accessibility (m) || m.overrides || (m.base_interface_method != null && !m.is_abstract && !m.is_virtual)) {
1293 if (!has_namespace (m)) {
1297 string tag_name = "method";
1298 var parent = this.hierarchy.get (0);
1299 if (parent is Enum) {
1304 if (parent is Namespace || m.binding == MemberBinding.STATIC || parent != m.parent_symbol) {
1305 tag_name = "function";
1308 if (!get_ccode_no_wrapper (m) && m.signal_reference == null) {
1309 write_signature (m, tag_name, true);
1312 if (m.is_abstract || m.is_virtual) {
1313 write_signature (m, "virtual-method", true, false);
1317 bool is_type_introspectable (DataType type) {
1318 // gobject-introspection does not currently support va_list parameters
1319 if (get_ccode_name (type) == "va_list") {
1326 bool is_method_introspectable (Method m) {
1327 if (!is_type_introspectable (m.return_type)) {
1330 foreach (var param in m.get_parameters ()) {
1331 if (param.ellipsis || param.params_array || !is_type_introspectable (param.variable_type)) {
1338 bool is_introspectable (Symbol sym) {
1339 if (sym is Method && !is_method_introspectable ((Method) sym)) {
1343 return is_visibility (sym);
1346 private void write_signature (Method m, string tag_name, bool write_doc, bool instance = false, bool write_attributes = true) {
1347 var parent = this.hierarchy.get (0);
1349 if (m.parent_symbol != parent) {
1351 name = get_ccode_name (m);
1352 var parent_prefix = get_ccode_lower_case_prefix (parent);
1353 if (name.has_prefix (parent_prefix)) {
1354 name = name.substring (parent_prefix.length);
1361 string finish_name = name;
1362 if (finish_name.has_suffix ("_async")) {
1363 finish_name = finish_name.substring (0, finish_name.length - "_async".length);
1365 finish_name += "_finish";
1366 do_write_signature (m, tag_name, instance, name, get_ccode_name (m), m.get_async_begin_parameters (), new VoidType (), false, true, write_attributes);
1367 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);
1369 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);
1373 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) {
1375 buffer.append_printf ("<%s name=\"%s\"", tag_name, name);
1376 if (tag_name == "virtual-method") {
1377 if (!get_ccode_no_wrapper (m)) {
1378 buffer.append_printf (" invoker=\"%s\"", name);
1380 } else if (tag_name == "callback") {
1381 /* this is only used for vfuncs */
1382 buffer.append_printf (" c:type=\"%s\"", name);
1384 buffer.append_printf (" c:identifier=\"%s\"", cname);
1387 buffer.append_printf (" throws=\"1\"");
1389 if (write_attributes) {
1390 write_symbol_attributes (m);
1392 buffer.append_printf (">\n");
1395 string? return_comment = null;
1396 if (write_comment) {
1397 return_comment = get_method_return_comment (m);
1398 write_doc (get_method_comment (m));
1401 write_params_and_return (tag_name, params, m.get_type_parameters (), return_type, get_ccode_array_length (m), return_comment, false, m.this_parameter);
1405 buffer.append_printf ("</%s>\n", tag_name);
1408 public override void visit_creation_method (CreationMethod m) {
1409 if (m.external_package) {
1413 if (!check_accessibility (m)) {
1417 if (m.parent_symbol is Class && ((Class) m.parent_symbol).is_abstract) {
1423 bool is_struct = m.parent_symbol is Struct;
1424 // GI doesn't like constructors that return void type
1425 string tag_name = is_struct ? "method" : "constructor";
1427 if (m.parent_symbol is Class && m == ((Class)m.parent_symbol).default_construction_method ||
1428 m.parent_symbol is Struct && m == ((Struct)m.parent_symbol).default_construction_method) {
1429 string m_name = is_struct ? "init" : "new";
1430 buffer.append_printf ("<%s name=\"%s\" c:identifier=\"%s\"", tag_name, m_name, get_ccode_name (m));
1431 } else if (is_struct) {
1432 buffer.append_printf ("<%s name=\"init_%s\" c:identifier=\"%s\"", tag_name, m.name, get_ccode_name (m));
1434 buffer.append_printf ("<%s name=\"%s\" c:identifier=\"%s\"", tag_name, m.name, get_ccode_name (m));
1437 if (m.tree_can_fail) {
1438 buffer.append_printf (" throws=\"1\"");
1440 write_symbol_attributes (m);
1441 buffer.append_printf (">\n");
1444 write_doc (get_method_comment (m));
1446 var datatype = SemanticAnalyzer.get_data_type_for_symbol (m.parent_symbol);
1447 List<TypeParameter>? type_params = null;
1448 if (m.parent_symbol is Class) {
1449 type_params = ((Class) m.parent_symbol).get_type_parameters ();
1451 write_params_and_return (tag_name, m.get_parameters (), type_params, datatype, false, get_method_return_comment (m), true);
1455 buffer.append_printf ("</%s>\n", tag_name);
1458 public override void visit_property (Property prop) {
1459 if (!check_accessibility (prop) || prop.overrides || (prop.base_interface_property != null && !prop.is_abstract && !prop.is_virtual)) {
1463 if (context.analyzer.is_gobject_property (prop)) {
1465 buffer.append_printf ("<property name=\"%s\"", get_ccode_name (prop));
1466 if (prop.get_accessor == null) {
1467 buffer.append_printf (" readable=\"0\"");
1469 if (prop.set_accessor != null) {
1470 buffer.append_printf (" writable=\"1\"");
1471 if (prop.set_accessor.construction) {
1472 if (!prop.set_accessor.writable) {
1473 buffer.append_printf (" construct-only=\"1\"");
1475 buffer.append_printf (" construct=\"1\"");
1479 write_symbol_attributes (prop);
1480 buffer.append_printf (">\n");
1483 write_doc (get_property_comment (prop));
1485 write_type (prop.property_type);
1489 buffer.append_printf ("</property>\n");
1492 if (prop.get_accessor != null) {
1493 var m = prop.get_accessor.get_method ();
1499 if (prop.set_accessor != null) {
1500 var m = prop.set_accessor.get_method ();
1507 public override void visit_signal (Signal sig) {
1508 if (!check_accessibility (sig)) {
1512 if (sig.emitter != null) {
1513 sig.emitter.accept (this);
1516 if (sig.default_handler != null) {
1517 sig.default_handler.accept (this);
1521 buffer.append_printf ("<glib:signal name=\"%s\"", get_ccode_name (sig));
1522 write_symbol_attributes (sig);
1523 buffer.append_printf (">\n");
1526 write_doc (get_signal_comment (sig));
1528 write_params_and_return ("glib:signal", sig.get_parameters (), null, sig.return_type, false, get_signal_return_comment (sig));
1532 buffer.append_printf ("</glib:signal>\n");
1535 private void write_indent () {
1538 for (i = 0; i < indent; i++) {
1539 buffer.append_c ('\t');
1543 private void write_indent_stream () {
1546 for (i = 0; i < indent; i++) {
1552 private void write_param_or_return (DataType? type, string tag, ref int index, bool has_array_length, string? name = null, string? comment = null, ParameterDirection direction = ParameterDirection.IN, bool constructor = false, bool caller_allocates = false, bool ellipsis = false) {
1554 buffer.append_printf ("<%s", tag);
1559 buffer.append_printf (" name=\"%s\"", name);
1561 if (direction == ParameterDirection.REF) {
1562 buffer.append_printf (" direction=\"inout\"");
1563 } else if (direction == ParameterDirection.OUT) {
1564 buffer.append_printf (" direction=\"out\"");
1567 unowned DelegateType? delegate_type = type as DelegateType;
1568 unowned ArrayType? array_type = type as ArrayType;
1570 if (type != null && ((type.value_owned && delegate_type == null) || (constructor
1571 && !(type.type_symbol is Struct || type.type_symbol.is_subtype_of (ginitiallyunowned_type))))) {
1572 var any_owned = false;
1573 foreach (var generic_arg in type.get_type_arguments ()) {
1574 any_owned |= generic_arg.value_owned;
1576 if (type.has_type_arguments () && !any_owned) {
1577 buffer.append_printf (" transfer-ownership=\"container\"");
1578 } else if (array_type != null && !array_type.element_type.value_owned) {
1579 buffer.append_printf (" transfer-ownership=\"container\"");
1581 buffer.append_printf (" transfer-ownership=\"full\"");
1584 buffer.append_printf (" transfer-ownership=\"none\"");
1586 if (caller_allocates) {
1587 buffer.append_printf (" caller-allocates=\"1\"");
1589 if (type != null && type.nullable) {
1590 if (tag == "parameter"
1591 && (direction == ParameterDirection.OUT || direction == ParameterDirection.REF)) {
1592 buffer.append_printf (" optional=\"1\"");
1594 buffer.append_printf (" nullable=\"1\"");
1598 if (delegate_type != null && delegate_type.delegate_symbol.has_target) {
1599 int closure_index = tag == "parameter" ?
1600 index + 1 : (type.value_owned ? index - 1 : index);
1601 buffer.append_printf (" closure=\"%i\"", closure_index);
1602 if (delegate_type.is_called_once) {
1603 buffer.append (" scope=\"async\"");
1604 } else if (type.value_owned) {
1605 buffer.append_printf (" scope=\"notified\" destroy=\"%i\"", closure_index + 1);
1607 buffer.append (" scope=\"call\"");
1609 } else if (delegate_type != null) {
1610 buffer.append (" scope=\"call\"");
1613 buffer.append_printf (">\n");
1616 write_doc (comment);
1620 buffer.append ("<varargs/>\n");
1621 } else if (type != null) {
1622 int length_param_index = -1;
1623 if (has_array_length) {
1624 length_param_index = tag == "parameter" ? index + 1 : index;
1626 write_type (type, length_param_index, direction);
1631 buffer.append_printf ("</%s>\n", tag);
1635 private void write_ctype_attributes (TypeSymbol symbol, string suffix = "", bool symbol_prefix = false) {
1636 buffer.append_printf (" c:type=\"%s%s\"", get_ccode_name (symbol), suffix);
1637 if (symbol_prefix) {
1638 buffer.append_printf (" c:symbol-prefix=\"%s\"", get_ccode_lower_case_suffix (symbol));
1642 private void write_gtype_attributes (TypeSymbol symbol, bool symbol_prefix = false) {
1643 write_ctype_attributes(symbol, "", symbol_prefix);
1644 buffer.append_printf (" glib:type-name=\"%s\"", get_ccode_name (symbol));
1645 buffer.append_printf (" glib:get-type=\"%sget_type\"", get_ccode_lower_case_prefix (symbol));
1648 private void write_type (DataType type, int index = -1, ParameterDirection direction = ParameterDirection.IN) {
1649 if (type is ArrayType) {
1650 var array_type = (ArrayType) type;
1653 buffer.append_printf ("<array");
1654 if (array_type.fixed_length && array_type.length is IntegerLiteral) {
1655 var lit = (IntegerLiteral) array_type.length;
1656 buffer.append_printf (" fixed-size=\"%i\"", int.parse (lit.value));
1657 } else if (index != -1) {
1658 buffer.append_printf (" length=\"%i\"", index);
1660 buffer.append_printf (" c:type=\"%s%s\"", get_ccode_name (array_type.element_type), direction == ParameterDirection.IN ? "*" : "**");
1661 buffer.append_printf (">\n");
1664 write_type (array_type.element_type);
1668 buffer.append_printf ("</array>\n");
1669 } else if (type is VoidType) {
1671 buffer.append_printf ("<type name=\"none\" c:type=\"void\"/>\n");
1672 } else if (type is PointerType) {
1674 buffer.append_printf ("<type name=\"gpointer\" c:type=\"%s%s\"/>\n", get_ccode_name (type), direction == ParameterDirection.IN ? "" : "*");
1675 } else if (type is GenericType) {
1676 // generic type parameters not supported in GIR
1678 buffer.append ("<type name=\"gpointer\" c:type=\"gpointer\"/>\n");
1679 } else if (type is DelegateType) {
1680 var deleg_type = (DelegateType) type;
1682 buffer.append_printf ("<type name=\"%s\" c:type=\"%s%s\"/>\n", gi_type_name (deleg_type.delegate_symbol), get_ccode_name (type), direction == ParameterDirection.IN ? "" : "*");
1683 } else if (type.type_symbol != null) {
1685 string type_name = gi_type_name (type.type_symbol);
1686 bool is_array = false;
1687 if ((type_name == "GLib.Array") || (type_name == "GLib.PtrArray")) {
1690 buffer.append_printf ("<%s name=\"%s\" c:type=\"%s%s\"", is_array ? "array" : "type", gi_type_name (type.type_symbol), get_ccode_name (type), direction == ParameterDirection.IN ? "" : "*");
1692 List<DataType> type_arguments = type.get_type_arguments ();
1693 if (type_arguments.size == 0) {
1694 buffer.append_printf ("/>\n");
1696 buffer.append_printf (">\n");
1699 foreach (DataType type_argument in type_arguments) {
1700 write_type (type_argument);
1705 buffer.append_printf ("</%s>\n", is_array ? "array" : "type");
1709 buffer.append_printf ("<type name=\"%s\"/>\n", type.to_string ());
1713 private string? get_full_gir_name (Symbol sym) {
1714 string? gir_fullname = sym.get_attribute_string ("GIR", "fullname");
1715 if (gir_fullname != null) {
1716 return gir_fullname;
1719 string? gir_name = sym.get_attribute_string ("GIR", "name");
1721 if (gir_name == null && sym is Namespace) {
1722 gir_name = sym.get_attribute_string ("CCode", "gir_namespace");
1724 if (gir_name == null) {
1725 gir_name = sym.name;
1728 if (sym.parent_symbol == null) {
1732 if (sym.name == null) {
1733 return get_full_gir_name (sym.parent_symbol);
1736 string parent_gir_name = get_full_gir_name (sym.parent_symbol);
1737 if (parent_gir_name == null) {
1741 string self_gir_name = gir_name.has_prefix (".") ? gir_name.substring (1) : gir_name;
1742 if ("." in parent_gir_name) {
1743 return "%s%s".printf (parent_gir_name, self_gir_name);
1745 return "%s.%s".printf (parent_gir_name, self_gir_name);
1749 private string gi_type_name (TypeSymbol type_symbol) {
1750 Symbol parent = type_symbol.parent_symbol;
1751 if (parent is Namespace) {
1752 Namespace ns = parent as Namespace;
1753 var ns_gir_name = ns.get_attribute_string ("GIR", "name") ?? ns.name;
1754 if (ns_gir_name != null) {
1755 unowned SourceFile source_file = type_symbol.source_reference.file;
1756 if (source_file.gir_namespace != null) {
1757 GIRNamespace external;
1758 if (source_file.gir_ambiguous) {
1759 external = GIRNamespace.for_symbol (type_symbol);
1761 external = GIRNamespace (source_file.gir_namespace, source_file.gir_version);
1763 if (!externals.contains (external)) {
1764 externals.add (external);
1766 string? gir_fullname = type_symbol.get_attribute_string ("GIR", "fullname");
1767 if (gir_fullname != null) {
1768 return gir_fullname;
1770 var type_name = type_symbol.get_attribute_string ("GIR", "name") ?? type_symbol.name;
1771 return "%s.%s".printf (external.ns, type_name);
1773 unannotated_namespaces.add(ns);
1778 return get_full_gir_name (type_symbol);
1781 private string? literal_expression_to_value_string (Expression literal) {
1782 if (literal is StringLiteral) {
1783 var lit = literal as StringLiteral;
1785 return Markup.escape_text (lit.eval ());
1787 } else if (literal is CharacterLiteral) {
1788 return "%c".printf ((char) ((CharacterLiteral) literal).get_char ());
1789 } else if (literal is BooleanLiteral) {
1790 return ((BooleanLiteral) literal).value ? "true" : "false";
1791 } else if (literal is RealLiteral) {
1792 return ((RealLiteral) literal).value;
1793 } else if (literal is IntegerLiteral) {
1794 return ((IntegerLiteral) literal).value;
1795 } else if (literal is UnaryExpression) {
1796 var unary = (UnaryExpression) literal;
1797 if (unary.operator == UnaryOperator.MINUS) {
1798 if (unary.inner is RealLiteral) {
1799 return "-" + ((RealLiteral) unary.inner).value;
1800 } else if (unary.inner is IntegerLiteral) {
1801 return "-" + ((IntegerLiteral) unary.inner).value;
1808 private bool check_accessibility (Symbol sym) {
1809 if (sym.access == SymbolAccessibility.PUBLIC ||
1810 sym.access == SymbolAccessibility.PROTECTED) {
1814 // internal fields and function pointers in classes/interfaces are public API
1815 if (sym.access == SymbolAccessibility.INTERNAL) {
1816 unowned Symbol? parent = sym.parent_symbol;
1818 && (parent is Class || parent is Interface)
1819 && ((sym is Field && ((Field) sym).binding == MemberBinding.INSTANCE)
1820 || (sym is Method && ((Method) sym).binding == MemberBinding.INSTANCE && (((Method) sym).is_abstract || ((Method) sym).is_virtual)))) {
1828 private bool is_visibility (Symbol sym) {
1829 return sym.get_attribute_bool ("GIR", "visible", true);
1832 bool has_namespace (Symbol sym) {
1833 if (!(sym.parent_symbol is Namespace) || sym.parent_symbol.name != null) {
1837 Report.warning (sym.source_reference, "`%s' must be part of namespace to be included in GIR", sym.name);