ea8eb2417f5c40557e6570f7db1ab89c57018c72
[app.Builder.js] / src / 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                 INVALID_FORMAT
28         }
29          
30             
31              
32             
33     
34     
35         public class Gir : GirObject {
36     
37                 public static  Gee.HashMap<string,Gir> cache = null;
38                 //Gee.Hashmap<string,what> nodes;
39
40
41                 
42                 public static Gir?  factory(string ns) {
43                         if (cache == null) {
44                                 cache = new Gee.HashMap<string,Gir>();
45                         }
46                         var ret = cache.get(ns);
47                         if (ret == null) {
48
49                                 var add = new Gir(ns);
50                                 cache.set(ns, add);
51                         
52                                 var iter = add.classes.map_iterator();
53                                 while(iter.next()) {
54                                         iter.get_value().overlayParent();
55                                 }
56                                 // loop again and add the ctor properties.
57                                 iter = add.classes.map_iterator();
58                                 while(iter.next()) {
59                                         iter.get_value().overlayCtorProperties();
60                                 }       
61
62                                 
63                                 ret = cache.get(ns);
64                         }
65                          
66
67                         return ret;
68                         
69                 }
70                 public static GirObject?  factoryFqn(string fqn)  
71                 {       
72                         var bits = fqn.split(".");
73                         if (bits.length < 1) {
74                                 return null;
75                         }
76                         
77                         var f = (GirObject)factory(bits[0]);
78
79                         if (bits.length == 1 || f ==null) {
80                                 return f;
81                         }
82                         return f.fetchByFqn(fqn.substring(bits[0].length+1)); // since classes are stored in fqn format...?
83                                             
84                         
85                 }
86
87                         
88                 /**
89                  * guess the fqn of a type == eg. gboolean or Widget etc...
90                  */
91                 public static string fqtypeLookup(string type, string ns) {
92                         var g = factory(ns);
93                         if (g.classes.has_key(type)) {
94                                 return ns + "." + type;
95                         }
96                         // enums..
97                         if (g.consts.has_key(type)) {
98                                 return ns + "." + type;
99                         }
100                         
101                         
102                         // look at includes..
103                         var iter = g.includes.map_iterator();
104                         while(iter.next()) {
105                                 // skip empty namespaces on include..?
106                                 if ( iter.get_key() == "") {
107                                         continue;
108                                 }
109                                 var ret = fqtypeLookup(type, iter.get_key());
110                                 if (ret != type) {
111                                         return ret;
112                                 }
113                 }       
114                         return type;
115                 }
116                 
117
118
119                 
120
121                 public static string guessDefaultValueForType(string type) {
122                         //print("guessDefaultValueForType: %s\n", type);
123                         if (type.length < 1 || type.contains(".")) {
124                                 return "null";
125                         }
126                         switch(type) {
127                                 case "gboolean":
128                                         return "true";
129                                 case "guint":
130                                         return "0";
131                                 case "utf8":
132                                         return "\"\"";
133                                 default:
134                                         return "?"+  type + "?";
135                         }
136
137                 }
138
139
140                 public Gir.new_empty (string ns)
141                 {
142                         base("Package",ns);
143                 }
144                 public Gir (string ns)  
145                 {
146                         var xns = ns == "Glade" ? "Gladeui" : ns;
147                         var gi = GI.Repository.get_default();
148                         gi.require(xns, null, 0);
149                         
150                         var ver = gi.get_version(xns);
151                         unowned GLib.SList<string>  pth = GI.Repository.get_search_path ();
152                         var gir_path = pth.nth_data(0).replace("/lib/girepository-1.0", "/share/gir-1.0");
153                         // 64bit...
154                         gir_path = gir_path.replace("/lib/x86_64-linux-gnu/girepository-1.0", "/share/gir-1.0");
155                         
156                         //console.log(fn);
157
158                         
159                         
160                         var file  = gir_path + "/" + xns + "-" + ver + ".gir";
161                         // print("ns: " + ns + "\n");
162                         // print("ver: " + ver + "\n");
163                         // print(file);
164
165
166                         base("Package",ns);
167                         this.ns = ns;
168                         //this.nodes = new Gee.Hashmap<string,what>();
169                      
170                         var doc = Xml.Parser.parse_file (file);
171                         var root = doc->get_root_element();
172                         this.walk( root, (GirObject) this );
173
174                         delete doc;
175                 
176                 }
177                 public void walk(Xml.Node* element, GirObject? parent)
178                 {
179                     var n = element->get_prop("name");
180                         // ignore null or c:include...
181                     if (n == null || (element->ns->prefix != null && element->ns->prefix == "c")) {
182                                 n = "";
183                     }
184                     //print("%s:%s (%s ==> %s\n", element->ns->prefix , element->name , parent.name , n);
185                     switch (element->name) {
186                         case "repository":
187                             break;
188                         
189                         case "include":
190                             parent.includes.set(n, element->get_prop("version"));
191                             break;
192                         
193                         case "package":
194                             parent.package = n;
195                             break;
196                         
197                         case "c:include":
198                             break;
199                         
200                         case "namespace":
201                             parent.name = n;
202                             break;
203                         
204                         case "alias":
205                             return;
206                             //break; // not handled..
207                         
208                         case "class":
209                                 var c = new GirObject("Class", parent.name + "." + n);
210                                 parent.classes.set(n, c);
211                                 c.ns = this.ns;
212                                 c.parent = element->get_prop("parent");
213                                 c.gparent = parent;
214                                 if (c.parent == null) {
215                                         c.parent = "";
216                                 }
217                                 parent =  c;
218                                 break;
219                         
220                         case "interface":
221                             var c = new GirObject("Interface", parent.name + "." + n);
222                             c.gparent = parent;
223                             parent.classes.set(n, c);
224                                 c.ns = this.ns;
225                                 c.ns = parent.name;
226                                 c.parent = element->get_prop("parent");
227                                 if (c.parent == null) {
228                                         c.parent = "";
229                                 }
230                                 parent =  c;
231                             break;
232                         
233                         
234                         case "doc":
235                             parent.doctxt = element->get_content();
236                             return;
237                         
238                         case "implements":
239                             parent.implements.add(n);
240                 
241                             break;
242                         
243                         case "constructor":
244                             var c = new GirObject("Ctor",n);
245                             c.ns = this.ns;
246                             c.gparent = parent;
247                             parent.ctors.set(n,c);
248                             parent  = c;
249                             break;
250                         
251                         case "return-value":
252                             var c = new GirObject("Return", "return-value");
253                             c.gparent = parent;
254                             c.ns = this.ns;
255                             parent.return_value = c;
256                             parent =  c;
257                             break;
258                         
259                         case "virtual-method": // not sure...
260                             return;
261                         /*
262                             var c = new GirObject("Signal",n);
263                             parent.signals.set(n,c);
264                             parent = c;
265                             break;
266                         */
267                         case "signal": // Glib:signal
268                                 var c = new GirObject("Signal",n.replace("-", "_"));
269                                 c.gparent = parent;
270                                 c.ns = this.ns;
271                                 parent.signals.set(n.replace("-", "_"),c);
272                                 parent = c;
273                                 break;
274                             
275                         
276                       
277                         case "callback": // not sure...
278                             return;
279                         
280                         
281                         case "type":
282                             parent.type = n;
283                                 
284                                                 return; // no children?
285                             //break;
286                         
287                         case "method":
288                                 var c = new GirObject("Method",n);
289                                 c.gparent = parent;
290                                 c.ns = this.ns;
291                                 c.propertyof = parent.name;
292                                 parent.methods.set(n,c);
293                                 parent = c;
294                                 break;
295                         
296                         case "parameters":
297                             var c = new GirObject("Paramset",n);
298                             c.gparent = parent;
299                             c.ns = this.ns;
300                             parent.paramset = c;
301                             parent =  c;
302                             break;
303                         
304                         case "instance-parameter":
305                                         break;
306                                         // looks  like this is the C first arg, that is ignored (as it is 
307                                         // treated as 'this' )
308                                 var c = new GirObject("Param",n);
309                                         c.gparent = parent;
310                                         c.ns = this.ns;
311                                 c.is_instance = true;
312                                 parent.params.add(c);
313                                 parent = c;
314                                 break;
315                         
316                         case "parameter":
317                                 var c = new GirObject("Param",n);
318                                 c.gparent = parent;
319                                 c.ns = this.ns;
320                                 parent.params.add(c);
321                                 parent = c;
322                                 this.checkParamOverride(c);   
323                             break;
324                         
325                         case "property":
326                         case "field":
327                                 var c = new GirObject("Prop",n.replace("-", "_"));
328                                 c.gparent = parent;
329                                 c.ns = this.ns;
330                                 c.propertyof = parent.name;
331                                 parent.props.set(n.replace("-", "_"),c);
332                                 parent = c;
333                                 break;
334                         
335                         case "function":
336                             var c = new GirObject("Function",n);
337                             c.gparent = parent;
338                             c.ns = this.ns;
339                             parent.methods.set(n,c);
340                             parent = c;
341                             break;
342                         
343                         case "array":
344                             parent.is_array = true;  
345                             break; // type is added soon..
346                         
347                         case "varargs":
348                             parent.is_varargs= true;  
349                             return;
350                         
351                         case "constant":
352                             var c = new GirObject("Const",n);
353                             c.gparent = parent;
354                             c.value = element->get_prop("value");
355                                                 c.ns = this.ns;
356                             parent.consts.set(n,c);
357                             parent = c;
358                             return;
359                             //break;
360                         case "bitfield":
361                         case "enumeration":
362                                 var c = new GirObject("Enum",n);
363                                 c.gparent = parent;
364                                 c.ns = this.ns;
365                                 parent.consts.set(n,c);
366                                 
367                                 parent = c;
368                                 break;
369                         
370                         case "member":
371                                 var c = new GirObject("EnumMember",n);
372                                 c.gparent = parent;
373                                 c.ns = this.ns;
374                                 c.value = element->get_prop("value");
375                                 parent.consts.set(n,c);
376                                 return;
377                                 break;
378                         
379                         
380                         case "doc-deprecated":
381                             return;
382                         
383                         case "record": // struct?
384                             return;
385                          
386                                             
387                             return;
388                         case "prerequisite": // ignore?
389                             return;
390                                         case "union": // ignore?
391                             return;
392                                         default:
393                             print("UNHANDLED Gir file element: " + element->name +"\n");
394                             return;
395                     }
396                     /*
397                     if (element->name == "signal") {
398                         path += ".signal";
399                     }
400                     
401                     
402                     if (element->name == "return-value") {
403                         path += ".return-value";
404                     }
405                     print(path + ":"  + element->name + "\n");
406                     */
407                     //var d =   getAttribute(element,'doc');
408                     //if (d) {
409                      //   Seed.print(path + ':' + d);
410                     //    ret[path] = d;
411                     //}
412                     for (Xml.Node* iter = element->children; iter != null; iter = iter->next) {
413                         if (iter->type == Xml.ElementType.TEXT_NODE) {
414                             continue;
415                         }
416                         this.walk(iter, parent);
417                     }
418
419                 }
420                 public string doc(string what)
421                 {
422                         var ar = what.split(".");
423                         var cls = this.classes.get(ar[1]);
424                         if (ar.length == 2) {
425                                 return cls.doctxt != null ? cls.doctxt : "";
426                         }
427                         // return the property.. by default..
428                         var pr = cls.props.get(ar[2]);
429                         return pr.doctxt != null ? pr.doctxt : "";
430
431                 }
432
433
434
435                 public void checkParamOverride(GirObject c)
436                 {
437                         var parset = c.gparent;
438                         if (parset == null || parset.nodetype != "Paramset") {
439                                 return;
440                         }
441                         var method = parset.gparent;
442                         if (method == null || method.nodetype != "Ctor") {
443                                 return;
444                         }
445                         var cls = method.gparent;
446                         if (cls == null || cls.nodetype != "Class") {
447                                 return;
448                         }
449
450                          
451                 
452                         c.name = this.fetchOverride( cls.name, method.name, c.name);
453                 }
454                 public static bool overrides_loaded = false;
455                 public static Gee.HashMap<string,string> overrides;
456         
457                 public string fetchOverride(  string cls, string method, string param)
458                 {
459                         // overrides should be in a file Gir.overides
460                         // in that "Gtk.Label.new.str" : "label"
461                         this.loadOverrides();
462                         var key = "%s.%s.%s".printf(cls,method,param);
463                         //print("Chekcing for key %s\n", key);
464                         if (!overrides.has_key(key)) {
465                                 return param;
466                         }
467                         return overrides.get(key);
468
469
470                 }
471                 public void loadOverrides(bool force = false)
472                 {
473                         if (overrides_loaded && ! force) {
474                                 return;
475                         }
476                 
477                         var pa = new Json.Parser();
478                         pa.load_from_file(BuilderApplication.configDirectory() + "/resources/Gir.overides");
479                         var node = pa.get_root();
480                     
481                         if (node.get_node_type () != Json.NodeType.OBJECT) {
482                                 throw new GirError.INVALID_FORMAT ("Error loading gir.overides : Unexpected element type %s", node.type_name ());
483                         }
484                         overrides = new Gee.HashMap<string,string>();
485                 
486                 
487                         var obj = node.get_object ();
488                 
489                 
490                         obj.foreach_member((o , key, value) => {
491                                 //print(key+"\n");
492                                  
493                                 var v = obj.get_string_member(key);
494                         
495                         
496                                 overrides.set(key, v);
497
498                         });
499         
500                         overrides_loaded = true;
501
502                 
503
504                 }
505         }       
506
507         
508 }