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 c.is_sealed = cls.is_sealed;
188 foreach(var p in cls.get_properties()) {
189 this.add_property(c, p);
192 foreach(var p in cls.get_signals()) {
193 this.add_signal(c, p);
196 foreach(var p in cls.get_methods()) {
197 // skip static methods..
198 if (p.binding != Vala.MemberBinding.INSTANCE &&
199 !(p is Vala.CreationMethod)
204 this.add_method(c, p);
207 if (cls.base_class != null) {
208 c.inherits.add(cls.base_class.get_full_name());
210 foreach(var p in cls.get_base_types()) {
212 if (p.type_symbol != null) {
213 c.implements.add(p.type_symbol.get_full_name());
216 if (p.data_type != null) {
217 c.implements.add(p.data_type.get_full_name());
224 if (cls.version.deprecated) {
225 GLib.debug("class %s is deprecated", c.name);
226 c.is_deprecated = true;
231 public GirObject? fqn_to_cls(string fqn)
233 var ar = fqn.split(".");
234 var pkg = this.project.gir_cache.get(ar[0]);
235 var cls = pkg != null ? pkg.classes.get(ar[1]) : null;
239 public void augment_inherits_for(GirObject cls, Gee.ArrayList<string> to_check, bool is_top)
241 foreach (var chk_cls in to_check) {
242 if (!cls.inherits.contains(chk_cls)) {
243 cls.inherits.add(chk_cls);
252 var subcls = this.fqn_to_cls(chk_cls);
253 if (subcls == null) {
256 this.augment_inherits_for(cls, subcls.inherits, false);
257 this.augment_implements_for(cls, subcls.implements);
261 public void augment_implements_for(GirObject cls, Gee.ArrayList<string> to_check)
263 foreach (var chk_cls in to_check) {
264 if (cls.implements.contains(chk_cls)) {
267 cls.implements.add(chk_cls);
269 var subcls = this.fqn_to_cls(chk_cls);
270 if (subcls == null) {
273 this.augment_implements_for(cls, subcls.implements);
279 // this might miss out interfaces of child classes?
280 public void augment_all_inheritence()
282 // this works out all the children...
283 foreach(var pkgname in this.project.gir_cache.keys) {
285 var pkg = this.project.gir_cache.get(pkgname);
286 foreach (var clsname in pkg.classes.keys) {
287 var cls = pkg.classes.get(clsname);
288 this.augment_inherits_for(cls, cls.inherits, true);
289 this.augment_implements_for(cls, cls.implements);
292 // now do the implementations
293 foreach(var pkgname in this.project.gir_cache.keys) {
295 var pkg = this.project.gir_cache.get(pkgname);
296 foreach (var clsname in pkg.classes.keys) {
297 var cls = pkg.classes.get(clsname);
298 foreach(var parentname in cls.inherits) {
299 var parent = this.fqn_to_cls(parentname);
300 if (parent == null) {
303 if (parent.implementations.contains(cls.fqn())) {
306 parent.implementations.add(cls.fqn());
309 foreach(var parentname in cls.implements) {
310 var parent = this.fqn_to_cls(parentname);
311 if (parent == null) {
314 if (parent.implementations.contains(cls.fqn())) {
317 parent.implementations.add(cls.fqn());
327 public void add_property(GirObject parent, Vala.Property prop)
329 var c = new GirObject("Prop",prop.name);
332 c.propertyof = parent.name;
334 c.type = prop.property_type.type_symbol == null ? "" : prop.property_type.type_symbol.get_full_name();
336 c.type = prop.property_type.data_type == null ? "" : prop.property_type.data_type.get_full_name();
338 c.is_readable = prop.get_accessor != null ? prop.get_accessor.readable : false;
339 c.is_writable = prop.set_accessor != null ? prop.set_accessor.writable || prop.set_accessor.construction : false;
340 //if (prop.name == "child") {
341 // GLib.debug("prop child : w%s r%s", c.is_writable ? "YES" : "n" , c.is_readable ? "YES" : "n");
343 if (prop.version.deprecated) {
344 GLib.debug("class %s is deprecated", c.name);
345 c.is_deprecated = true;
347 parent.props.set(prop.name,c);
353 public void add_field(GirObject parent, Vala.Field prop)
355 var c = new GirObject("Field",prop.name);
358 c.propertyof = parent.name;
360 c.type = prop.variable_type.type_symbol == null ? "" : prop.variable_type.type_symbol.get_full_name();
362 c.type = prop.variable_type.data_type == null ? "" : prop.variable_type.data_type.get_full_name();
365 if (prop.version.deprecated) {
366 GLib.debug("class %s is deprecated", c.name);
367 c.is_deprecated = true;
369 parent.props.set(prop.name,c);
373 public void add_delegate(GirObject parent, Vala.Delegate sig)
376 var c = new GirObject("Delegate", sig.name);
379 c.propertyof = parent.name;
381 var dt = sig.return_type.type_symbol ;
383 var dt = sig.return_type.data_type;
385 if (sig.version.deprecated) {
386 GLib.debug("class %s is deprecated", c.name);
387 c.is_deprecated = true;
393 //print("creating return type on signal %s\n", sig.name);
394 var cc = new GirObject("Return", "return-value");
397 cc.type = dt.get_full_name();
399 c.type = dt.get_full_name(); // type is really return type in this scenario.
400 retval = "\treturn " + cc.type +";";
402 parent.delegates.set(sig.name,c);
404 var params = sig.get_parameters() ;
405 if (params.size < 1) {
407 c.sig = "( ) => {\n\n"+ retval + "\n}\n";
411 var cc = new GirObject("Paramset",sig.name); // what's the name on this?
417 foreach(var p in params) {
418 this.add_param(cc, p);
419 args += args.length > 0 ? ", " : "";
422 // add c.sig -> this is the empty
423 c.sig = "(" + args + ") => {\n\n"+ retval + "\n}\n";
432 public void add_signal(GirObject parent, Vala.Signal sig)
434 var c = new GirObject("Signal",sig.name);
437 c.propertyof = parent.name;
439 var dt = sig.return_type.type_symbol ;
441 var dt = sig.return_type.data_type;
443 if (sig.version.deprecated) {
444 GLib.debug("class %s is deprecated", c.name);
445 c.is_deprecated = true;
451 //print("creating return type on signal %s\n", sig.name);
452 var cc = new GirObject("Return", "return-value");
455 cc.type = dt.get_full_name();
457 c.type = dt.get_full_name(); // type is really return type in this scenario.
458 retval = "\treturn " + cc.type +";";
460 parent.signals.set(sig.name,c);
462 var params = sig.get_parameters() ;
463 if (params.size < 1) {
465 c.sig = "( ) => {\n\n"+ retval + "\n}\n";
469 var cc = new GirObject("Paramset",sig.name); // what's the name on this?
475 foreach(var p in params) {
476 this.add_param(cc, p);
477 args += args.length > 0 ? ", " : "";
480 // add c.sig -> this is the empty
481 c.sig = "(" + args + ") => {\n\n"+ retval + "\n}\n";
487 public void add_method(GirObject parent, Vala.Method met)
489 var n = met.name == null ? "" : met.name;
491 if (met is Vala.CreationMethod) {
493 if(n == "" || n == ".new") {
498 //print("add_method : %s\n", n);
500 var c = new GirObject(ty,n);
504 if (met.return_type.type_symbol != null) {
506 if (met.return_type.data_type != null) {
510 //print("creating return type on method %s\n", met.name);
511 var cc = new GirObject("Return", "return-value");
516 cc.type = met.return_type.type_symbol.get_full_name();
518 cc.type = met.return_type.data_type.get_full_name();
525 if (met is Vala.CreationMethod) {
526 parent.ctors.set(c.name,c);
528 parent.methods.set(met.name,c);
531 var params = met.get_parameters() ;
532 if (params.size < 1) {
535 var cc = new GirObject("Paramset",met.name); // what's the name on this?
541 foreach(var p in params) {
542 if (p.name == null && !p.ellipsis) {
545 var pp = this.add_param(cc, p);
546 c.sig += (c.sig == "(" ? "" : ",");
547 c.sig += " " + (pp.direction == "in" ? "" : pp.direction) + " " + pp.type + " " + pp.name;
549 c.sig += (c.sig == "(" ? ")" : " )");
553 public GirObject add_param(GirObject parent, Vala.Parameter pam)
560 var c = new GirObject("Param",n);
564 switch (pam.direction) {
565 case Vala.ParameterDirection.IN:
568 case Vala.ParameterDirection.OUT:
571 case Vala.ParameterDirection.REF:
576 parent.params.add(c);
580 c.type = pam.variable_type.type_symbol == null ? "" : pam.variable_type.type_symbol.get_full_name();
582 c.type = pam.variable_type.data_type == null ? "" : pam.variable_type.data_type.get_full_name();
585 Gir.checkParamOverride(c);
595 public Gee.ArrayList<string> fillDeps(Gee.ArrayList<string> in_ar)
597 var ret = new Gee.ArrayList<string>();
598 foreach(var k in in_ar) {
599 if (!ret.contains(k)) {
602 var deps = this.loadDeps(k);
603 // hopefully dont need to recurse through these..
604 for(var i =0;i< deps.length;i++) {
605 if (!ret.contains(deps[i])) {
617 public string[] loadDeps(string n)
619 // only try two? = we are ignoreing our configDirectory?
621 var fn = "/usr/share/vala-0.%d/vapi/%s.deps".printf(this.vala_version, n);
622 if (!FileUtils.test (fn, FileTest.EXISTS)) {
626 fn = "/usr/share/vala/vapi/%s.deps".printf( n);
627 if (!FileUtils.test (fn, FileTest.EXISTS)) {
633 FileUtils.get_contents(fn, out ostr);
634 } catch (GLib.Error e) {
635 GLib.debug("failed loading deps %s", e.message);
638 return ostr.split("\n");
645 public void create_valac_tree( )
648 context = new Vala.CodeContext ();
649 Vala.CodeContext.push (context);
651 context.experimental = false;
652 context.experimental_non_null = false;
655 //for (int i = 2; i <= ver; i += 2) {
656 // context.add_define ("VALA_0_%d".printf (i));
660 //var vapidirs = ((Project.Gtk)this.file.project).vapidirs();
661 // what's the current version of vala???
664 //vapidirs += Path.get_dirname (context.get_vapi_path("glib-2.0")) ;
666 var vapidirs = context.vapi_directories;
668 vapidirs += (BuilderApplication.configDirectory() + "/resources/vapi");
669 vapidirs += "/usr/share/vala-0.%d/vapi".printf(this.vala_version);
670 vapidirs += "/usr/share/vala/vapi";
671 context.vapi_directories = vapidirs;
673 // or context.get_vapi_path("glib-2.0"); // should return path..
674 //context.vapi_directories = vapidirs;
675 context.report.enable_warnings = true;
676 context.metadata_directories = { };
677 context.gir_directories = {};
678 //context.thread = true;
681 //this.report = new ValaSourceReport(this.file);
682 //context.report = this.report;
685 context.basedir = "/tmp"; //Posix.realpath (".");
687 context.directory = context.basedir;
690 // add default packages:
691 //if (settings.profile == "gobject-2.0" || settings.profile == "gobject" || settings.profile == null) {
693 context.set_target_profile (Vala.Profile.GOBJECT);
695 context.profile = Vala.Profile.GOBJECT;
698 var ns_ref = new Vala.UsingDirective (new Vala.UnresolvedSymbol (null, "GLib", null));
699 context.root.add_using_directive (ns_ref);
702 context.add_external_package ("glib-2.0");
703 context.add_external_package ("gobject-2.0");
704 // user defined ones..
708 var pkgs = this.fillDeps(this.project.packages);
711 for (var i = 0; i < pkgs.size; i++) {
713 var pkg = pkgs.get(i);
714 // do not add libvala versions except the one that matches the one we are compiled against..
715 if (Regex.match_simple("^libvala", pkg) && pkg != ("libvala-0." + vala_version.to_string())) {
718 //valac += " --pkg " + dcg.packages.get(i);
719 if (!this.has_vapi(context.vapi_directories, pkg)) {
723 GLib.debug("ADD vapi '%s'",pkgs.get(i));
724 context.add_external_package (pkgs.get(i));
730 // core packages we are interested in for the builder..
731 // some of these may fail... - we probalby need a better way to handle this..
733 context.add_external_package ("gtk+-3.0");
734 context.add_external_package ("libsoup-2.4");
735 if (!context.add_external_package ("webkit2gtk-4.0")) {
736 context.add_external_package ("webkit2gtk-3.0");
738 // these are supposed to be in the 'deps' file, but it's not getting read..
739 context.add_external_package ("cogl-1.0");
740 context.add_external_package ("json-glib-1.0");
741 context.add_external_package ("clutter-gtk-1.0");
745 context.add_external_package ("gdl-3.0");
746 context.add_external_package ("gtksourceview-3.0");
747 context.add_external_package ("vte-2.90"); //??? -- hopefullly that works..
749 //add_documented_files (context, settings.source_files);
751 Vala.Parser parser = new Vala.Parser ();
752 parser.parse (context);
753 //gir_parser.parse (context);
754 if (context.report.get_errors () > 0) {
756 //throw new VapiParserError.PARSE_FAILED("failed parse VAPIS, so we can not write file correctly");
758 print("parse got errors");
761 Vala.CodeContext.pop ();
769 if (context.report.get_errors () > 0) {
770 GLib.error("failed check VAPIS, so we can not write file correctly");
771 // throw new VapiParserError.PARSE_FAILED("failed check VAPIS, so we can not write file correctly");
772 //Vala.CodeContext.pop ();
780 context.accept(this);
783 // dump the tree for Gtk?
785 Vala.CodeContext.pop ();
788 this.augment_all_inheritence();
798 public bool has_vapi(string[] dirs, string vapi)
800 for(var i =0 ; i < dirs.length; i++) {
801 GLib.debug("check VAPI - %s", dirs[i] + "/" + vapi + ".vapi");
802 if (!FileUtils.test( dirs[i] + "/" + vapi + ".vapi", FileTest.EXISTS)) {
813 int main (string[] args) {
815 var g = Palete.Gir.factoryFqn("Gtk.SourceView");
816 print("%s\n", g.asJSONString());