JsRender/Roo.js
[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 GLib.List<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.length() > 0) {
179                 r.set_array_member("params", this.toJSONArrayObject(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                 public Json.Array toJSONArrayObject(GLib.List<GirObject> map)
238         {
239             var r = new Json.Array();
240             for(var i =0;i< map.length();i++) {
241             
242                 r.add_object_element(map.nth_data().toJSON());
243             }
244             return r;
245         }
246     }
247     
248      
249     
250     
251     
252     public class Gir : GirObject {
253     
254         static  Gee.HashMap<string,Gir> cache = null;
255         //Gee.Hashmap<string,what> nodes;
256                 public static Gir factory(string ns) {
257                         if (cache == null) {
258                                 cache = new Gee.HashMap<string,Gir>();
259                         }
260                         var ret = cache.get(ns);
261                         if (ret != null) {
262                                 return ret;
263                         }
264                         var add = new Gir(ns);
265                         cache.set(ns, add);
266                         
267                         var iter = add.classes.map_iterator();
268                         while(iter.next()) {
269                 
270                                 iter.get_value().overlayParent();
271             }   
272
273                         return cache.get(ns);
274                         
275                 }
276         public Gir (string ns)  
277         {
278
279                         var gi = GI.Repository.get_default();
280                         gi.require(ns, null, 0);
281                         
282                     var ver = gi.get_version(ns);
283                     unowned GLib.SList<string>  pth = GI.Repository.get_search_path ();
284                     var gir_path = pth.nth_data(0).replace("/lib/girepository-1.0", "/share/gir-1.0");
285                    //console.log(fn);
286                     var file  = gir_path + "/" + ns + "-" + ver + ".gir";
287                         // print("ns: " + ns + "\n");
288                         // print("ver: " + ver + "\n");
289                     // print(file);
290
291
292                         base("Package",ns);
293                                 this.ns = ns;
294             //this.nodes = new Gee.Hashmap<string,what>();
295              
296             var doc = Xml.Parser.parse_file (file);
297             var root = doc->get_root_element();
298             this.walk( root, (GirObject) this );
299                 
300             delete doc;
301         
302         }
303         public void walk(Xml.Node* element, GirObject? parent)
304         {
305             var n = element->get_prop("name");
306             if (n == null) {
307                 n = "";
308             }
309             //print(element->name + " ("  + parent.name + "==>" + n +")\n");
310             switch (element->name) {
311                 case "repository":
312                     break;
313                 
314                 case "include":
315                     parent.includes.set(n, element->get_prop("version"));
316                     break;
317                 
318                 case "package":
319                     parent.package = n;
320                     break;
321                 
322                 case "c:include":
323                     break;
324                 
325                 case "namespace":
326                     parent.name = n;
327                     break;
328                 
329                 case "alias":
330                     return;
331                     //break; // not handled..
332                 
333                 case "class":
334                     var c = new GirObject("Class", parent.name + "." + n);
335                     parent.classes.set(n, c);
336                                         c.ns = this.ns;
337                     c.parent = element->get_prop("parent");
338                                         if (c.parent == null) {
339                                                 c.parent = "";
340                                         }
341                     parent =  c;
342                     break;
343                 
344                 case "interface":
345                     var c = new GirObject("Interface", parent.name + "." + n);
346                     parent.classes.set(n, c);
347                                         c.ns = this.ns;
348                                         c.ns = parent.name;
349                     c.parent = element->get_prop("parent");
350                                         if (c.parent == null) {
351                                                 c.parent = "";
352                                         }
353                                         parent =  c;
354                     break;
355                 
356                 
357                 case "doc":
358                     parent.doctxt = element->get_content();
359                     return;
360                 
361                 case "implements":
362                     parent.implements.append(n);
363                     break;
364                 
365                 case "constructor":
366                     var c = new GirObject("Ctor",n);
367                                         c.ns = this.ns;
368                     parent.ctors.set(n,c);
369                     parent  = c;
370                     break;
371                 
372                 case "return-value":
373                     var c = new GirObject("Return", "return-value");
374                                         c.ns = this.ns;
375                     parent.return_value = c;
376                     parent =  c;
377                     break;
378                 
379                 case "virtual-method": // not sure...
380                     return;
381                 /*
382                     var c = new GirObject("Signal",n);
383                     parent.signals.set(n,c);
384                     parent = c;
385                     break;
386                 */
387                 case "signal": // Glib:signal
388                     var c = new GirObject("Signal",n.replace("-", "_"));
389                                         c.ns = this.ns;
390                     parent.signals.set(n.replace("-", "_"),c);
391                     parent = c;
392                     break;
393                     
394                 
395               
396                 case "callback": // not sure...
397                     return;
398                 
399                 
400                 case "type":
401                     parent.type = n;
402                                         
403                                         return; // no children?
404                     //break;
405                 
406                 case "method":
407                     var c = new GirObject("Method",n);
408                                         c.ns = this.ns;
409                                         c.propertyof = parent.name;
410                     parent.methods.set(n,c);
411                     parent = c;
412                     break;
413                 
414                 case "parameters":
415                     var c = new GirObject("Paramset",n);
416                                         c.ns = this.ns;
417                     parent.paramset = c;
418                     parent =  c;
419                     break;
420                 
421                 case "instance-parameter":
422                     var c = new GirObject("Param",n);
423                                         c.ns = this.ns;
424                     c.is_instance = true;
425                     parent.params.append(c);
426                     parent = c;
427                     break;
428                 
429                 case "parameter":
430                     var c = new GirObject("Param",n);
431                                         c.ns = this.ns;
432                     parent.params.append(c);
433                     parent = c;
434                     break;
435                 
436                 case "property":
437                 case "field":
438                     var c = new GirObject("Prop",n.replace("-", "_"));
439                                         c.ns = this.ns;
440                                         c.propertyof = parent.name;
441                     parent.props.set(n.replace("-", "_"),c);
442                     parent = c;
443                     break;
444                 
445                 case "function":
446                     var c = new GirObject("Function",n);
447                                         c.ns = this.ns;
448                     parent.methods.set(n,c);
449                     parent = c;
450                     break;
451                 
452                 case "array":
453                     parent.is_array = true;  
454                     break; // type is added soon..
455                 
456                 case "varargs":
457                     parent.is_varargs= true;  
458                     return;
459                 
460                 case "constant":
461                     var c = new GirObject("Const",n);
462                     c.value = element->get_prop("value");
463                                         c.ns = this.ns;
464                     parent.consts.set(n,c);
465                     parent = c;
466                     return;
467                     //break;
468                 
469                 case "enumeration":
470                     var c = new GirObject("Enum",n);
471                                         c.ns = this.ns;
472                     parent.consts.set(n,c);
473                                         
474                     parent = c;
475                     break;
476                 
477                 case "member":
478                     var c = new GirObject("EnumMember",n);
479                                         c.ns = this.ns;
480                     c.value = element->get_prop("value");
481                     parent.consts.set(n,c);
482                     return;
483                     break;
484                 
485                 
486                 case "doc-deprecated":
487                     return;
488                 
489                 case "record": // struct?
490                     return;
491                 case "bitfield": // ignore?
492                     return;
493                 case "prerequisite": // ignore?
494                     return;
495                 default:
496                     print("UNHANDLED Gir file element: " + element->name +"\n");
497                     return;
498             }
499             /*
500             if (element->name == "signal") {
501                 path += ".signal";
502             }
503             
504             
505             if (element->name == "return-value") {
506                 path += ".return-value";
507             }
508             print(path + ":"  + element->name + "\n");
509             */
510             //var d =   getAttribute(element,'doc');
511             //if (d) {
512              //   Seed.print(path + ':' + d);
513             //    ret[path] = d;
514             //}
515             for (Xml.Node* iter = element->children; iter != null; iter = iter->next) {
516                 if (iter->type == Xml.ElementType.TEXT_NODE) {
517                     continue;
518                 }
519                 this.walk(iter, parent);
520             }
521             
522         }
523         public string doc(string what)
524                 {
525                         var ar = what.split(".");
526                         var cls = this.classes.get(ar[1]);
527                         if (ar.length == 2) {
528                                 return cls.doctxt != null ? cls.doctxt : "";
529                         }
530                         // return the property.. by default..
531                         var pr = cls.props.get(ar[2]);
532                         return pr.doctxt != null ? pr.doctxt : "";
533
534                 }
535     
536     
537     } 
538         
539 }