9 public class Introspect.El : Object
23 public class Roo : Palete {
25 Gee.ArrayList<string> top_classes;
28 public Roo(Project.Project project)
35 this.top_classes = new Gee.ArrayList<string>();
38 Gee.HashMap<string,GirObject> propsFromJSONArray(string type, Json.Array ar, GirObject cls)
41 var ret = new Gee.HashMap<string,GirObject>();
43 for (var i =0 ; i < ar.get_length(); i++) {
44 var o = ar.get_object_element(i);
45 var name = o.get_string_member("name");
46 var prop = new GirObject(type, name );
48 prop.type = o.get_string_member("type");
49 prop.doctxt = o.get_string_member("desc");
50 prop.propertyof = o.has_member("memberOf") ? o.get_string_member("memberOf") : "";
51 if (prop.propertyof.length < 1) {
52 prop.propertyof = cls.name;
55 // this is the function default.
56 prop.sig = o.has_member("sig") ? o.get_string_member("sig") : "";
58 if (o.has_member("optvals") ) {
59 var oar = o.get_array_member("optvals");
61 for (var oi = 0; oi < oar.get_length(); oi++) {
62 prop.optvalues.add(oar.get_string_element(oi));
67 //print(type + ":" + name +"\n");
74 public override void load () {
76 if (this.classes != null) {
79 // this.loadUsageFile(BuilderApplication.configDirectory() + "/resources/RooUsage.txt");
80 this.classes = new Gee.HashMap<string,GirObject>();
81 var add_to = new Gee.HashMap<string,Gee.ArrayList<string>>();
83 var pa = new Json.Parser();
84 pa.load_from_file(BuilderApplication.configDirectory() + "/resources/roodata.json");
85 var node = pa.get_root();
87 var clist = node.get_object(); /// was in data... .get_object_member("data");
88 clist.foreach_member((o , key, value) => {
89 //print("cls:" + key+"\n");
91 var cls = new GirObject("class", key);
92 cls.props = this.propsFromJSONArray("prop", value.get_object().get_array_member("props"),cls);
93 cls.signals = this.propsFromJSONArray("signal", value.get_object().get_array_member("events"),cls);
96 if (value.get_object().has_member("methods")) {
97 cls.methods = this.propsFromJSONArray("method", value.get_object().get_array_member("methods"),cls);
99 if (value.get_object().has_member("implementations")) {
100 var vcn = value.get_object().get_array_member("implementations");
101 for (var i =0 ; i < vcn.get_length(); i++) {
102 cls.implementations.add(vcn.get_string_element(i));
108 if (value.get_object().has_member("tree_children")) {
109 var vcn = value.get_object().get_array_member("tree_children");
110 for (var i =0 ; i < vcn.get_length(); i++) {
111 var ad_c = vcn.get_string_element(i);
112 if (!cls.valid_cn.contains(ad_c)) {
113 cls.valid_cn.add( ad_c );
115 if (!add_to.has_key(ad_c)) {
116 add_to.set(ad_c, new Gee.ArrayList<string>());
118 if (!add_to.get(ad_c).contains(cls.name)) {
119 add_to.get(ad_c).add(cls.name);
129 if (value.get_object().has_member("tree_parent")) {
130 var vcn = value.get_object().get_array_member("tree_parent");
131 for (var i =0 ; i < vcn.get_length(); i++) {
132 if ("builder" == vcn.get_string_element(i)) {
133 // this class can be added to the top level.
134 GLib.debug("Add %s to *top", cls.name);
136 this.top_classes.add(cls.name);
143 this.classes.set(key, cls);
146 // look for properties of classes, that are atually clasess
147 // eg. Roo.data.Store has proxy and reader..
150 foreach(var cls in this.classes.values) {
151 foreach(var gir_obj in cls.props.values) {
152 var types = gir_obj.type.split("|");
153 for(var i =0; i < types.length; i++) {
156 if (/^Roo\./.match(type) && classes.has_key(type)) {
159 cls.valid_cn.add(type + ":" + gir_obj.name );
160 // Roo.bootstrap.panel.Content:east
161 // also means that Roo.bootstrap.panel.Grid:east works
162 var prop_type = classes.get(type);
163 foreach(var imp_str in prop_type.implementations) {
164 //GLib.debug("addChild for %s - child= %s:%s", cls.name, imp_str, gir_obj.name);
165 cls.valid_cn.add(imp_str + ":" + gir_obj.name);
166 if (!add_to.has_key(imp_str)) {
167 add_to.set( imp_str, new Gee.ArrayList<string>());
169 if (!add_to.get( imp_str).contains(cls.name)) {
170 add_to.get( imp_str ).add(cls.name );
176 if (!add_to.has_key( type)) {
177 add_to.set( type, new Gee.ArrayList<string>());
179 if (!add_to.get(type).contains(cls.name)) {
180 add_to.get( type ).add(cls.name );
187 foreach(var cls in this.classes.values) {
188 if (add_to.has_key(cls.name)) {
189 cls.can_drop_onto = add_to.get(cls.name);
196 public string doc(string what) {
198 /*var ns = what.split(".")[0];
203 var gir = Gir.factory(ns);
204 return gir.doc(what);
207 //return typeof(this.comments[ns][what]) == 'undefined' ? '' : this.comments[ns][what];
210 // does not handle implements...
211 public override GirObject? getClass(string ename)
214 return this.classes.get(ename);
218 public override Gee.HashMap<string,GirObject> getPropertiesFor(string ename, JsRender.NodePropType ptype)
220 //print("Loading for " + ename);
224 // if (typeof(this.proplist[ename]) != 'undefined') {
225 //print("using cache");
226 // return this.proplist[ename][type];
228 // use introspection to get lists..
231 var cls = this.classes.get(ename);
232 var ret = new Gee.HashMap<string,GirObject>();
234 print("could not find class: %s\n", ename);
236 //throw new Error.INVALID_VALUE( "Could not find class: " + ename);
241 //cls.parseSignals(); // ?? needed for add handler..
242 //cls.parseMethods(); // ?? needed for ??..
243 //cls.parseConstructors(); // ?? needed for ??..
245 //cls.overlayParent();
250 case JsRender.NodePropType.PROP:
251 return this.filterProps(cls.props);
252 case JsRender.NodePropType.LISTENER:
254 case JsRender.NodePropType.METHOD:
256 case JsRender.NodePropType.CTOR:
259 throw new Error.INVALID_VALUE( "getPropertiesFor called with: " + ptype.to_string());
260 //var ret = new Gee.HashMap<string,GirObject>();
266 //cls.overlayInterfaces(gir);
273 // get rid of objecst from props list.. (assumed to be anything with 'dot' in the type.
274 public Gee.HashMap<string,GirObject> filterProps(Gee.HashMap<string,GirObject> props)
276 // we shold probably cache this??
278 var outprops = new Gee.HashMap<string,GirObject>();
280 foreach(var k in props.keys) {
281 var val = props.get(k);
283 if (!val.type.contains(".")) {
288 // do nothing? - classes not allowed?
298 public string[] getInheritsFor(string ename)
301 var es = ename.split(".");
302 var gir = Gir.factory(null, es[0]);
304 var cls = gir.classes.get(es[1]);
308 return cls.inheritsToStringArray();
314 public override void on_child_added(JsRender.Node? parent,JsRender.Node child)
320 * Pulldown options for type
322 public override bool typeOptions(string fqn, string key, string type, out string[] opts)
325 print("get typeOptions %s (%s)%s", fqn, type, key);
326 if (type.up() == "BOOL" || type.up() == "BOOLEAN") {
327 opts = { "true", "false" };
331 var props = this.getPropertiesFor(fqn, JsRender.NodePropType.PROP);
332 if (!props.has_key(key)) {
333 print("prop %s does not have key %s\n", fqn, key);
336 var pr = props.get(key);
337 if (pr.optvalues.size < 1) {
338 print("prop %s no optvalues for %s\n", fqn, key);
342 for(var i = 0; i < pr.optvalues.size; i++) {
343 ret += pr.optvalues.get(i);
346 print("prop %s returning optvalues for %s\n", fqn, key);
350 public override List<SourceCompletionItem> suggestComplete(
351 JsRender.JsRender file,
353 JsRender.NodeProp? xxprop,
354 string complete_string
357 var ret = new List<SourceCompletionItem>();
358 // completion rules??
362 // this. (based on the node type)
363 // this.xxx // Node and any determination...
365 if (complete_string.index_of(".",0) < 0) {
366 // string does not have a '.'
367 // offer up this / Roo / javascript keywords... / look for var string = .. in the code..
368 for(var i = 0; i < JsRender.Lang.match_strings.size ; i++) {
369 var str = JsRender.Lang.match_strings.get(i);
370 if (complete_string != str && str.index_of(complete_string,0) == 0 ) { // should we ignore exact matches... ???
371 ret.append(new SourceCompletionItem (str, str, null, "javascript : " + str));
376 if (complete_string != "Roo" && "Roo".index_of(complete_string,0) == 0 ) { // should we ignore exact matches... ???
377 ret.append(new SourceCompletionItem ("Roo - A Roo class", "Roo", null, "Roo library"));
379 if (complete_string != "_this" && "_this".index_of(complete_string,0) == 0 ) { // should we ignore exact matches... ???
380 ret.append(new SourceCompletionItem ("_this - the top level element", "_this", null, "Top level element"));
384 // got at least one ".".
385 var parts = complete_string.split(".");
387 var cur_instance = false;
388 if (parts[0] == "this") {
389 // work out from the node, what the type is...
391 print("node is empty - no return\n");
392 return ret; // no idea..
394 curtype = node.fqn();
397 if (parts[0] == "Roo") {
399 cur_instance = false;
402 var prevbits = parts[0] + ".";
403 for(var i =1; i < parts.length; i++) {
404 print("matching %d/%d\n", i, parts.length);
405 var is_last = i == parts.length -1;
407 // look up all the properties of the type...
408 var cls = this.getClass(curtype);
410 print("could not get class of curtype %s\n", curtype);
416 // only exact matches from here on...
418 if (cls.props.has_key(parts[i])) {
419 var prop = cls.props.get(parts[i]);
420 if (prop.type.index_of(".",0) > -1) {
421 // type is another roo object..
423 prevbits += parts[i] + ".";
431 // check methods?? - we do not export that at present..
432 return ret; //no idea...
436 //look for child classes.
437 var citer = this.classes.map_iterator();
439 while (citer.next()) {
440 var scls = citer.get_key();
441 var look = prevbits + parts[i];
442 if (scls.index_of(look,0) != 0) {
445 // got a starting match..
447 cur_instance = false;
454 prevbits += parts[i] + ".";
457 // got to the last element..
458 print("Got last element\n");
459 if (curtype == "") { // should not happen.. we would have returned already..
462 print("Got last element type %s\n",curtype);
464 print("matching instance");
465 // it's a static reference..
466 var citer = this.classes.map_iterator();
467 while (citer.next()) {
468 var scls = citer.get_key();
469 var look = prevbits + parts[i];
470 if (parts[i].length > 0 && scls.index_of(look,0) != 0) {
473 // got a starting match..
474 ret.append(new SourceCompletionItem (
482 print("matching property");
486 var citer = cls.methods.map_iterator();
487 while (citer.next()) {
488 var prop = citer.get_value();
489 // does the name start with ...
490 if (parts[i].length > 0 && prop.name.index_of(parts[i],0) != 0) {
493 // got a matching property...
495 ret.append(new SourceCompletionItem (
496 prop.name + prop.sig + " : ("+ prop.propertyof + ")",
497 prevbits + prop.name + "(",
502 // get the properties / methods and subclasses.. of cls..
503 // we have cls.. - see if the string matches any of the properties..
504 citer = cls.props.map_iterator();
505 while (citer.next()) {
506 var prop = citer.get_value();
507 // does the name start with ...
508 if (parts[i].length > 0 && prop.name.index_of(parts[i],0) != 0) {
511 // got a matching property...
513 ret.append(new SourceCompletionItem (
514 prop.name + " : " + prop.type + " ("+ prop.propertyof + ")",
515 prevbits + prop.name,
536 public override string[] getChildList(string in_rval)
538 if (this.top_classes.size < 1) {
544 var ar = this.top_classes;
545 if (in_rval != "*top") {
546 if (this.classes.has_key(in_rval)) {
547 // some of these children will be eg: Roo.bootstrap.layout.Region:center
548 ar = this.classes.get(in_rval).valid_cn;
550 ar = new Gee.ArrayList<string>();
554 foreach(var str in ar) {
557 GLib.debug("getChildList for %s returns %s", in_rval, string.joinv(", ", ret));
560 //return this.original_getChildList( in_rval);
562 public override string[] getDropList(string rval)
564 // we might be dragging Roo.bootstrap.layout.Region:center
565 // in which case we need to lookup Roo.bootstrap.layout.Region
566 // and see if it's has can_drop_onto
568 var cls = this.classes.get(rval);
570 if (cls == null && rval.contains(":")) {
571 var rr = rval.substring(0,rval.index_of(":"));
572 GLib.debug("Converted classname to %s", rr);
573 cls = this.classes.get(rr);
576 return ret; //nothing..
579 foreach(var str in cls.can_drop_onto) {
583 GLib.debug("getDropList for %s return[] %s", rval, string.joinv(", ", ret));
588 //return this.default_getDropList(rval);