remove obsolete ref modifier and callback keyword
[vala-lang.git] / vapigen / valagidlparser.vala
blobfcc5fd155965a5662a88a352b446b6317fe78e12
1 /* valagidlparser.vala
3 * Copyright (C) 2006-2007 Jürg Billeter, Raffaele Sandrini
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 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
19 * Author:
20 * Jürg Billeter <j@bitron.ch>
21 * Raffaele Sandrini <rasa@gmx.ch>
24 using GLib;
26 /**
27 * Code visitor parsing all GIDL files.
29 public class Vala.GIdlParser : CodeVisitor {
30 private SourceReference current_source_reference;
32 private DataType current_data_type;
33 private HashTable<string,string> codenode_attributes_map;
34 private HashTable<string,string> current_type_symbol_map;
36 /**
37 * Parse all source files in the specified code context and build a
38 * code tree.
40 * @param context a code context
42 public void parse (CodeContext! context) {
43 context.accept (this);
46 public override void visit_source_file (SourceFile! source_file) {
47 if (source_file.filename.has_suffix (".gidl")) {
48 parse_file (source_file);
52 private void parse_file (SourceFile! source_file) {
53 Error error = null;
55 string metadata_filename = "%s.metadata".printf (source_file.filename.ndup (source_file.filename.size () - ".gidl".size ()));
57 codenode_attributes_map = new HashTable.full (str_hash, str_equal, g_free, g_free);
59 if (FileUtils.test (metadata_filename, FileTest.EXISTS)) {
60 string metadata;
61 long metadata_len;
62 FileUtils.get_contents (metadata_filename, out metadata, out metadata_len, out error);
64 foreach (string line in metadata.split ("\n")) {
65 var line_parts = line.split (" ", 2);
66 if (line_parts[0] == null) {
67 continue;
70 codenode_attributes_map.insert (line_parts[0], line_parts[1]);
74 var modules = Idl.parse_file (source_file.filename, out error);
76 if (error != null) {
77 stdout.printf ("error parsing GIDL file: %s\n", error.message);
80 current_source_reference = new SourceReference (source_file);
82 foreach (IdlModule module in modules) {
83 var ns = parse_module (module);
84 source_file.add_namespace (ns);
88 private string! fix_type_name (string! type_name, IdlModule! module) {
89 if (type_name.has_prefix (module.name)) {
90 return type_name.offset (module.name.len ());
91 } else if (module.name == "GLib" && type_name.has_prefix ("G")) {
92 return type_name.offset (1);
94 return type_name;
97 private string! fix_const_name (string! const_name, IdlModule! module) {
98 if (const_name.has_prefix (module.name.up () + "_")) {
99 return const_name.offset (module.name.len () + 1);
100 } else if (module.name == "GLib" && const_name.has_prefix ("G_")) {
101 return const_name.offset (2);
103 return const_name;
106 private Namespace parse_module (IdlModule! module) {
107 var ns = new Namespace (module.name, current_source_reference);
109 var attributes = get_attributes (ns.name);
110 if (attributes != null) {
111 foreach (string attr in attributes) {
112 var nv = attr.split ("=", 2);
113 if (nv[0] == "cheader_filename") {
114 ns.set_cheader_filename (eval (nv[1]));
115 } else if (nv[0] == "cprefix") {
116 ns.set_cprefix (eval (nv[1]));
117 } else if (nv[0] == "lower_case_cprefix") {
118 ns.set_lower_case_cprefix (eval (nv[1]));
123 foreach (IdlNode node in module.entries) {
124 if (node.type == IdlNodeTypeId.CALLBACK) {
125 var cb = parse_callback ((IdlNodeFunction) node);
126 if (cb == null) {
127 continue;
129 cb.name = fix_type_name (cb.name, module);
130 ns.add_callback (cb);
131 } else if (node.type == IdlNodeTypeId.STRUCT) {
132 var st = parse_struct ((IdlNodeStruct) node);
133 if (st == null) {
134 continue;
136 st.name = fix_type_name (st.name, module);
137 ns.add_struct (st);
138 } else if (node.type == IdlNodeTypeId.BOXED) {
139 var st = parse_boxed ((IdlNodeBoxed) node);
140 st.name = fix_type_name (st.name, module);
141 ns.add_struct (st);
142 st.set_type_id (st.get_upper_case_cname ("TYPE_"));
143 } else if (node.type == IdlNodeTypeId.ENUM) {
144 var en = parse_enum ((IdlNodeEnum) node);
145 en.name = fix_type_name (en.name, module);
146 ns.add_enum (en);
147 } else if (node.type == IdlNodeTypeId.OBJECT) {
148 var cl = parse_object ((IdlNodeInterface) node);
149 cl.name = fix_type_name (cl.name, module);
150 ns.add_class (cl);
151 } else if (node.type == IdlNodeTypeId.INTERFACE) {
152 var iface = parse_interface ((IdlNodeInterface) node);
153 iface.name = fix_type_name (iface.name, module);
154 ns.add_interface (iface);
155 } else if (node.type == IdlNodeTypeId.CONSTANT) {
156 var c = parse_constant ((IdlNodeConstant) node);
157 c.name = fix_const_name (c.name, module);
158 ns.add_constant (c);
159 } else if (node.type == IdlNodeTypeId.FUNCTION) {
160 var m = parse_function ((IdlNodeFunction) node);
161 if (m != null) {
162 m.instance = false;
163 ns.add_method (m);
168 return ns;
171 private Callback parse_callback (IdlNodeFunction! f_node) {
172 weak IdlNode node = (IdlNode) f_node;
174 var attributes = get_attributes (node.name);
175 if (attributes != null) {
176 foreach (string attr in attributes) {
177 var nv = attr.split ("=", 2);
178 if (nv[0] == "hidden") {
179 if (eval (nv[1]) == "1") {
180 return null;
186 var cb = new Callback (node.name, parse_param (f_node.result), current_source_reference);
187 cb.access = MemberAccessibility.PUBLIC;
189 foreach (IdlNodeParam param in f_node.parameters) {
190 weak IdlNode param_node = (IdlNode) param;
192 var p = new FormalParameter (param_node.name, parse_param (param));
193 cb.add_parameter (p);
196 return cb;
199 private Struct parse_struct (IdlNodeStruct! st_node) {
200 weak IdlNode node = (IdlNode) st_node;
202 if (st_node.deprecated) {
203 return null;
206 var st = new Struct (node.name, current_source_reference);
207 st.access = MemberAccessibility.PUBLIC;
209 st.set_is_reference_type (true);
211 var st_attributes = get_attributes (node.name);
212 if (st_attributes != null) {
213 foreach (string attr in st_attributes) {
214 var nv = attr.split ("=", 2);
215 if (nv[0] == "is_value_type" && eval (nv[1]) == "1") {
216 st.set_is_reference_type (false);
221 current_data_type = st;
223 foreach (IdlNode member in st_node.members) {
224 if (member.type == IdlNodeTypeId.FUNCTION) {
225 var m = parse_function ((IdlNodeFunction) member);
226 if (m != null) {
227 st.add_method (m);
229 } else if (member.type == IdlNodeTypeId.FIELD) {
230 var f = parse_field ((IdlNodeField) member);
231 if (f != null) {
232 st.add_field (f);
237 current_data_type = null;
239 return st;
242 private Struct parse_boxed (IdlNodeBoxed! boxed_node) {
243 weak IdlNode node = (IdlNode) boxed_node;
245 var st = new Struct (node.name, current_source_reference);
246 st.access = MemberAccessibility.PUBLIC;
248 st.set_is_reference_type (true);
250 var st_attributes = get_attributes (node.name);
251 if (st_attributes != null) {
252 foreach (string attr in st_attributes) {
253 var nv = attr.split ("=", 2);
254 if (nv[0] == "is_value_type" && eval (nv[1]) == "1") {
255 st.set_is_reference_type (false);
260 current_data_type = st;
262 foreach (IdlNode member in boxed_node.members) {
263 if (member.type == IdlNodeTypeId.FUNCTION) {
264 var m = parse_function ((IdlNodeFunction) member);
265 if (m != null) {
266 st.add_method (m);
268 } else if (member.type == IdlNodeTypeId.FIELD) {
269 var f = parse_field ((IdlNodeField) member);
270 if (f != null) {
271 st.add_field (f);
276 current_data_type = null;
278 return st;
281 private Enum parse_enum (IdlNodeEnum! en_node) {
282 weak IdlNode node = (IdlNode) en_node;
284 var en = new Enum (node.name, current_source_reference);
285 en.access = MemberAccessibility.PUBLIC;
287 string common_prefix = null;
289 foreach (IdlNode value in en_node.values) {
290 if (common_prefix == null) {
291 common_prefix = value.name;
292 while (common_prefix.len () > 0 && !common_prefix.has_suffix ("_")) {
293 // FIXME: could easily be made faster
294 common_prefix = common_prefix.ndup (common_prefix.size () - 1);
296 } else {
297 while (!value.name.has_prefix (common_prefix)) {
298 common_prefix = common_prefix.ndup (common_prefix.size () - 1);
303 en.set_cprefix (common_prefix);
305 foreach (IdlNode value2 in en_node.values) {
306 var ev = new EnumValue (value2.name.offset (common_prefix.len ()));
307 en.add_value (ev);
310 return en;
313 private Class parse_object (IdlNodeInterface! node) {
314 var cl = new Class (node.gtype_name, current_source_reference);
315 cl.access = MemberAccessibility.PUBLIC;
317 var attributes = get_attributes (cl.name);
318 if (attributes != null) {
319 foreach (string attr in attributes) {
320 var nv = attr.split ("=", 2);
321 if (nv[0] == "cheader_filename") {
322 cl.add_cheader_filename (eval (nv[1]));
327 if (node.parent != null) {
328 var parent = new TypeReference ();
329 parse_type_string (parent, node.parent);
330 cl.add_base_type (parent);
333 foreach (string iface_name in node.interfaces) {
334 var iface = new TypeReference ();
335 parse_type_string (iface, iface_name);
336 cl.add_base_type (iface);
339 current_data_type = cl;
341 current_type_symbol_map = new HashTable<string,string>.full (str_hash, str_equal, g_free, g_free);
342 var current_type_vfunc_map = new HashTable<string,string>.full (str_hash, str_equal, g_free, g_free);
344 foreach (IdlNode member in node.members) {
345 if (member.type == IdlNodeTypeId.VFUNC) {
346 current_type_vfunc_map.insert (member.name, "1");
350 foreach (IdlNode member in node.members) {
351 if (member.type == IdlNodeTypeId.FUNCTION) {
352 bool is_virtual = current_type_vfunc_map.lookup (member.name) != null;
354 var m = parse_function ((IdlNodeFunction) member, is_virtual);
355 if (m != null) {
356 cl.add_method (m);
358 } else if (member.type == IdlNodeTypeId.PROPERTY) {
359 var prop = parse_property ((IdlNodeProperty) member);
360 if (prop != null) {
361 cl.add_property (prop);
363 } else if (member.type == IdlNodeTypeId.SIGNAL) {
364 var sig = parse_signal ((IdlNodeSignal) member);
365 if (sig != null) {
366 cl.add_signal (sig);
371 foreach (IdlNode member in node.members) {
372 if (member.type == IdlNodeTypeId.FIELD) {
373 if (current_type_symbol_map.lookup (member.name) == null) {
374 var f = parse_field ((IdlNodeField) member);
375 if (f != null) {
376 cl.add_field (f);
382 foreach (Property prop in cl.get_properties ()) {
383 var getter = "get_%s".printf (prop.name);
385 if (prop.get_accessor != null && current_type_symbol_map.lookup (getter) == null) {
386 prop.no_accessor_method = true;
389 var setter = "set_%s".printf (prop.name);
391 if (prop.set_accessor != null && current_type_symbol_map.lookup (setter) == null) {
392 prop.no_accessor_method = true;
396 current_data_type = null;
397 current_type_symbol_map = null;
399 return cl;
402 private Interface parse_interface (IdlNodeInterface! node) {
403 var iface = new Interface (node.gtype_name, current_source_reference);
404 iface.access = MemberAccessibility.PUBLIC;
406 var attributes = get_attributes (iface.name);
407 if (attributes != null) {
408 foreach (string attr in attributes) {
409 var nv = attr.split ("=", 2);
410 if (nv[0] == "cheader_filename") {
411 iface.add_cheader_filename (eval (nv[1]));
416 foreach (string prereq_name in node.prerequisites) {
417 var prereq = new TypeReference ();
418 parse_type_string (prereq, prereq_name);
419 iface.add_prerequisite (prereq);
422 current_data_type = iface;
424 var current_type_vfunc_map = new HashTable<string,string>.full (str_hash, str_equal, g_free, g_free);
425 foreach (IdlNode member in node.members) {
426 if (member.type == IdlNodeTypeId.VFUNC) {
427 current_type_vfunc_map.insert (member.name, "1");
431 foreach (IdlNode member in node.members) {
432 if (member.type == IdlNodeTypeId.FUNCTION) {
433 bool is_virtual = current_type_vfunc_map.lookup (member.name) != null;
435 var m = parse_function ((IdlNodeFunction) member, is_virtual);
436 if (m != null) {
437 iface.add_method (m);
439 } else if (member.type == IdlNodeTypeId.SIGNAL) {
440 var sig = parse_signal ((IdlNodeSignal) member);
441 if (sig != null) {
442 iface.add_signal (sig);
447 current_data_type = null;
449 return iface;
452 private TypeReference parse_type (IdlNodeType! type_node) {
453 var type = new TypeReference ();
454 if (type_node.tag == TypeTag.VOID) {
455 if (type_node.is_pointer) {
456 type.type_name = "pointer";
457 } else {
458 type.type_name = "void";
460 } else if (type_node.tag == TypeTag.BOOLEAN) {
461 type.type_name = "bool";
462 } else if (type_node.tag == TypeTag.INT8) {
463 type.type_name = "char";
464 } else if (type_node.tag == TypeTag.UINT8) {
465 type.type_name = "uchar";
466 } else if (type_node.tag == TypeTag.INT16) {
467 type.type_name = "short";
468 } else if (type_node.tag == TypeTag.UINT16) {
469 type.type_name = "ushort";
470 } else if (type_node.tag == TypeTag.INT32) {
471 type.type_name = "int";
472 } else if (type_node.tag == TypeTag.UINT32) {
473 type.type_name = "uint";
474 } else if (type_node.tag == TypeTag.INT64) {
475 type.type_name = "int64";
476 } else if (type_node.tag == TypeTag.UINT64) {
477 type.type_name = "uint64";
478 } else if (type_node.tag == TypeTag.INT) {
479 type.type_name = "int";
480 } else if (type_node.tag == TypeTag.UINT) {
481 type.type_name = "uint";
482 } else if (type_node.tag == TypeTag.LONG) {
483 type.type_name = "long";
484 } else if (type_node.tag == TypeTag.ULONG) {
485 type.type_name = "ulong";
486 } else if (type_node.tag == TypeTag.SSIZE) {
487 type.type_name = "long";
488 } else if (type_node.tag == TypeTag.SIZE) {
489 type.type_name = "ulong";
490 } else if (type_node.tag == TypeTag.FLOAT) {
491 type.type_name = "float";
492 } else if (type_node.tag == TypeTag.DOUBLE) {
493 type.type_name = "double";
494 } else if (type_node.tag == TypeTag.UTF8) {
495 type.type_name = "string";
496 } else if (type_node.tag == TypeTag.FILENAME) {
497 type.type_name = "string";
498 } else if (type_node.tag == TypeTag.ARRAY) {
499 type = parse_type (type_node.parameter_type1);
500 type.array_rank = 1;
501 } else if (type_node.tag == TypeTag.LIST) {
502 type.namespace_name = "GLib";
503 type.type_name = "List";
504 } else if (type_node.tag == TypeTag.SLIST) {
505 type.namespace_name = "GLib";
506 type.type_name = "SList";
507 } else if (type_node.tag == TypeTag.HASH) {
508 type.namespace_name = "GLib";
509 type.type_name = "HashTable";
510 } else if (type_node.tag == TypeTag.ERROR) {
511 type.namespace_name = "GLib";
512 type.type_name = "Error";
513 } else if (type_node.is_interface) {
514 var n = type_node.@interface;
516 if (n == "") {
517 return null;
520 if (n.has_prefix ("const-")) {
521 n = n.offset ("const-".len ());
524 if (type_node.is_pointer &&
525 (n == "gchar" || n == "char")) {
526 type.type_name = "string";
527 } else if (n == "gunichar") {
528 type.type_name = "unichar";
529 } else if (n == "gchar") {
530 type.type_name = "char";
531 } else if (n == "guchar" || n == "guint8") {
532 type.type_name = "uchar";
533 if (type_node.is_pointer) {
534 type.array_rank = 1;
536 } else if (n == "gushort") {
537 type.type_name = "ushort";
538 } else if (n == "gshort") {
539 type.type_name = "short";
540 } else if (n == "gconstpointer" || n == "void") {
541 type.type_name = "pointer";
542 } else if (n == "goffset") {
543 type.type_name = "int64";
544 } else if (n == "value_array") {
545 type.namespace_name = "GLib";
546 type.type_name = "ValueArray";
547 } else if (n == "time_t") {
548 type.type_name = "ulong";
549 } else if (n == "pid_t") {
550 type.type_name = "int";
551 } else if (n == "FILE") {
552 type.namespace_name = "GLib";
553 type.type_name = "FileStream";
554 } else {
555 parse_type_string (type, n);
556 if (type_node.is_pointer && is_value_type (n)) {
557 type.is_out = true;
560 } else {
561 stdout.printf ("%d\n", type_node.tag);
563 return type;
566 private bool is_value_type (string! type_name) {
567 // FIXME only works if both types are in current package, e.g. doesn't work when Gtk uses GdkRectangle
568 var type_attributes = get_attributes (type_name);
569 if (type_attributes != null) {
570 foreach (string attr in type_attributes) {
571 var nv = attr.split ("=", 2);
572 if (nv[0] == "is_value_type" && eval (nv[1]) == "1") {
573 return true;
578 return false;
581 private void parse_type_string (TypeReference! type, string! n) {
582 // Generated GIDL misses explicit namespace specifier,
583 // so try to guess namespace
584 if (n.has_prefix ("H") || n.has_suffix ("Class") || n == "va_list" || n.has_prefix ("LOGFONT")) {
585 // unsupported
586 type.type_name = "pointer";
587 } else if (n.has_prefix ("cairo")) {
588 type.namespace_name = "Cairo";
589 if (n == "cairo_t") {
590 type.type_name = "Context";
591 } else if (n == "cairo_surface_t") {
592 type.type_name = "Surface";
593 } else {
594 type.namespace_name = null;
595 type.type_name = "pointer";
597 } else if (n.has_prefix ("Atk")) {
598 type.namespace_name = "Atk";
599 type.type_name = n.offset ("Atk".len ());
600 if (type.type_name == "AttributeSet") {
601 type.namespace_name = "GLib";
602 type.type_name = "SList";
604 } else if (n.has_prefix ("Gtk")) {
605 type.namespace_name = "Gtk";
606 type.type_name = n.offset ("Gtk".len ());
607 if (type.type_name == "TextLayout") {
608 type.namespace_name = null;
609 type.type_name = "pointer";
611 } else if (n.has_prefix ("Gdk")) {
612 type.namespace_name = "Gdk";
613 type.type_name = n.offset ("Gdk".len ());
614 if (type.type_name == "NativeWindow" || type.type_name == "XEvent") {
615 type.namespace_name = null;
616 type.type_name = "pointer";
618 } else if (n.has_prefix ("Pango")) {
619 type.namespace_name = "Pango";
620 type.type_name = n.offset ("Pango".len ());
621 if (type.type_name == "Glyph") {
622 type.namespace_name = null;
623 type.type_name = "uint";
624 } else if (type.type_name == "GlyphUnit") {
625 type.namespace_name = null;
626 type.type_name = "int";
628 } else if (n.has_prefix ("Vte")) {
629 type.namespace_name = "Vte";
630 type.type_name = n.offset ("Vte".len ());
631 } else if (n.has_prefix ("Goo")) {
632 type.namespace_name = "Goo";
633 type.type_name = n.offset ("Goo".len ());
634 } else if (n.has_prefix ("G")) {
635 type.namespace_name = "GLib";
636 type.type_name = n.offset ("G".len ());
637 if (type.type_name == "Strv") {
638 type.namespace_name = null;
639 type.type_name = "string";
640 type.array_rank = 1;
642 } else {
643 var name_parts = n.split (".", 2);
644 if (name_parts[1] == null) {
645 type.type_name = name_parts[0];
646 } else {
647 type.namespace_name = name_parts[0];
648 type.type_name = name_parts[1];
653 private TypeReference parse_param (IdlNodeParam! param) {
654 var type = parse_type (param.type);
656 // disable for now as null_ok not yet correctly set
657 // type.non_null = !param.null_ok;
659 return type;
662 private Method parse_function (IdlNodeFunction! f, bool is_virtual = false) {
663 weak IdlNode node = (IdlNode) f;
665 if (f.deprecated) {
666 return null;
669 TypeReference return_type = null;
670 if (f.result != null) {
671 return_type = parse_param (f.result);
674 Method m;
675 if (f.is_constructor || node.name.has_prefix ("new")) {
676 m = new CreationMethod (node.name, current_source_reference);
677 if (m.name == "new") {
678 m.name = null;
679 } else if (m.name.has_prefix ("new_")) {
680 m.name = m.name.offset ("new_".len ());
682 } else {
683 m = new Method (node.name, return_type, current_source_reference);
685 m.access = MemberAccessibility.PUBLIC;
687 m.is_virtual = is_virtual;
689 // GIDL generator can't provide array parameter information yet
690 m.no_array_length = true;
692 if (current_type_symbol_map != null) {
693 current_type_symbol_map.insert (node.name, "1");
696 if (current_data_type != null) {
697 var sig_attributes = get_attributes ("%s::%s".printf (current_data_type.name, node.name));
698 if (sig_attributes != null) {
699 foreach (string attr in sig_attributes) {
700 var nv = attr.split ("=", 2);
701 if (nv[0] == "has_emitter" && eval (nv[1]) == "1") {
702 return null;
708 bool add_ellipsis = false;
710 var attributes = get_attributes (f.symbol);
711 if (attributes != null) {
712 foreach (string attr in attributes) {
713 var nv = attr.split ("=", 2);
714 if (nv[0] == "hidden") {
715 if (eval (nv[1]) == "1") {
716 return null;
718 } else if (nv[0] == "ellipsis") {
719 if (eval (nv[1]) == "1") {
720 add_ellipsis = true;
726 m.set_cname (f.symbol);
728 bool first = true;
729 FormalParameter last_param = null;
730 foreach (IdlNodeParam param in f.parameters) {
731 weak IdlNode param_node = (IdlNode) param;
733 if (first) {
734 first = false;
735 if (current_data_type != null &&
736 param.type.is_interface &&
737 (param_node.name == "self" ||
738 param.type.@interface.has_suffix (current_data_type.name))) {
739 // instance method
741 if (!current_data_type.is_reference_type () &&
742 param.type.is_pointer) {
743 m.instance_by_reference = true;
746 continue;
747 } else {
748 // static method
749 m.instance = false;
753 var p = new FormalParameter (param_node.name, parse_param (param));
754 m.add_parameter (p);
756 if (last_param != null && p.name == "n_" + last_param.name) {
757 // last_param is array, p is array length
758 last_param.type_reference.array_rank = 1;
759 last_param.type_reference.is_out = false;
762 last_param = p;
765 if (first) {
766 // no parameters => static method
767 m.instance = false;
770 if (add_ellipsis) {
771 m.add_parameter (new FormalParameter.with_ellipsis ());
774 return m;
777 private string! fix_prop_name (string name) {
778 var str = new String ();
780 string i = name;
782 while (i.len () > 0) {
783 unichar c = i.get_char ();
784 if (c == '-') {
785 str.append_c ('_');
786 } else {
787 str.append_unichar (c);
790 i = i.next_char ();
793 return str.str;
796 private Property parse_property (IdlNodeProperty! prop_node) {
797 weak IdlNode node = (IdlNode) prop_node;
799 if (prop_node.deprecated) {
800 return null;
803 if (!prop_node.readable && !prop_node.writable) {
804 // buggy GIDL definition
805 prop_node.readable = true;
806 prop_node.writable = true;
809 PropertyAccessor get_acc = null;
810 PropertyAccessor set_acc = null;
811 if (prop_node.readable) {
812 get_acc = new PropertyAccessor (true, false, false, null, null);
814 if (prop_node.writable) {
815 set_acc = new PropertyAccessor (false, false, false, null, null);
816 if (prop_node.construct_only) {
817 set_acc.construction = true;
818 } else {
819 set_acc.writable = true;
820 set_acc.construction = prop_node.@construct;
824 var prop = new Property (fix_prop_name (node.name), parse_type (prop_node.type), get_acc, set_acc, current_source_reference);
825 prop.access = MemberAccessibility.PUBLIC;
826 prop.interface_only = true;
828 if (current_type_symbol_map != null) {
829 current_type_symbol_map.insert (prop.name, "1");
832 return prop;
835 private Constant parse_constant (IdlNodeConstant! const_node) {
836 weak IdlNode node = (IdlNode) const_node;
838 var type = parse_type (const_node.type);
839 if (type == null) {
840 return null;
843 var c = new Constant (node.name, type, null, current_source_reference);
845 return c;
848 private Field parse_field (IdlNodeField! field_node) {
849 weak IdlNode node = (IdlNode) field_node;
851 var type = parse_type (field_node.type);
852 if (type == null) {
853 return null;
856 if (!field_node.readable) {
857 return null;
860 if (current_type_symbol_map != null) {
861 current_type_symbol_map.insert (node.name, "1");
864 var field = new Field (node.name, type, null, current_source_reference);
865 field.access = MemberAccessibility.PUBLIC;
867 return field;
870 [NoArrayLength]
871 private string[] get_attributes (string! codenode) {
872 string attributes = codenode_attributes_map.lookup (codenode);
873 if (attributes == null) {
874 return null;
877 return attributes.split (" ");
880 private string eval (string! s) {
881 return s.offset (1).ndup (s.size () - 2);
884 private Signal parse_signal (IdlNodeSignal! sig_node) {
885 weak IdlNode node = (IdlNode) sig_node;
887 if (sig_node.deprecated || sig_node.result == null) {
888 return null;
891 var sig = new Signal (fix_prop_name (node.name), parse_param (sig_node.result), current_source_reference);
892 sig.access = MemberAccessibility.PUBLIC;
894 var attributes = get_attributes ("%s::%s".printf (current_data_type.name, sig.name));
895 if (attributes != null) {
896 foreach (string attr in attributes) {
897 var nv = attr.split ("=", 2);
898 if (nv[0] == "name") {
899 sig.set_cname (sig.name);
900 sig.name = eval (nv[1]);
901 } else if (nv[0] == "has_emitter" && eval (nv[1]) == "1") {
902 sig.has_emitter = true;
903 } else if (nv[0] == "hidden") {
904 if (eval (nv[1]) == "1") {
905 return null;
911 bool first = true;
913 foreach (IdlNodeParam param in sig_node.parameters) {
914 if (first) {
915 // ignore implicit first signal parameter (sender)
916 first = false;
917 continue;
920 weak IdlNode param_node = (IdlNode) param;
922 var p = new FormalParameter (param_node.name, parse_param (param));
923 sig.add_parameter (p);
926 return sig;