2 * This is the base class for representing the vala API
4 * it was originally based on parsing Gir files - but since then
5 * has evolved into using libvala
13 public errordomain GirError {
20 public class GirObject: Object {
23 public string propertyof;
25 public string nodetype; // eg. Signal / prop etc.
26 public string package;
27 public string direction; // used for vala in/out/ref...
29 public GirObject paramset = null;
30 public GirObject return_value = null;
31 public bool is_deprecated = false;
32 public bool is_instance;
34 public bool is_varargs;
35 public bool ctor_only; // specially added ctor properties..
36 public bool is_writable = true;
37 public bool is_readable = true;
38 public bool is_abstract = false;
39 public bool is_sealed = false;
44 public string sig; // signture (used to create event handlers)
46 public bool is_overlaid;
48 public GirObject gparent;
49 public Gee.ArrayList<GirObject> params;
50 public Gee.ArrayList<string> implements;
51 public Gee.ArrayList<string> implementations;
52 public Gee.ArrayList<string> inherits; // full list of all classes and interfaces...
53 public Gee.HashMap<string,GirObject> ctors;
54 public Gee.HashMap<string,GirObject> methods;
55 public Gee.HashMap<string,string> includes;
56 public Gee.HashMap<string,GirObject> classes;
57 public Gee.HashMap<string,GirObject> props;
58 public Gee.HashMap<string,GirObject> consts;
59 public Gee.HashMap<string,GirObject> signals;
60 public Gee.HashMap<string,GirObject> delegates;
62 public Gee.ArrayList<string> optvalues; // used by Roo only..
64 public Gee.ArrayList<string> can_drop_onto; // used by Roo only.. at present
65 public Gee.ArrayList<string> valid_cn; // used by Roo only.. at present
71 public GirObject(string nodetype, string n)
73 this.nodetype = nodetype;
79 this.is_array = false;
80 this.is_instance = false;
81 this.is_varargs = false;
82 this.ctor_only =false;
89 this.implements = new Gee.ArrayList<string>();
90 this.implementations = new Gee.ArrayList<string>();
91 this.inherits = new Gee.ArrayList<string>(); // list of all ancestors. (interfaces and parents)
92 this.includes = new Gee.HashMap<string,string>();
94 this.params = new Gee.ArrayList<GirObject>();
95 this.ctors = new Gee.HashMap<string,GirObject>();
96 this.methods =new Gee.HashMap<string,GirObject>();
98 this.classes = new Gee.HashMap<string,GirObject>();
99 this.props = new Gee.HashMap<string,GirObject>();
100 this.consts = new Gee.HashMap<string,GirObject>();
101 this.signals = new Gee.HashMap<string,GirObject>();
102 this.delegates = new Gee.HashMap<string,GirObject>();
104 this.optvalues = new Gee.ArrayList<string>();
105 this.can_drop_onto = new Gee.ArrayList<string>();
106 this.valid_cn = new Gee.ArrayList<string>();
110 this.is_overlaid = false;
111 this.paramset = null;
114 public string[] inheritsToStringArray()
117 for(var i =0;i< this.inherits.size; i++) {
118 ret += this.inherits.get(i);
120 for(var i =0;i< this.implements.size; i++) {
121 ret += this.implements.get(i);
128 public void overlayParent(Project.Project project)
131 if (this.parent.length < 1 || this.is_overlaid) {
132 this.is_overlaid = true;
136 //print("Overlaying " +this.name + " with " + this.parent + "\n");
138 var pcls = this.clsToObject( project, this.parent);
141 //throw new GirError.INVALID_VALUE("Could not find class : " +
142 // this.parent + " of " + this.name + " in " + this.ns);
145 pcls.overlayParent( project );
146 this.copyFrom(pcls,false);
147 for(var i=0; i < this.implements.size; i++) {
148 var clsname = this.implements.get(i);
149 var picls = this.clsToObject(project, clsname);
150 this.copyFrom(picls,true);
152 this.is_overlaid = true;
156 public void overlayCtorProperties()
158 //print("Check overlay Ctor %s\n", this.name);
159 if (!this.ctors.has_key("new")) {
162 var ctor = this.ctors.get("new");
163 if (ctor.paramset == null || ctor.paramset.params.size < 1) {
166 //print("Found Ctor\n");
167 var iter = ctor.paramset.params.list_iterator();
168 while (iter.next()) {
169 var n = iter.get().name;
171 if (this.props.has_key(n)) {
177 //print("Adding prop %s\n", n);
180 var c = new GirObject("Prop",n);
183 c.propertyof = this.name;
184 c.type = iter.get().type;
186 this.props.set(n, c);
194 public string fqn() {
195 // not sure if fqn really is correct here...
197 return this.nodetype.down() == "class" || this.nodetype.down() =="interface"
198 ? this.name : (this.ns + this.name);
201 public void copyFrom(GirObject pcls, bool is_interface)
204 this.inherits.add(pcls.fqn());
206 var liter = pcls.inherits.list_iterator();
207 while(liter.next()) {
208 if (this.inherits.contains(liter.get())) {
211 this.inherits.add(liter.get());
215 var iter = pcls.methods.map_iterator();
217 if (null != this.methods.get(iter.get_key())) {
221 this.methods.set(iter.get_key(), iter.get_value());
224 iter = pcls.props.map_iterator();
226 if (null != this.props.get(iter.get_key())) {
230 this.props.set(iter.get_key(), iter.get_value());
233 iter = pcls.signals.map_iterator();
235 if (null != this.signals.get(iter.get_key())) {
239 this.signals.set(iter.get_key(), iter.get_value());
243 public Json.Object toJSON()
245 var r = new Json.Object();
246 r.set_string_member("nodetype", this.nodetype);
247 r.set_string_member("name", this.name);
248 if (this.propertyof.length > 0) {
249 r.set_string_member("of", this.propertyof);
251 if (this.type.length > 0) {
252 r.set_string_member("type", this.type);
254 if (this.parent != null && this.parent.length > 0) {
255 r.set_string_member("parent", this.parent);
257 if (this.sig.length > 0) {
258 r.set_string_member("sig", this.sig);
261 // is_arary / is_instance / is_varargs..
264 if (this.inherits.size > 0) {
265 r.set_array_member("inherits", this.toJSONArrayString(this.inherits));
268 if (this.implements.size > 0) {
269 r.set_array_member("implements", this.toJSONArrayString(this.implements));
272 if (this.params.size > 0) {
273 r.set_array_member("params", this.toJSONArrayObject(this.params));
275 if (this.ctors.size > 0) {
276 r.set_object_member("ctors", this.toJSONObject(this.ctors));
278 if (this.methods.size > 0) {
279 r.set_object_member("methods", this.toJSONObject(this.methods));
281 if (this.includes.size > 0) {
282 r.set_object_member("includes", this.toJSONObjectString(this.includes));
284 if (this.classes.size > 0) {
285 r.set_object_member("classes", this.toJSONObject(this.classes));
287 if (this.props.size > 0) {
288 r.set_object_member("props", this.toJSONObject(this.props));
290 if (this.consts.size > 0) {
291 r.set_object_member("consts", this.toJSONObject(this.consts));
293 if (this.signals.size > 0) {
294 r.set_object_member("signals", this.toJSONObject(this.signals));
296 if (this.paramset != null) {
297 r.set_object_member("paramset", this.paramset.toJSON());
299 if (this.return_value != null) {
300 r.set_object_member("return_value", this.return_value.toJSON());
304 public Json.Object toJSONObject(Gee.HashMap<string,GirObject> map)
306 var r = new Json.Object();
307 var iter = map.map_iterator();
309 r.set_object_member(iter.get_key(), iter.get_value().toJSON());
313 public Json.Object toJSONObjectString(Gee.HashMap<string,string> map)
315 var r = new Json.Object();
316 var iter = map.map_iterator();
318 r.set_string_member(iter.get_key(), iter.get_value());
322 public Json.Array toJSONArrayString(Gee.ArrayList<string> map)
324 var r = new Json.Array();
325 for(var i =0;i< map.size;i++) {
327 r.add_string_element(map.get(i));
331 public Json.Array toJSONArrayObject(Gee.ArrayList<GirObject> map)
333 var r = new Json.Array();
334 for(var i =0;i< map.size;i++) {
336 r.add_object_element(map.get(i).toJSON());
340 public string asJSONString()
342 var generator = new Json.Generator ();
343 generator.indent = 4;
344 generator.pretty = true;
345 var n = new Json.Node(Json.NodeType.OBJECT);
346 n.set_object(this.toJSON());
347 generator.set_root(n);
349 return generator.to_data(null);
353 public GirObject? fetchByFqn(string fqn) {
354 GLib.debug("Searching (%s)%s for %s\n", this.nodetype, this.name, fqn);
355 var bits = fqn.split(".");
357 var ret = this.classes.get(bits[0]);
359 if (bits.length < 2) {
362 return ret.fetchByFqn(fqn.substring(bits[0].length+1));
365 ret = this.ctors.get(bits[0]);
367 if (bits.length < 2) {
370 return ret.fetchByFqn(fqn.substring(bits[0].length+1));
373 ret = this.methods.get(bits[0]);
375 if (bits.length < 2) {
378 return ret.fetchByFqn(fqn.substring(bits[0].length+1));
380 ret = this.props.get(bits[0]);
382 if (bits.length < 2) {
385 return ret.fetchByFqn(fqn.substring(bits[0].length+1));
387 ret = this.consts.get(bits[0]);
389 if (bits.length < 2) {
392 return ret.fetchByFqn(fqn.substring(bits[0].length+1));
395 ret = this.signals.get(bits[0]);
397 if (bits.length < 2) {
400 return ret.fetchByFqn(fqn.substring(bits[0].length+1));
402 ret = this.delegates.get(bits[0]);
404 // delegates are only on namespaces...
409 if (this.paramset == null) {
412 var iter = this.paramset.params.list_iterator();
413 while (iter.next()) {
415 if (p.name != bits[0]) {
421 // fixme - other queires? - enums?
425 * -----------------------------------------------
426 * code relating to the structure loader ....
430 public GirObject clsToObject(Project.Project project , string in_pn)
435 var gir = Gir.factory (project, this.ns);
436 if (in_pn.contains(".")) {
437 gir = Gir.factory(project, in_pn.split(".")[0]);
438 pn = in_pn.split(".")[1];
442 return gir.classes.get(pn);
448 public JsRender.NodeProp toNodeProp( Palete pal, string par_xtype)
451 if (this.nodetype.down() == "signal") { // gtk is Signal, roo is signal??
452 // when we add properties, they are actually listeners attached to signals
453 // was a listener overrident?? why?
454 var r = new JsRender.NodeProp.listener(this.name, this.sig);
455 r.propertyof = this.propertyof;
456 if (this.name == "notify" && pal.name == "Gtk") {
457 this.nodePropAddNotify(r, par_xtype, pal);
463 // does not handle Enums... - no need to handle anything else.
464 var def = this.type.contains(".") ? "" : Gir.guessDefaultValueForType(this.type);
465 if (this.type.contains(".") || this.type.contains("|") || this.type.contains("/")) {
466 var ret = new JsRender.NodeProp.prop(this.name, this.type, def); ///< was raw..?
467 ret.propertyof = this.propertyof;
468 this.nodePropAddChildren(ret, this.type, pal);
469 if (ret.childstore.n_items == 1) {
470 var np = (JsRender.NodeProp) ret.childstore.get_item(0);
471 ret.add_node = np.add_node;
472 ret.childstore.remove_all();
478 if (this.type.down() == "function" ) {
479 var r = new JsRender.NodeProp.raw(this.name, this.type, "function()\n{\n\n}");
480 r.propertyof = this.propertyof;
483 if (this.type.down() == "array" ) {
484 var r = new JsRender.NodeProp.raw(this.name, this.type, "[\n\n]");
485 r.propertyof = this.propertyof;
488 if (this.type.down() == "object" ) {
489 var r = new JsRender.NodeProp.raw(this.name, this.type, "{\n\n}");
490 r.propertyof = this.propertyof;
493 // plain property.. no children..
494 var r = new JsRender.NodeProp.prop(this.name, this.type, def); // signature?
495 r.propertyof = this.propertyof;
499 public void nodePropAddChildren(JsRender.NodeProp par, string str, Palete pal)
503 if (str.contains("|")) {
504 var ar = str.split("|");
505 for(var i = 0; i < ar.length; i++) {
506 this.nodePropAddChildren(par, ar[i], pal);
510 if (str.contains("/")) {
511 var ar = str.split("/");
512 for(var i = 0; i < ar.length; i++) {
513 this.nodePropAddChildren(par, ar[i], pal);
517 var cls = pal.getClass(str);
519 // if node does not have any children and the object type only has 1 type.. then we dont add anything...
520 // note all classes are expected to have '.' seperators
521 if (cls == null || !str.contains(".")) {
522 GLib.debug("nodepropaddchildren: check class %s - not found in classes", str);
523 par.childstore.append( new JsRender.NodeProp.prop(this.name, str, Gir.guessDefaultValueForType(str)));
526 GLib.debug("nodepropaddchildren: check class %s - type = %s", str, cls.nodetype);
527 if (cls.nodetype.down() == "enum") {
528 var add = new JsRender.NodeProp.raw(this.name, str, "");
529 par.childstore.append( add);
534 if (cls.nodetype.down() == "class") {
535 var add = new JsRender.NodeProp.raw(this.name, str, "");
539 add.add_node = pal.fqnToNode(str);
540 add.add_node.add_prop(new JsRender.NodeProp.special("prop", this.name));
541 par.childstore.append( add);
546 if (cls.implementations.size < 1) {
547 GLib.debug("nodepropaddchildren: check class %s - no implementations", str);
551 GLib.debug("nodepropaddchildren: check class %s", str);
553 foreach (var cname in cls.implementations) {
556 var subcls = pal.getClass(cname);
558 GLib.debug("nodepropaddchildren: check class %s add %s type %s", str, cname, subcls == null ? "NO?" :subcls.nodetype );
559 if (subcls.nodetype.down() != "class") {
564 var add = new JsRender.NodeProp.raw(this.name, cname, "");
566 add.add_node = pal.fqnToNode(cname);
567 add.add_node.add_prop(new JsRender.NodeProp.special("prop", this.name));
568 par.childstore.append( add);
577 public void nodePropAddNotify(JsRender.NodeProp par, string par_xtype, Palete pal)
579 var els = pal.getPropertiesFor( par_xtype, JsRender.NodePropType.PROP);
580 foreach(var elname in els.keys) {
581 var add = new JsRender.NodeProp.listener("notify[\"" + elname +"\"]" , "() => {\n }");
582 add.propertyof = par.propertyof;
583 par.childstore.append( add);