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