3 // valac -g --pkg libvala-0.26 --pkg gee-1.0 --pkg json-glib-1.0 --pkg gtk+-3.0 VapiParser.vala Gir.vala GirObject.vala -o /tmp/vdoc
7 public errordomain VapiParserError {
12 public class VapiParser : Vala.CodeVisitor {
14 Vala.CodeContext context;
18 public VapiParser(Project.Gtk project) {
20 this.project = project;
21 // should not really happen..
22 if (project.gir_cache == null) {
23 project.gir_cache = new Gee.HashMap<string,Gir>();
28 public override void visit_namespace (Vala.Namespace element)
30 if (element == null) {
36 //print("parsing namespace %s\n", element.name);
37 if (element.name == null) {
38 element.accept_children(this); // catch sub namespaces..
41 this.add_namespace(null, element);
43 public void add_namespace(GirObject? parent, Vala.Namespace element)
47 var g = new GirObject("Package",element.name) ;
49 this.project.gir_cache.set(element.name, g);
51 // we add it as a class of the package.. even though its a namespace..
52 parent.classes.set(element.name, g);
56 foreach(var c in element.get_classes()) {
59 foreach(var c in element.get_enums()) {
62 foreach(var c in element.get_interfaces()) {
63 this.add_interface(g, c);
65 foreach(var c in element.get_namespaces()) {
66 this.add_namespace(g, c);
68 foreach(var c in element.get_methods()) {
69 this.add_method(g, c);
72 foreach(var c in element.get_structs()) {
73 this.add_struct(g, c);
75 foreach(var c in element.get_delegates()) {
76 this.add_delegate(g, c);
78 element.accept_children(this); // catch sub namespaces..
84 public void add_enum(GirObject parent, Vala.Enum cls)
87 var c = new GirObject("Enum", cls.name);
88 parent.consts.set(cls.name, c);
93 foreach(var e in cls.get_values()) {
94 var em = new GirObject("EnumMember",e.name);
99 em.type = e.type_reference == null || e.type_reference.type_symbol == null ? "" : e.type_reference.type_symbol.get_full_name();
101 em.type = e.type_reference == null || e.type_reference.data_type == null ? "" : e.type_reference.data_type.get_full_name();
105 // unlikely to get value..
106 //c.value = element->get_prop("value");
107 c.consts.set(e.name,em);
113 public void add_interface(GirObject parent, Vala.Interface cls)
116 var c = new GirObject("Interface", parent.name + "." + cls.name);
117 parent.classes.set(cls.name, c);
119 //c.parent = cls.base_class == null ? "" : cls.base_class.get_full_name() ; // extends...
122 foreach(var p in cls.get_properties()) {
123 this.add_property(c, p);
126 foreach(var p in cls.get_signals()) {
127 this.add_signal(c, p);
130 foreach(var p in cls.get_methods()) {
131 // skip static methods..
132 if (p.binding != Vala.MemberBinding.INSTANCE &&
133 !(p is Vala.CreationMethod)
138 this.add_method(c, p);
141 //if (cls.base_class != null) {
142 // c.inherits.add(cls.base_class.get_full_name());
144 //foreach(var p in cls.get_base_types()) {
145 // if (p.data_type != null) {
146 // c.implements.add(p.data_type.get_full_name());
154 //https://learnxinyminutes.com/docs/vala/ -- see for ctor on structs.
156 public void add_struct(GirObject parent, Vala.Struct cls)
159 var c = new GirObject("Struct", parent.name + "." + cls.name);
160 parent.classes.set(cls.name, c);
162 foreach(var p in cls.get_fields()) {
163 this.add_field(c, p);
169 if (cls.version.deprecated) {
170 GLib.debug("class %s is deprecated", c.name);
171 c.is_deprecated = true;
178 public void add_class(GirObject parent, Vala.Class cls)
181 var c = new GirObject("Class", parent.name + "." + cls.name);
182 parent.classes.set(cls.name, c);
184 c.parent = cls.base_class == null ? "" : cls.base_class.get_full_name() ; // extends...
186 c.is_abstract = cls.is_abstract;
187 foreach(var p in cls.get_properties()) {
188 this.add_property(c, p);
191 foreach(var p in cls.get_signals()) {
192 this.add_signal(c, p);
195 foreach(var p in cls.get_methods()) {
196 // skip static methods..
197 if (p.binding != Vala.MemberBinding.INSTANCE &&
198 !(p is Vala.CreationMethod)
203 this.add_method(c, p);
206 if (cls.base_class != null) {
207 c.inherits.add(cls.base_class.get_full_name());
209 foreach(var p in cls.get_base_types()) {
211 if (p.type_symbol != null) {
212 c.implements.add(p.type_symbol.get_full_name());
215 if (p.data_type != null) {
216 c.implements.add(p.data_type.get_full_name());
223 if (cls.version.deprecated) {
224 GLib.debug("class %s is deprecated", c.name);
225 c.is_deprecated = true;
230 public GirObject? fqn_to_cls(string fqn)
232 var ar = fqn.split(".");
233 var pkg = this.project.gir_cache.get(ar[0]);
234 var cls = pkg != null ? pkg.classes.get(ar[1]) : null;
238 public void augment_inherits_for(GirObject cls, Gee.ArrayList<string> to_check, bool is_top)
240 foreach (var chk_cls in to_check) {
241 if (!cls.inherits.contains(chk_cls)) {
242 cls.inherits.add(chk_cls);
251 var subcls = this.fqn_to_cls(chk_cls);
252 if (subcls == null) {
255 this.augment_inherits_for(cls, subcls.inherits, false);
256 this.augment_implements_for(cls, subcls.implements);
260 public void augment_implements_for(GirObject cls, Gee.ArrayList<string> to_check)
262 foreach (var chk_cls in to_check) {
263 if (cls.implements.contains(chk_cls)) {
266 cls.implements.add(chk_cls);
268 var subcls = this.fqn_to_cls(chk_cls);
269 if (subcls == null) {
272 this.augment_implements_for(cls, subcls.implements);
278 // this might miss out interfaces of child classes?
279 public void augment_all_inheritence()
281 // this works out all the children...
282 foreach(var pkgname in this.project.gir_cache.keys) {
284 var pkg = this.project.gir_cache.get(pkgname);
285 foreach (var clsname in pkg.classes.keys) {
286 var cls = pkg.classes.get(clsname);
287 this.augment_inherits_for(cls, cls.inherits, true);
288 this.augment_implements_for(cls, cls.implements);
291 // now do the implementations
292 foreach(var pkgname in this.project.gir_cache.keys) {
294 var pkg = this.project.gir_cache.get(pkgname);
295 foreach (var clsname in pkg.classes.keys) {
296 var cls = pkg.classes.get(clsname);
297 foreach(var parentname in cls.inherits) {
298 var parent = this.fqn_to_cls(parentname);
299 if (parent == null) {
302 if (parent.implementations.contains(cls.fqn())) {
305 parent.implementations.add(cls.fqn());
308 foreach(var parentname in cls.implements) {
309 var parent = this.fqn_to_cls(parentname);
310 if (parent == null) {
313 if (parent.implementations.contains(cls.fqn())) {
316 parent.implementations.add(cls.fqn());
326 public void add_property(GirObject parent, Vala.Property prop)
328 var c = new GirObject("Prop",prop.name);
331 c.propertyof = parent.name;
333 c.type = prop.property_type.type_symbol == null ? "" : prop.property_type.type_symbol.get_full_name();
335 c.type = prop.property_type.data_type == null ? "" : prop.property_type.data_type.get_full_name();
337 c.is_readable = prop.get_accessor != null ? prop.get_accessor.readable : false;
338 c.is_writable = prop.set_accessor != null ? prop.set_accessor.writable || prop.set_accessor.construction : false;
339 //if (prop.name == "child") {
340 // GLib.debug("prop child : w%s r%s", c.is_writable ? "YES" : "n" , c.is_readable ? "YES" : "n");
342 if (prop.version.deprecated) {
343 GLib.debug("class %s is deprecated", c.name);
344 c.is_deprecated = true;
346 parent.props.set(prop.name,c);
352 public void add_field(GirObject parent, Vala.Field prop)
354 var c = new GirObject("Field",prop.name);
357 c.propertyof = parent.name;
359 c.type = prop.variable_type.type_symbol == null ? "" : prop.variable_type.type_symbol.get_full_name();
361 c.type = prop.variable_type.data_type == null ? "" : prop.variable_type.data_type.get_full_name();
364 if (prop.version.deprecated) {
365 GLib.debug("class %s is deprecated", c.name);
366 c.is_deprecated = true;
368 parent.props.set(prop.name,c);
372 public void add_delegate(GirObject parent, Vala.Delegate sig)
375 var c = new GirObject("Delegate", sig.name);
378 c.propertyof = parent.name;
380 var dt = sig.return_type.type_symbol ;
382 var dt = sig.return_type.data_type;
384 if (sig.version.deprecated) {
385 GLib.debug("class %s is deprecated", c.name);
386 c.is_deprecated = true;
392 //print("creating return type on signal %s\n", sig.name);
393 var cc = new GirObject("Return", "return-value");
396 cc.type = dt.get_full_name();
398 c.type = dt.get_full_name(); // type is really return type in this scenario.
399 retval = "\treturn " + cc.type +";";
401 parent.delegates.set(sig.name,c);
403 var params = sig.get_parameters() ;
404 if (params.size < 1) {
406 c.sig = "( ) => {\n\n"+ retval + "\n}\n";
410 var cc = new GirObject("Paramset",sig.name); // what's the name on this?
416 foreach(var p in params) {
417 this.add_param(cc, p);
418 args += args.length > 0 ? ", " : "";
421 // add c.sig -> this is the empty
422 c.sig = "(" + args + ") => {\n\n"+ retval + "\n}\n";
431 public void add_signal(GirObject parent, Vala.Signal sig)
433 var c = new GirObject("Signal",sig.name);
436 c.propertyof = parent.name;
438 var dt = sig.return_type.type_symbol ;
440 var dt = sig.return_type.data_type;
442 if (sig.version.deprecated) {
443 GLib.debug("class %s is deprecated", c.name);
444 c.is_deprecated = true;
450 //print("creating return type on signal %s\n", sig.name);
451 var cc = new GirObject("Return", "return-value");
454 cc.type = dt.get_full_name();
456 c.type = dt.get_full_name(); // type is really return type in this scenario.
457 retval = "\treturn " + cc.type +";";
459 parent.signals.set(sig.name,c);
461 var params = sig.get_parameters() ;
462 if (params.size < 1) {
464 c.sig = "( ) => {\n\n"+ retval + "\n}\n";
468 var cc = new GirObject("Paramset",sig.name); // what's the name on this?
474 foreach(var p in params) {
475 this.add_param(cc, p);
476 args += args.length > 0 ? ", " : "";
479 // add c.sig -> this is the empty
480 c.sig = "(" + args + ") => {\n\n"+ retval + "\n}\n";
486 public void add_method(GirObject parent, Vala.Method met)
488 var n = met.name == null ? "" : met.name;
490 if (met is Vala.CreationMethod) {
492 if(n == "" || n == ".new") {
497 //print("add_method : %s\n", n);
499 var c = new GirObject(ty,n);
503 if (met.return_type.type_symbol != null) {
505 if (met.return_type.data_type != null) {
509 //print("creating return type on method %s\n", met.name);
510 var cc = new GirObject("Return", "return-value");
515 cc.type = met.return_type.type_symbol.get_full_name();
517 cc.type = met.return_type.data_type.get_full_name();
524 if (met is Vala.CreationMethod) {
525 parent.ctors.set(c.name,c);
527 parent.methods.set(met.name,c);
530 var params = met.get_parameters() ;
531 if (params.size < 1) {
534 var cc = new GirObject("Paramset",met.name); // what's the name on this?
540 foreach(var p in params) {
541 if (p.name == null && !p.ellipsis) {
544 var pp = this.add_param(cc, p);
545 c.sig += (c.sig == "(" ? "" : ",");
546 c.sig += " " + (pp.direction == "in" ? "" : pp.direction) + " " + pp.type + " " + pp.name;
548 c.sig += (c.sig == "(" ? ")" : " )");
552 public GirObject add_param(GirObject parent, Vala.Parameter pam)
559 var c = new GirObject("Param",n);
563 switch (pam.direction) {
564 case Vala.ParameterDirection.IN:
567 case Vala.ParameterDirection.OUT:
570 case Vala.ParameterDirection.REF:
575 parent.params.add(c);
579 c.type = pam.variable_type.type_symbol == null ? "" : pam.variable_type.type_symbol.get_full_name();
581 c.type = pam.variable_type.data_type == null ? "" : pam.variable_type.data_type.get_full_name();
584 Gir.checkParamOverride(c);
594 public Gee.ArrayList<string> fillDeps(Gee.ArrayList<string> in_ar)
596 var ret = new Gee.ArrayList<string>();
597 foreach(var k in in_ar) {
598 if (!ret.contains(k)) {
601 var deps = this.loadDeps(k);
602 // hopefully dont need to recurse through these..
603 for(var i =0;i< deps.length;i++) {
604 if (!ret.contains(deps[i])) {
616 public string[] loadDeps(string n)
618 // only try two? = we are ignoreing our configDirectory?
620 var fn = "/usr/share/vala-0.%d/vapi/%s.deps".printf(this.vala_version, n);
621 if (!FileUtils.test (fn, FileTest.EXISTS)) {
625 fn = "/usr/share/vala/vapi/%s.deps".printf( n);
626 if (!FileUtils.test (fn, FileTest.EXISTS)) {
632 FileUtils.get_contents(fn, out ostr);
633 } catch (GLib.Error e) {
634 GLib.debug("failed loading deps %s", e.message);
637 return ostr.split("\n");
644 public void create_valac_tree( )
647 context = new Vala.CodeContext ();
648 Vala.CodeContext.push (context);
650 context.experimental = false;
651 context.experimental_non_null = false;
654 //for (int i = 2; i <= ver; i += 2) {
655 // context.add_define ("VALA_0_%d".printf (i));
659 //var vapidirs = ((Project.Gtk)this.file.project).vapidirs();
660 // what's the current version of vala???
663 //vapidirs += Path.get_dirname (context.get_vapi_path("glib-2.0")) ;
665 var vapidirs = context.vapi_directories;
667 vapidirs += (BuilderApplication.configDirectory() + "/resources/vapi");
668 vapidirs += "/usr/share/vala-0.%d/vapi".printf(this.vala_version);
669 vapidirs += "/usr/share/vala/vapi";
670 context.vapi_directories = vapidirs;
672 // or context.get_vapi_path("glib-2.0"); // should return path..
673 //context.vapi_directories = vapidirs;
674 context.report.enable_warnings = true;
675 context.metadata_directories = { };
676 context.gir_directories = {};
677 //context.thread = true;
680 //this.report = new ValaSourceReport(this.file);
681 //context.report = this.report;
684 context.basedir = "/tmp"; //Posix.realpath (".");
686 context.directory = context.basedir;
689 // add default packages:
690 //if (settings.profile == "gobject-2.0" || settings.profile == "gobject" || settings.profile == null) {
692 context.set_target_profile (Vala.Profile.GOBJECT);
694 context.profile = Vala.Profile.GOBJECT;
697 var ns_ref = new Vala.UsingDirective (new Vala.UnresolvedSymbol (null, "GLib", null));
698 context.root.add_using_directive (ns_ref);
701 context.add_external_package ("glib-2.0");
702 context.add_external_package ("gobject-2.0");
703 // user defined ones..
707 var pkgs = this.fillDeps(this.project.packages);
710 for (var i = 0; i < pkgs.size; i++) {
712 var pkg = pkgs.get(i);
713 // do not add libvala versions except the one that matches the one we are compiled against..
714 if (Regex.match_simple("^libvala", pkg) && pkg != ("libvala-0." + vala_version.to_string())) {
717 //valac += " --pkg " + dcg.packages.get(i);
718 if (!this.has_vapi(context.vapi_directories, pkg)) {
722 GLib.debug("ADD vapi '%s'",pkgs.get(i));
723 context.add_external_package (pkgs.get(i));
729 // core packages we are interested in for the builder..
730 // some of these may fail... - we probalby need a better way to handle this..
732 context.add_external_package ("gtk+-3.0");
733 context.add_external_package ("libsoup-2.4");
734 if (!context.add_external_package ("webkit2gtk-4.0")) {
735 context.add_external_package ("webkit2gtk-3.0");
737 // these are supposed to be in the 'deps' file, but it's not getting read..
738 context.add_external_package ("cogl-1.0");
739 context.add_external_package ("json-glib-1.0");
740 context.add_external_package ("clutter-gtk-1.0");
744 context.add_external_package ("gdl-3.0");
745 context.add_external_package ("gtksourceview-3.0");
746 context.add_external_package ("vte-2.90"); //??? -- hopefullly that works..
748 //add_documented_files (context, settings.source_files);
750 Vala.Parser parser = new Vala.Parser ();
751 parser.parse (context);
752 //gir_parser.parse (context);
753 if (context.report.get_errors () > 0) {
755 //throw new VapiParserError.PARSE_FAILED("failed parse VAPIS, so we can not write file correctly");
757 print("parse got errors");
760 Vala.CodeContext.pop ();
768 if (context.report.get_errors () > 0) {
769 GLib.error("failed check VAPIS, so we can not write file correctly");
770 // throw new VapiParserError.PARSE_FAILED("failed check VAPIS, so we can not write file correctly");
771 //Vala.CodeContext.pop ();
779 context.accept(this);
782 // dump the tree for Gtk?
784 Vala.CodeContext.pop ();
787 this.augment_all_inheritence();
797 public bool has_vapi(string[] dirs, string vapi)
799 for(var i =0 ; i < dirs.length; i++) {
800 GLib.debug("check VAPI - %s", dirs[i] + "/" + vapi + ".vapi");
801 if (!FileUtils.test( dirs[i] + "/" + vapi + ".vapi", FileTest.EXISTS)) {
812 int main (string[] args) {
814 var g = Palete.Gir.factoryFqn("Gtk.SourceView");
815 print("%s\n", g.asJSONString());