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