Palete/Gir.vala
[app.Builder.js] / Palete / Gir.vala
1
2 // valac -g  --pkg gee-1.0 --pkg libxml-2.0 --pkg gobject-introspection-1.0 --pkg json-glib-1.0  Palete/Gir.vala -o /tmp/Gir
3  
4 public static int main (string[] args) {
5     
6     var g = Palete.Gir.factory("Gtk");
7         var test = g.classes.get("ToolButton");
8         
9         
10     var generator = new Json.Generator ();
11     var n = new Json.Node(Json.NodeType.OBJECT);
12     n.set_object(test.toJSON());
13     generator.set_root(n);
14     generator.indent = 4;
15     generator.pretty = true;
16     
17     print(generator.to_data(null));
18     return 0;
19 }
20  
21 namespace Palete {
22         public errordomain GirError {
23         INVALID_TYPE,
24         NEED_IMPLEMENTING,
25                 MISSING_FILE,
26                 INVALID_VALUE
27     }
28     public class GirObject: Object {
29         public string name;
30                 public string ns;
31                 public string propertyof;
32         public string type;
33         public string nodetype;
34         public string  package;
35         
36         public GirObject paramset = null;
37         public GirObject return_value = null;
38             
39         public bool is_instance;
40         public bool is_array;
41         public bool  is_varargs;
42         public  string parent;
43         public  string value;
44
45                 bool is_overlaid;
46         public GLib.List<GirObject> params;
47         public GLib.List<string> implements;
48                 public GLib.List<string> inherits; // full list of all classes and interfaces...
49         public Gee.HashMap<string,GirObject> ctors;
50         public Gee.HashMap<string,GirObject> methods;
51         public Gee.HashMap<string,string>    includes;
52         public Gee.HashMap<string,GirObject> classes;
53         public Gee.HashMap<string,GirObject> props;
54         public Gee.HashMap<string,GirObject> consts;
55         public Gee.HashMap<string,GirObject> signals;
56         public string doctxt;
57         public GirObject(string nodetype, string n)
58                 {
59             this.nodetype = nodetype;
60             this.name = n;
61                         this.ns = "";
62             this.parent = "";
63             this.type = "";
64                         this.propertyof = "";
65             this.is_array = false;
66             this.is_instance = false;
67             this.is_varargs = false;
68             this.implements = new GLib.List<string>();
69                         this.inherits  = new GLib.List<string>();
70             this.includes   = new Gee.HashMap<string,string>();
71             
72             this.params = new Gee.HashMap<string,GirObject>();
73             this.ctors      = new Gee.HashMap<string,GirObject>();
74             this.methods    =new Gee.HashMap<string,GirObject>();
75            
76             this.classes    = new Gee.HashMap<string,GirObject>();
77             this.props      = new Gee.HashMap<string,GirObject>();
78             this.consts     = new Gee.HashMap<string,GirObject>();
79             this.signals    = new Gee.HashMap<string,GirObject>();
80                         this.is_overlaid = false;
81                         this.paramset = null;
82         }
83
84                 public void  overlayParent()
85                 {
86                         
87                         if (this.parent.length < 1 || this.is_overlaid) {
88                                 this.is_overlaid = true;
89                                 return;
90                         }
91                         // print("Overlaying " +this.name + " with " + this.parent + "\n");
92
93                         var pcls = this.clsToObject( this.parent);
94                         if (pcls == null) {
95                                 throw new GirError.INVALID_VALUE("Could not find class : " + 
96                                         this.parent + " of " + this.name  + " in " + this.ns);
97                         }
98                         
99                         pcls.overlayParent( );
100                         this.copyFrom(pcls,false);
101                         for(var i=0; i < this.implements.length(); i++) {
102                                 var clsname = this.implements.nth_data(i);
103                                 var picls = this.clsToObject(clsname);
104                                 this.copyFrom(picls,true);
105                         }
106                         this.is_overlaid = true;
107                         
108                 }
109                 public GirObject clsToObject(string in_pn)
110                 {
111                         var pn = in_pn;
112                         var gir = Gir.factory (this.ns);
113                         if (in_pn.contains(".")) {
114                                 gir =  Gir.factory(in_pn.split(".")[0]);
115                                 pn = in_pn.split(".")[1];
116                         }
117                         
118                         return gir.classes.get(pn);
119
120                         
121                 }
122                 public string fqn() {
123                         return this.ns + this.name;
124                 }
125                 
126                 public void copyFrom(GirObject pcls, bool is_interface) 
127                 {
128
129                         this.inherits.append(pcls.fqn());
130                         var iter = pcls.methods.map_iterator();
131                         while(iter.next()) {
132                 if (null != this.methods.get(iter.get_key())) {
133                                         continue;
134                                 }
135                                 
136                                 this.methods.set(iter.get_key(), iter.get_value());
137             }
138                         
139                         iter = pcls.props.map_iterator();
140                         while(iter.next()) {
141                 if (null != this.props.get(iter.get_key())) {
142                                         continue;
143                                 }
144                                 
145                                 this.props.set(iter.get_key(), iter.get_value());
146             }
147                         
148                         iter = pcls.signals.map_iterator();
149                         while(iter.next()) {
150                 if (null != this.signals.get(iter.get_key())) {
151                                         continue;
152                                 }
153                                 
154                                 this.signals.set(iter.get_key(), iter.get_value());
155             }   
156                 }
157                 
158         public Json.Object toJSON()
159         {
160             var r = new Json.Object();
161             r.set_string_member("nodetype", this.nodetype);
162             r.set_string_member("name", this.name);
163                         if (this.propertyof.length > 0) {
164                 r.set_string_member("of", this.propertyof);
165             }
166             if (this.type.length > 0) {
167                 r.set_string_member("type", this.type);
168             }
169                         if (this.parent != null && this.parent.length > 0) {
170                 r.set_string_member("parent", this.parent);
171             }
172             // is_arary / is_instance / is_varargs..
173             
174             if (this.implements.length() > 0) {
175                 r.set_array_member("length", this.toJSONArrayString(this.implements));
176             }
177             
178             if (this.params.size > 0) {
179                 r.set_object_member("params", this.toJSONObject(this.params));
180             }
181             if (this.ctors.size > 0) {
182                 r.set_object_member("ctors", this.toJSONObject(this.ctors));
183             }
184             if (this.methods.size > 0) {
185                 r.set_object_member("methods", this.toJSONObject(this.methods));
186             }
187             if (this.includes.size > 0) {
188                 r.set_object_member("includes", this.toJSONObjectString(this.includes));
189             }
190             if (this.classes.size > 0) {
191                 r.set_object_member("classes", this.toJSONObject(this.classes));
192             }
193             if (this.props.size > 0) {
194                 r.set_object_member("props", this.toJSONObject(this.props));
195             }
196             if (this.consts.size > 0) {
197                 r.set_object_member("consts", this.toJSONObject(this.consts));
198             }
199             if (this.signals.size > 0) {
200                 r.set_object_member("signals", this.toJSONObject(this.signals));
201             }
202             if (this.paramset != null) {
203                 r.set_object_member("params", this.paramset.toJSON());
204             }
205             if (this.return_value != null) {
206                 r.set_object_member("return_value", this.return_value.toJSON());
207             }
208             return r;
209         }
210         public Json.Object toJSONObject(Gee.HashMap<string,GirObject> map)
211         {
212             var r = new Json.Object();
213             var iter = map.map_iterator();
214             while(iter.next()) {
215                 r.set_object_member(iter.get_key(), iter.get_value().toJSON());
216             }
217             return r;
218         }
219         public Json.Object  toJSONObjectString(Gee.HashMap<string,string> map)
220         {
221             var r = new Json.Object();
222             var iter = map.map_iterator();
223             while(iter.next()) {
224                 r.set_string_member(iter.get_key(), iter.get_value());
225             }
226             return r;
227         }
228         public Json.Array toJSONArrayString(GLib.List<string> map)
229         {
230             var r = new Json.Array();
231             for(var i =0;i< map.length();i++) {
232             
233                 r.add_string_element(map.nth_data(i));
234             }
235             return r;
236         }
237     }
238     
239      
240     
241     
242     
243     public class Gir : GirObject {
244     
245         static  Gee.HashMap<string,Gir> cache = null;
246         //Gee.Hashmap<string,what> nodes;
247                 public static Gir factory(string ns) {
248                         if (cache == null) {
249                                 cache = new Gee.HashMap<string,Gir>();
250                         }
251                         var ret = cache.get(ns);
252                         if (ret != null) {
253                                 return ret;
254                         }
255                         var add = new Gir(ns);
256                         cache.set(ns, add);
257                         
258                         var iter = add.classes.map_iterator();
259                         while(iter.next()) {
260                 
261                                 iter.get_value().overlayParent();
262             }   
263
264                         return cache.get(ns);
265                         
266                 }
267         public Gir (string ns)  
268         {
269
270                         var gi = GI.Repository.get_default();
271                         gi.require(ns, null, 0);
272                         
273                     var ver = gi.get_version(ns);
274                     unowned GLib.SList<string>  pth = GI.Repository.get_search_path ();
275                     var gir_path = pth.nth_data(0).replace("/lib/girepository-1.0", "/share/gir-1.0");
276                    //console.log(fn);
277                     var file  = gir_path + "/" + ns + "-" + ver + ".gir";
278                         // print("ns: " + ns + "\n");
279                         // print("ver: " + ver + "\n");
280                     // print(file);
281
282
283                         base("Package",ns);
284                                 this.ns = ns;
285             //this.nodes = new Gee.Hashmap<string,what>();
286              
287             var doc = Xml.Parser.parse_file (file);
288             var root = doc->get_root_element();
289             this.walk( root, (GirObject) this );
290                 
291             delete doc;
292         
293         }
294         public void walk(Xml.Node* element, GirObject? parent)
295         {
296             var n = element->get_prop("name");
297             if (n == null) {
298                 n = "";
299             }
300             //print(element->name + " ("  + parent.name + "==>" + n +")\n");
301             switch (element->name) {
302                 case "repository":
303                     break;
304                 
305                 case "include":
306                     parent.includes.set(n, element->get_prop("version"));
307                     break;
308                 
309                 case "package":
310                     parent.package = n;
311                     break;
312                 
313                 case "c:include":
314                     break;
315                 
316                 case "namespace":
317                     parent.name = n;
318                     break;
319                 
320                 case "alias":
321                     return;
322                     //break; // not handled..
323                 
324                 case "class":
325                     var c = new GirObject("Class", parent.name + "." + n);
326                     parent.classes.set(n, c);
327                                         c.ns = this.ns;
328                     c.parent = element->get_prop("parent");
329                                         if (c.parent == null) {
330                                                 c.parent = "";
331                                         }
332                     parent =  c;
333                     break;
334                 
335                 case "interface":
336                     var c = new GirObject("Interface", parent.name + "." + n);
337                     parent.classes.set(n, c);
338                                         c.ns = this.ns;
339                                         c.ns = parent.name;
340                     c.parent = element->get_prop("parent");
341                                         if (c.parent == null) {
342                                                 c.parent = "";
343                                         }
344                                         parent =  c;
345                     break;
346                 
347                 
348                 case "doc":
349                     parent.doctxt = element->get_content();
350                     return;
351                 
352                 case "implements":
353                     parent.implements.append(n);
354                     break;
355                 
356                 case "constructor":
357                     var c = new GirObject("Ctor",n);
358                                         c.ns = this.ns;
359                     parent.ctors.set(n,c);
360                     parent  = c;
361                     break;
362                 
363                 case "return-value":
364                     var c = new GirObject("Return", "return-value");
365                                         c.ns = this.ns;
366                     parent.return_value = c;
367                     parent =  c;
368                     break;
369                 
370                 case "virtual-method": // not sure...
371                     return;
372                 /*
373                     var c = new GirObject("Signal",n);
374                     parent.signals.set(n,c);
375                     parent = c;
376                     break;
377                 */
378                 case "signal": // Glib:signal
379                     var c = new GirObject("Signal",n.replace("-", "_"));
380                                         c.ns = this.ns;
381                     parent.signals.set(n.replace("-", "_"),c);
382                     parent = c;
383                     break;
384                     
385                 
386               
387                 case "callback": // not sure...
388                     return;
389                 
390                 
391                 case "type":
392                     parent.type = n;
393                                         
394                                         return; // no children?
395                     //break;
396                 
397                 case "method":
398                     var c = new GirObject("Method",n);
399                                         c.ns = this.ns;
400                                         c.propertyof = parent.name;
401                     parent.methods.set(n,c);
402                     parent = c;
403                     break;
404                 
405                 case "parameters":
406                     var c = new GirObject("Paramset",n);
407                                         c.ns = this.ns;
408                     parent.paramset = c;
409                     parent =  c;
410                     break;
411                 
412                 case "instance-parameter":
413                     var c = new GirObject("Param",n);
414                                         c.ns = this.ns;
415                     c.is_instance = true;
416                     parent.params.set(n,c);
417                     parent = c;
418                     break;
419                 
420                 case "parameter":
421                     var c = new GirObject("Param",n);
422                                         c.ns = this.ns;
423                     parent.params.set(n,c);
424                     parent = c;
425                     break;
426                 
427                 case "property":
428                 case "field":
429                     var c = new GirObject("Prop",n.replace("-", "_"));
430                                         c.ns = this.ns;
431                                         c.propertyof = parent.name;
432                     parent.props.set(n.replace("-", "_"),c);
433                     parent = c;
434                     break;
435                 
436                 case "function":
437                     var c = new GirObject("Function",n);
438                                         c.ns = this.ns;
439                     parent.methods.set(n,c);
440                     parent = c;
441                     break;
442                 
443                 case "array":
444                     parent.is_array = true;  
445                     break; // type is added soon..
446                 
447                 case "varargs":
448                     parent.is_varargs= true;  
449                     return;
450                 
451                 case "constant":
452                     var c = new GirObject("Const",n);
453                     c.value = element->get_prop("value");
454                                         c.ns = this.ns;
455                     parent.consts.set(n,c);
456                     parent = c;
457                     return;
458                     //break;
459                 
460                 case "enumeration":
461                     var c = new GirObject("Enum",n);
462                                         c.ns = this.ns;
463                     parent.consts.set(n,c);
464                                         
465                     parent = c;
466                     break;
467                 
468                 case "member":
469                     var c = new GirObject("EnumMember",n);
470                                         c.ns = this.ns;
471                     c.value = element->get_prop("value");
472                     parent.consts.set(n,c);
473                     return;
474                     break;
475                 
476                 
477                 case "doc-deprecated":
478                     return;
479                 
480                 case "record": // struct?
481                     return;
482                 case "bitfield": // ignore?
483                     return;
484                 case "prerequisite": // ignore?
485                     return;
486                 default:
487                     print("UNHANDLED Gir file element: " + element->name +"\n");
488                     return;
489             }
490             /*
491             if (element->name == "signal") {
492                 path += ".signal";
493             }
494             
495             
496             if (element->name == "return-value") {
497                 path += ".return-value";
498             }
499             print(path + ":"  + element->name + "\n");
500             */
501             //var d =   getAttribute(element,'doc');
502             //if (d) {
503              //   Seed.print(path + ':' + d);
504             //    ret[path] = d;
505             //}
506             for (Xml.Node* iter = element->children; iter != null; iter = iter->next) {
507                 if (iter->type == Xml.ElementType.TEXT_NODE) {
508                     continue;
509                 }
510                 this.walk(iter, parent);
511             }
512             
513         }
514         public string doc(string what)
515                 {
516                         var ar = what.split(".");
517                         var cls = this.classes.get(ar[1]);
518                         if (ar.length == 2) {
519                                 return cls.doctxt != null ? cls.doctxt : "";
520                         }
521                         // return the property.. by default..
522                         var pr = cls.props.get(ar[2]);
523                         return pr.doctxt != null ? pr.doctxt : "";
524
525                 }
526     
527     
528     } 
529         
530 }