Fix #6912 - issue with parsing Roo.lib.Dom
[roojspacker] / roojspacker / Symbol.vala
1  
2 /**
3         Create a new Symbol.
4         @class Represents a symbol in the source code.
5  */
6
7  
8 namespace JSDOC {
9
10
11         public  class Symbol : Object
12         {
13                 // debugging?
14                 
15                 
16                 public static bool regex_init = false;
17                 
18
19                 private string private_string_name = "";
20                 private string _assigned_name = "";
21                 // called by symbolset...
22                 public string private_name {
23                 set {
24                                 this._assigned_name = name;
25                                 var n = /^_global_[.#-]/.replace(value, value.length, 0, "");
26                         n =  /\.prototype\.?/.replace(n,n.length, 0, "#");
27                         while (true) {
28                                 if (!n.has_suffix("#")) {
29                                         break;
30                                         }
31                                         n = n.substring(0, n.length-1);
32                                 }
33                         
34                         this.private_string_name = n;
35                 }
36                 
37                 }
38                  
39         public string name {
40                 get { return this.private_string_name; }
41                 }
42                 
43       
44         string defaultValue = "";        
45                 private Gee.ArrayList<DocTag> private_doctag_params = null;
46
47                 private Gee.ArrayList<DocTag> private_params{
48                         set  {
49                                 if (this.private_doctag_params == null) {
50                                         this.private_doctag_params = new Gee.ArrayList<DocTag>();
51                                 }
52                                 for (var i = 0; i < value.size; i++) {
53                                    
54                                     this.private_doctag_params.add(value.get(i));
55                                 }
56                                 //this.params = this._params;
57                         }
58                 }
59      
60                 Gee.ArrayList<string> private_string_params{
61                         set  {
62                                 if (this.private_doctag_params == null) {
63                                         this.private_doctag_params = new Gee.ArrayList<DocTag>();
64                                 }
65                                 for (var i = 0; i < value.size; i++) {
66
67                                     //var ty = v[i].hasOwnProperty('type') ? v[i].type : '';
68                                     this.private_doctag_params.add( new DocTag(value.get(i)));
69                                            
70                                    //"param"+((ty)?" {"+ty+"}":"")+" "+v.get(i).name);
71                                     
72                                 }
73                                 
74                         }
75                 }
76                 public Gee.ArrayList<DocTag> params {
77                         get {
78                                 if (this.private_doctag_params == null) {
79                                         this.private_doctag_params = new Gee.ArrayList<DocTag>();
80                                 }
81                                 return this.private_doctag_params;
82                         }
83                 
84                 }
85
86                 public Gee.ArrayList<string>  augments ;  
87                 
88
89                 private Gee.ArrayList<DocTag>  exceptions ;
90
91                 //public Gee.ArrayList<DocTag>  inherits; 
92                 public Gee.ArrayList<Symbol>  methods;
93
94                 public Gee.ArrayList<Symbol> properties;
95                 private Gee.ArrayList<string> requires;
96                 public Gee.ArrayList<DocTag> returns;
97                 private Gee.ArrayList<string> see ;
98
99                 public Gee.HashMap<string,Gee.ArrayList<string>> childClasses;
100                 public Gee.ArrayList<string> childClassesList;
101                 public Gee.ArrayList<string> inheritsFrom;
102                 public Gee.HashMap<string,DocTag>cfgs;
103
104
105                 public Gee.ArrayList<string> tree_parent;
106                 public Gee.ArrayList<string> tree_children;
107                 
108
109         public DocComment comment;
110                 
111         //$args : [], // original arguments used when constructing.
112         //string addOn = "";
113         public string alias = "";
114         
115         string author = "";
116         string classDesc = "";
117
118         string deprecated = "";
119         public string desc = "";
120         //events : false,
121         string example = "";
122         
123
124                 public string isa = "OBJECT"; // OBJECT//FUNCTION
125         
126                 public bool isEvent = false;
127                 public bool isConstant = false;
128                 public bool isIgnored = false;
129                 public bool isInner = false;
130                 public bool isNamespace = false;
131                 public bool isPrivate = false;
132                 public bool isStatic = false;
133                 public bool isAbstract = false;
134                 public bool isBuilderTop = false;
135         
136         public string memberOf = "";
137
138                 public string asString()
139                 {
140                         return "NAME: %s:%s   ASNAME: %s : %s%s%s%s".printf(
141                                 this.memberOf,
142                                 this.name,
143                                 this._assigned_name,
144                                 isStatic ? "static": "",
145                                 isEvent ? "EV": "",
146                                 isConstant ? "CO": "",
147                                 isNamespace ? "NS": ""
148                         );
149                                 
150                 
151                 }
152
153        
154         string since = "";
155
156         string type = "";
157         string version = "";
158        
159         public static string srcFile = "";
160         
161         
162         
163         public void initArrays()
164         {
165             // only initialize arrays / objects..
166
167             
168             //this.params = [];
169             //this.$args = [];
170             
171             //this.events = [];
172             this.exceptions = new Gee.ArrayList<DocTag>();
173             //this.inherits = new Gee.ArrayList<DocTag>();
174             //
175             this.isa = "OBJECT"; // OBJECT//FUNCTION
176             this.methods = new Gee.ArrayList<Symbol>();
177             //this.private_params = new Gee.ArrayList<DocTag>();
178             this.properties = new Gee.ArrayList<Symbol>();
179             this.requires = new Gee.ArrayList<string>();
180             this.returns = new Gee.ArrayList<DocTag>();
181             this.see = new Gee.ArrayList<string>();
182             this.augments = new Gee.ArrayList<string>();
183  
184             
185             this.cfgs = new Gee.HashMap<string,DocTag>();
186             // what is this?
187             this.inheritsFrom = new Gee.ArrayList<string>();
188
189             this.childClasses = new Gee.HashMap<string,Gee.ArrayList<string>>();
190             this.childClassesList = new Gee.ArrayList<string>();
191             
192             this.tree_parent = new Gee.ArrayList<string>();
193             this.tree_children = new Gee.ArrayList<string>();
194             
195              
196             this.comment = new DocComment();
197             this.comment.isUserComment =  false;
198             
199                
200         }
201                 
202                 public Symbol.new_builtin(string name)
203                 {
204             
205             this.initArrays();
206             this.srcFile = JSDOC.DocParser.currentSourceFile;
207                         this.private_name =  name ;
208                         this.alias = this.name;
209                         this.isa = "CONSTRUCTOR";
210                         this.comment = new DocComment("");
211                         this.comment.isUserComment =  false;
212                         this.isNamespace = false;
213                         this.srcFile = "";
214                         this.isPrivate = false;
215                         // init arrays....
216                         
217                         
218                         
219                 }
220                 
221
222  
223
224         public Symbol.new_populate_with_args(
225                 string  name,
226                 Gee.ArrayList<string> params, // fixme???
227                 string isa,
228                 DocComment comment
229         ) {
230            
231             this.initArrays();
232            // this.$args = arguments;
233             //println("Symbol created: " + isa + ":" + name);
234             this.private_name = name;
235             this.alias = this.name;
236             this.private_string_params = params; 
237             this.isa = (isa == "VIRTUAL")? "OBJECT":isa;
238             this.comment =  comment;
239             
240             this.srcFile = DocParser.currentSourceFile;
241             
242            
243             
244             if (this.is("FILE") && this.alias.length < 1) { // this will never hapen???
245                         this.alias = this.srcFile;
246                 }
247
248             this.tagsFromComment();
249             
250         }
251
252         void tagsFromComment() 
253         {
254             // @author
255             var authors = this.comment.getTag(DocTagTitle.AUTHOR);
256             if (authors.size > 0) {
257                         // turns author into a string....
258                         this.author = "";
259                 foreach(var a in authors) {
260                     this.author += (this.author == "") ? "": ", ";
261                     this.author += a.desc;
262                 }
263             }
264             
265             /*~t
266                 assert("testing Symbol");
267                 
268                 requires("../lib/JSDOC/DocComment.js");
269                 requires("../frame/String.js");
270                 requires("../lib/JSDOC/DocTag.js");
271
272                 var sym = new Symbol("foo", [], "OBJECT", new DocComment("/**@author Joe Smith*"+"/"));
273                 assertEqual(sym.author, "Joe Smith", "@author tag, author is found.");
274             */
275             // @desc
276             var mth = this.comment.getTag(DocTagTitle.METHOD);
277             if (mth.size  > 0) {
278                 this.isa = "FUNCTION";
279             }
280             // @desc
281             var descs = this.comment.getTag(DocTagTitle.DESC);
282             if (descs.size>  0) {
283                 this.desc = "";
284                 foreach(var d in descs) {
285                     this.desc = this.desc == "" ? "": "\n";
286                     this.desc += d.desc;
287                 }
288
289             }
290             
291             /*~t
292                 var sym = new Symbol("foo", [], "OBJECT", new DocComment("/**@desc This is a description.*"+"/"));
293                 assertEqual(sym.desc, "This is a description.", "@desc tag, description is found.");
294             */
295             
296             // @overview
297             if (this.is("FILE")) {
298                 if (this.alias.length < 1) this.alias = this.srcFile;
299                 
300                 var overviews = this.comment.getTag(DocTagTitle.OVERVIEW);
301                 if (overviews.size > 0) {
302                     foreach(var d in overviews) {
303                         this.desc = this.desc == "" ? "": "\n";
304                         this.desc += d.desc;
305                     }
306                 }
307             }
308             
309             /*~t
310                 var sym = new Symbol("foo", [], "FILE", new DocComment("/**@overview This is an overview.*"+"/"));
311                 assertEqual(sym.desc, "\nThis is an overview.", "@overview tag, description is found.");
312             */
313             
314             // @since
315             var sinces = this.comment.getTag(DocTagTitle.SINCE);
316             if (sinces.size > 0) {
317                 this.since = "";
318                 foreach(var d in sinces) {
319                     this.since = this.since == "" ? "": "\n";
320                     this.since += d.desc;
321                 }
322             }
323             
324             /*~t
325                 var sym = new Symbol("foo", [], "FILE", new DocComment("/**@since 1.01*"+"/"));
326                 assertEqual(sym.since, "1.01", "@since tag, description is found.");
327             */
328             
329             // @constant
330             if (this.comment.getTag(DocTagTitle.CONSTANT).size > 0) {
331                 this.isConstant = true;
332                 this.isa = "OBJECT";
333             }
334             
335             /*~t
336                 var sym = new Symbol("foo", [], "FILE", new DocComment("/**@constant*"+"/"));
337                 assertEqual(sym.isConstant, true, "@constant tag, isConstant set.");
338             */
339             
340             // @version
341             var versions = this.comment.getTag(DocTagTitle.VERSION);
342             if (versions.size > 0 ) {
343                 this.version = "";
344                  foreach(var d in versions) {
345                     this.version = this.version == "" ? "": "\n";
346                     this.version += d.desc;
347                 }
348             }
349             
350             /*~t
351                 var sym = new Symbol("foo", [], "FILE", new DocComment("/**@version 2.0x*"+"/"));
352                 assertEqual(sym.version, "2.0x", "@version tag, version is found.");
353             */
354             
355             // @deprecated
356             var deprecateds = this.comment.getTag(DocTagTitle.DEPRECATED);
357             if (deprecateds.size > 0) {
358                 this.deprecated = "";
359                  foreach(var d in deprecateds) {
360                     this.deprecated = this.deprecated == "" ? "": "\n";
361                     this.deprecated += d.desc;
362                 }
363             }
364             
365             /*~t
366                 var sym = new Symbol("foo", [], "FILE", new DocComment("/**@deprecated Use other method.*"+"/"));
367                 assertEqual(sym.deprecated, "Use other method.", "@deprecated tag, desc is found.");
368             */
369             
370             // @example
371             var examples = this.comment.getTag(DocTagTitle.EXAMPLE);
372             if (examples.size > 0) {
373                 this.example = examples.get(0).desc;
374             }
375             
376             /*~t
377                 var sym = new Symbol("foo", [], "FILE", new DocComment("/**@example This\n  is an example.*"+"/"));
378                 assertEqual(sym.example, "This\n  is an example.", "@deprecated tag, desc is found.");
379             */
380             
381             // @see
382             var sees = this.comment.getTag(DocTagTitle.SEE);
383             if (sees.size > 0) {
384                  
385                 foreach(var s in sees) {
386                     this.see.add(s.desc);
387                 }
388           }
389             
390             /*~t
391                 var sym = new Symbol("foo", [], "FILE", new DocComment("/**@see The other thing.*"+"/"));
392                 assertEqual(sym.see, "The other thing.", "@see tag, desc is found.");
393             */
394             
395             // @class
396             var classes = this.comment.getTag(DocTagTitle.CLASS);
397             if (classes.size > 0) {
398                 //print(JSON.stringify(this,null,4));
399                 this.isa = "CONSTRUCTOR";
400                 this.classDesc = classes[0].desc; // desc can't apply to the constructor as there is none.
401                 //if (!this.classDesc.leg) {
402                 //    this.classDesc = this.desc;
403                 //   }
404                 
405                 
406             }
407             
408             /*~t
409                 var sym = new Symbol("foo", [], "OBJECT", new DocComment("/**@class This describes the class.*"+"/"));
410                 assertEqual(sym.isa, "CONSTRUCTOR", "@class tag, makes symbol a constructor.");
411                 assertEqual(sym.classDesc, "This describes the class.", "@class tag, class description is found.");
412             */
413             
414             // @namespace
415             var namespaces = this.comment.getTag(DocTagTitle.NAMESPACE);
416             if (namespaces.size > 0) {
417                 this.classDesc = namespaces[0].desc+"\n"+this.desc; // desc can't apply to the constructor as there is none.
418                 this.isNamespace = true;
419             }
420             
421             /*~t
422                 var sym = new Symbol("foo", [], "OBJECT", new DocComment("/**@namespace This describes the namespace.*"+"/"));
423                 assertEqual(sym.classDesc, "This describes the namespace.\n", "@namespace tag, class description is found.");
424             */
425             
426             // @param
427             var params = this.comment.getTag(DocTagTitle.PARAM);
428             if (params.size > 0) {
429                 // user-defined params overwrite those with same name defined by the parser
430                 var thisParams = params;
431
432                 if (thisParams.size == 0) { // none exist yet, so just bung all these user-defined params straight in
433                     this.private_params = params;
434                 }
435                 else { // need to overlay these user-defined params on to existing parser-defined params
436                     for (var i = 0, l = params.size; i < l; i++) {
437                         if (thisParams.size <= i) {
438                                 var np = thisParams.get(i);
439                                 
440                             if (np.type.length > 0) np.type = params[i].type;
441                             np.name = params[i].name;
442                             np.desc = params[i].desc;
443                             np.isOptional = params[i].isOptional;
444                             np.defaultValue = params[i].defaultValue;
445                             //thisParams.set(i, np); ///?? needed OO ?
446                         }
447                         else thisParams.set(i, params[i]);
448                     }
449                     this.private_params = thisParams;
450                 }
451             }
452             
453             
454             
455             // @constructor
456             if (this.comment.getTag(DocTagTitle.CONSTRUCTOR).size > 0) {
457                 this.isa = "CONSTRUCTOR";
458             }
459             
460          
461             
462             // @static
463             if (this.comment.getTag(DocTagTitle.STATIC).size > 0) {
464                 this.isStatic = true;
465                 if (this.isa == "CONSTRUCTOR") {
466                     this.isNamespace = true;
467                 }
468             }
469             
470                 // @static
471             if (this.comment.getTag(DocTagTitle.SINGLETON).size > 0) {
472                 this.isStatic = true;
473                 //print('------------- got singleton ---------------' + this.isa);
474                 //if (this.isa == "CONSTRUCTOR") {
475                 //      this.isNamespace = true;
476                 //}
477             }
478             
479             
480             
481             // @inner
482             if (this.comment.getTag(DocTagTitle.INNER).size > 0) {
483                 this.isInner = true;
484                 this.isStatic = false;
485             }
486             
487             
488             // @field
489             if (this.comment.getTag(DocTagTitle.FIELD).size > 0) {
490                 this.isa = "OBJECT";
491             }
492             
493            
494             
495             // @function
496             if (this.comment.getTag(DocTagTitle.FUNCTION).size > 0) {
497                 this.isa = "FUNCTION";
498             }
499             
500             // @param
501             if (this.comment.getTag(DocTagTitle.PARAM).size > 0 && this.isa == "OBJECT" ) {
502                 // change a property to a function..
503                 this.isa = "FUNCTION";
504             }
505             
506             
507              
508             
509             // @event
510             var events = this.comment.getTag(DocTagTitle.EVENT);
511             if (events.size > 0) {
512                 this.isa = "FUNCTION";
513                 this.isEvent = true;
514             }
515             
516             
517             
518             // @name
519             var names = this.comment.getTag(DocTagTitle.NAME);
520             if (names.size > 0) {
521                 this.private_name = names.get(0).desc.strip();
522             }
523             
524             /*~t
525                 // todo
526             */
527             
528             // @property
529             var properties = this.comment.getTag(DocTagTitle.PROPERTY);
530             if (properties.size > 0) {
531                 //var thisProperties = this.properties;
532                 for (var i = 0; i < properties.size; i++) {
533
534                                         
535                                         // if the doc tag just says @property ... but no name etc..
536                                         // then name will not be filled in..
537                                         if (properties[i].name.length < 1 ) {
538                                                 continue;
539                                         }
540
541                     var property = new Symbol.new_populate_with_args(
542                         this.alias+"#"+properties[i].name,
543                          new Gee.ArrayList<string>(), 
544                         "OBJECT",
545                          new DocComment(
546                             "/**\n"+
547                                 properties[i].desc+
548                                 "\n@name "+ properties[i].name
549                                 +"\n@memberOf "+this.alias+"#*/"
550                     ));
551                     // TODO: shouldn't the following happen in the addProperty method of Symbol?
552                     property.private_name = properties[i].name;
553                     property.memberOf = this.alias;
554                     if (properties[i].type.length > 0) property.type = properties[i].type;
555                     if (properties[i].defaultValue.length > 0) property.defaultValue = properties[i].defaultValue;
556                     this.addProperty(property);
557                     JSDOC.DocParser.addSymbol(property);
558                 }
559             }
560             
561             // config..
562             var conf = this.comment.getTag(DocTagTitle.CFG);
563             if (conf.size > 0) {
564                 for (var i = 0; i < conf.size; i++) {
565                     this.addConfig(conf.get(i));
566                 }
567             }
568             
569           
570
571             // @return
572             var returns = this.comment.getTag(DocTagTitle.RETURN);
573             if (returns.size > 0) { // there can be many return tags in a single doclet
574                 this.returns = returns;
575
576                 this.type = "";
577                 foreach(var r in returns) {
578                     this.type += this.type == "" ? "": ", ";
579                     this.type += r.type;
580                 } 
581              }
582             
583             
584             
585             // @exception
586             this.exceptions = this.comment.getTag(DocTagTitle.THROWS);
587             
588            
589             // @requires
590             var requires = this.comment.getTag(DocTagTitle.REQUIRES);
591             if (requires.size > 0) {
592                 this.requires = new Gee.ArrayList<string>();
593                 foreach(var r in requires) {
594                     this.requires.add(r.desc);
595                 }
596             }
597            
598             
599             // @type
600             var types = this.comment.getTag(DocTagTitle.TYPE);
601             if (types.size > 0) {
602                 this.type = types.get(0).desc; //multiple type tags are ignored
603             }
604             
605             
606             
607             // @private
608             if (this.comment.getTag(DocTagTitle.PRIVATE).size > 0 || this.isInner) {
609                 this.isPrivate = true;
610             }
611             
612             // @ignore
613             if (this.comment.getTag(DocTagTitle.IGNORE).size > 0) {
614                 this.isIgnored = true;
615             }
616             
617             /*~t
618                 // todo
619             */
620             
621             // @inherits ... as ... -- not used!!!
622             /*
623             var inherits = this.comment.getTag("inherits");
624             if (inherits.length) {
625                 for (var i = 0; i < inherits.length; i++) {
626                     if (/^\s*([a-z$0-9_.#-]+)(?:\s+as\s+([a-z$0-9_.#]+))?/i.test(inherits[i].desc)) {
627                         var inAlias = RegExp.$1;
628                         var inAs = RegExp.$2 || inAlias;
629
630                         if (inAlias) inAlias = inAlias.replace(/\.prototype\.?/g, "#");
631                         
632                         if (inAs) {
633                             inAs = inAs.replace(/\.prototype\.?/g, "#");
634                             inAs = inAs.replace(/^this\.?/, "#");
635                         }
636
637                         if (inAs.indexOf(inAlias) != 0) { //not a full namepath
638                             var joiner = ".";
639                             if (this.alias.charAt(this.alias.length-1) == "#" || inAs.charAt(0) == "#") {
640                                 joiner = "";
641                             }
642                             inAs = this.alias + joiner + inAs;
643                         }
644                     }
645                     this.inherits.push({alias: inAlias, as: inAs});
646                 }
647             }
648             */
649             /*~t
650                 // todo
651             */
652
653             // @augments
654             foreach(var dt in this.comment.getTag(DocTagTitle.ARGUMENTS)) {
655                 this.augments.add(dt.desc);
656                 }
657             //@extends - Ext            
658             foreach(var dt in this.comment.getTag(DocTagTitle.EXTENDS)) {
659                 this.augments.add(dt.desc);
660                 }
661             
662             
663             
664             // @default
665             var defaults = this.comment.getTag(DocTagTitle.DEFAULT);
666             if (defaults.size > 0) {
667                 if (this.is("OBJECT")) {
668                     this.defaultValue = defaults.get(0).desc;
669                 }
670             }
671             
672             /*~t
673                 // todo
674             */
675             
676             // @memberOf
677             var memberOfs = this.comment.getTag(DocTagTitle.MEMBEROF);
678             if (memberOfs.size > 0) {
679                 this.memberOf = memberOfs[0].desc;
680                 var pr_reg = /\.prototype\.?/;
681                 
682                 this.memberOf = pr_reg.replace(this.memberOf, this.memberOf.length, 0, "#");
683                 var dname = this.name.split(".");
684                 var name = dname[dname.length-1];
685                 
686                 var hname = name.split("#");
687                 name = hname[hname.length-1];
688                 this.private_name = this.memberOf + "." + name; //?? "." ???
689                 this.alias = this.name;
690             }
691
692            
693              
694             // @public
695             if (this.comment.getTag(DocTagTitle.PUBLIC).size > 0) {
696                 this.isPrivate = false;
697             }
698              
699             // @children
700              if (this.comment.getTag(DocTagTitle.CHILDREN).size > 0) {
701                 foreach(var s in this.comment.getTag(DocTagTitle.CHILDREN).get(0).desc.strip().split(" ")) {
702                         this.tree_children.add(s);
703                 }
704             }
705             // @parent
706              if (this.comment.getTag(DocTagTitle.PARENT).size > 0) {
707                 foreach(var s in this.comment.getTag(DocTagTitle.PARENT).get(0).desc.strip().split(" ")) {
708                         this.tree_parent.add(s);
709                 }
710             }
711                         
712             // @abstract
713             if (this.comment.getTag(DocTagTitle.ABSTRACT).size > 0) {
714                 this.isAbstract = true;
715             }
716                         // @builder-top            
717                         if (this.comment.getTag(DocTagTitle.BUILDER_TOP).size > 0) {
718                 this.isBuilderTop = true;
719             }
720             
721             
722             
723              
724         }
725
726         public bool is (string what) {
727             return this.isa == what;
728         }
729         public bool isaClass()
730         {
731         
732                 return (this.is("CONSTRUCTOR") || this.isNamespace ); //|| this.isClass); 
733         }
734         
735  
736         public bool isBuiltin() {
737             return SymbolSet.isBuiltin(this.alias);
738         }
739
740         void setType(string comment,bool overwrite) {
741             if (!overwrite && this.type.length > 0) {
742                  return;
743                  }
744             var typeComment = DocComment.unwrapComment(comment);
745             this.type = typeComment;
746         }
747
748         public void inherit (Symbol symbol) {
749             if (!this.hasMember(symbol.name) && !symbol.isInner) {
750                 if (symbol.is("FUNCTION"))
751                     this.methods.add(symbol);
752                 else if (symbol.is("OBJECT"))
753                     this.properties.add(symbol);
754             }
755         }
756
757         bool hasMember (string name) {
758             return (this.hasMethod(name) || this.hasProperty(name));
759         }
760
761         public void addMember (Symbol symbol) {
762             //println("ADDMEMBER: " + this.name +  " ++ " + symbol.name);
763             
764             if (symbol.comment.getTag(DocTagTitle.CFG).size == 1) { 
765                 symbol.comment.getTag(DocTagTitle.CFG).get(0).memberOf = this.alias;
766                 this.addConfig(symbol.comment.getTag(DocTagTitle.CFG).get(0));
767                 return;
768             }
769             
770             if (symbol.is("FUNCTION")) { this.addMethod(symbol); }
771             else if (symbol.is("OBJECT")) { this.addProperty(symbol); }
772         }
773
774         bool hasMethod (string name) {
775             var thisMethods = this.methods;
776             for (var i = 0, l = thisMethods.size; i < l; i++) {
777                 if (thisMethods.get(i).name == name) return true;
778                 if (thisMethods.get(i).alias == name) return true;
779             }
780             return false;
781         }
782
783         void addMethod (Symbol symbol) {
784             var methodAlias = symbol.alias;
785             var thisMethods = this.methods;
786             for (var i = 0, l = thisMethods.size; i < l; i++) {
787                 if (thisMethods.get(i).alias == methodAlias) {
788                     thisMethods.set(i, symbol); // overwriting previous method
789                     return;
790                 }
791             }
792             thisMethods.add(symbol); // new method with this alias
793         }
794
795         bool hasProperty(string name) {
796             var thisProperties = this.properties;
797             for (var i = 0, l = thisProperties.size; i < l; i++) {
798                 if (thisProperties.get(i).name == name) return true;
799                 if (thisProperties.get(i).alias == name) return true;
800             }
801             return false;
802         }
803
804         void addProperty(Symbol symbol) {
805             var propertyAlias = symbol.alias;
806             var thisProperties = this.properties;
807             for (var i = 0, l = thisProperties.size; i < l; i++) {
808                 if (thisProperties.get(i).alias == propertyAlias) {
809                     thisProperties.set(i, symbol); // overwriting previous property
810                     return;
811                 }
812             }
813
814             thisProperties.add(symbol); // new property with this alias
815         }
816         
817         public void addChildClass(string clsname, string parent) 
818         {
819                 if (!this.childClasses.has_key( parent)) {
820                         this.childClasses.set(parent, new Gee.ArrayList<string>());
821                 }
822                 this.childClasses.get(parent).add(clsname);
823                 this.childClassesList.add(clsname);
824         }
825          
826         
827         public void addDocTag(DocTag docTag)
828         {
829             this.comment.tags.add(docTag);
830             if (docTag.title == DocTagTitle.CFG) {
831                 this.addConfig(docTag);
832             }
833              
834         }
835         
836         public void addConfig(DocTag docTag)
837         {
838             if (docTag.memberOf == "") {
839                 // remove prototype data...
840                 //var a = this.alias.split('#')[0];
841                 //docTag.memberOf = a;
842                 docTag.memberOf = this.alias;
843             }
844             if (!this.cfgs.has_key(docTag.name)) {
845                 this.cfgs.set(docTag.name,  docTag);
846             }
847             
848         }
849          
850         public Gee.ArrayList<DocTag> configToArray()
851         {
852             var r = new  Gee.ArrayList<DocTag>();
853             foreach(var ci in this.cfgs.keys) {
854                 // dont show hidden!!
855                 if (this.cfgs.get(ci).desc.contains("@hide")) {
856                     continue;
857                 }
858                 r.add(this.cfgs.get(ci)); 
859                
860             }
861             return r;
862         }
863         
864         
865                 
866                 public string makeFuncSkel() {
867                     if (this.params.size < 1) return "function ()\n{\n\n}";
868                         var ret = "function (";
869                         var f = false;
870                         foreach(var p in this.params) {
871                                 if (p.name.contains(".")) continue;
872                                 ret += f ? ", " : "";
873                                 f = true;
874                                 ret +=  p.name == "this" ? "_self" : p.name;
875                         }
876                         return ret + ")\n{\n\n}";
877                 }
878                 public string makeMethodSkel() {
879                     if (this.params.size < 1) return "()\n{\n\n}";
880                         var ret = "(";
881                         var f = false;
882                         foreach(var p in this.params) {
883                                 GLib.debug("got param: %s", p.asString());
884                                 if (p.name.contains(".")) continue;
885                                 ret += f ? ", " : "";
886                                 f = true;
887                                 switch(p.name) {
888                                         case "this" : ret += "this"; break;
889                                         case "function" : ret += "function() {\n\n}"; break;                                    
890                                         default : ret += p.name; break;
891                                 }
892                         }
893                         return ret + ")";
894                 }
895         
896                 public Json.Array stringArrayToJson( Gee.ArrayList<string> ar) 
897                 {
898                         var ret = new Json.Array();
899                         foreach(var a in ar) {
900                                 ret.add_string_element(a);
901                         }
902                         return ret;
903                 
904                 }
905                 public Json.Array symbolArrayToJson( Gee.ArrayList<Symbol> ar) 
906                 {
907                         var ret = new Json.Array();
908                         foreach(var a in ar) {
909                                 ret.add_object_element(a.toJson());
910                         }
911                         return ret;
912                 
913                 }
914                 public Json.Array docTagsArrayToJson( Gee.ArrayList<DocTag> ar) 
915                 {
916                         var ret = new Json.Array();
917                         foreach(var a in ar) {
918                                 ret.add_object_element(a.toJson());
919                         }
920                         return ret;
921                 
922                 } 
923                 
924                 public Json.Object assocStringToJson( Gee.HashMap<string,Gee.ArrayList<string>> ar) 
925                 {
926                         var ret = new Json.Object();
927                         foreach(var a in ar.keys) {
928                                 ret.set_array_member(a, this.stringArrayToJson(ar.get(a)));
929                         }
930                         return ret;
931                 
932                 } 
933                 
934                 public Json.Object assocDocTagToJson( Gee.HashMap<string,DocTag> ar) 
935                 {
936                         var ret = new Json.Object();
937                         foreach(var a in ar.keys) {
938                                 ret.set_object_member(a, ar.get(a).toJson());
939                         }
940                         return ret;
941                 
942                 } 
943                 
944                 /**
945                 * direct Json Dump
946                 */
947                 public Json.Object toJson()
948                 {
949                         var ret = new Json.Object();
950                         ret.set_string_member("name", this.name);
951                         ret.set_object_member("comment", this.comment.toJson()); //contains doctags?
952                         ret.set_boolean_member("isEvent", this.isEvent);
953                         ret.set_boolean_member("isConstant", this.isConstant);
954                         ret.set_boolean_member("isIgnored", this.isIgnored);
955                         ret.set_boolean_member("isInner", this.isInner);
956                         ret.set_boolean_member("isNamespace", this.isNamespace);
957                         ret.set_boolean_member("isPrivate", this.isPrivate);
958                         ret.set_boolean_member("isStatic", this.isStatic);
959                         ret.set_boolean_member("isAbstract", this.isAbstract);
960                         ret.set_boolean_member("isBuilderTop", this.isBuilderTop);      
961                         ret.set_string_member("memberOf", this.memberOf);
962                         ret.set_array_member("tree_children", this.stringArrayToJson(this.tree_children));
963                         ret.set_array_member("tree_parent", this.stringArrayToJson(this.tree_parent));
964                         
965                         
966                         ret.set_array_member("params", this.docTagsArrayToJson(this.params));
967
968                         ret.set_array_member("augments", this.stringArrayToJson(this.augments));
969                         ret.set_array_member("exceptions", this.docTagsArrayToJson(this.exceptions));
970                         ret.set_array_member("methods", this.symbolArrayToJson(this.methods));
971                         ret.set_array_member("properties", this.symbolArrayToJson(this.properties));
972                         ret.set_array_member("requires", this.stringArrayToJson(this.requires));
973                         ret.set_array_member("returns", this.docTagsArrayToJson(this.returns));
974                         ret.set_array_member("see", this.stringArrayToJson(this.see));
975                         ret.set_object_member("childClasses", this.assocStringToJson(this.childClasses));
976                         ret.set_array_member("inheritsFrom", this.stringArrayToJson(this.inheritsFrom));
977                         ret.set_object_member("cfgs", this.assocDocTagToJson(this.cfgs));
978
979                       //$args : [], // original arguments used when constructing.
980  
981                         ret.set_string_member("alias", this.alias);
982         
983                         ret.set_string_member("author", this.author);
984                         ret.set_string_member("classDesc" , this.classDesc);
985                         ret.set_string_member("deprecated", this.deprecated);
986                         ret.set_string_member("desc", this.desc);
987                         //events : false,
988                         ret.set_string_member("example", this.example);
989                         
990                         ret.set_string_member("isa", this.isa);
991
992
993
994                         return ret;
995                 }
996                 /**
997                 * This is the more detail Class output for documentation body text
998                 */
999                 
1000                 
1001                 public Json.Object toClassDocJSON ()
1002                 {
1003                         var ret = new Json.Object();
1004                         ret.set_string_member("name", this.alias);
1005                         
1006                         
1007                         var ag = new Json.Array();
1008                         ret.set_array_member("augments", this.stringArrayToJson(this.augments));
1009                         ret.set_object_member("childClasses", this.assocStringToJson(this.childClasses));
1010                         
1011                         ret.set_array_member("tree_children", this.stringArrayToJson(this.tree_children));
1012                         ret.set_array_member("tree_parent", this.stringArrayToJson(this.tree_parent));
1013
1014                         
1015                         ret.set_string_member("name", this.alias);  
1016                         ret.set_string_member("desc", this.desc);
1017                         ret.set_boolean_member("isSingleton", this.comment.getTag(DocTagTitle.SINGLETON).size > 0);
1018                         ret.set_boolean_member("isStatic", this.isStatic ); // ??? -> this.isa != "CONSTRUCTOR" ? true : this.isStatic);
1019                         ret.set_boolean_member("isBuiltin", this.isBuiltin());
1020                         ret.set_boolean_member("isAbstract", this.isAbstract);
1021                         ret.set_boolean_member("isBuilderTop", this.isBuilderTop);                      
1022
1023                         // needded so that the class can fake a ctor..
1024                         ret.set_string_member("memberOf", this.name);
1025                         ret.set_string_member("example", this.comment.getTagAsString(DocTagTitle.EXAMPLE));
1026                         ret.set_string_member("deprecated", // as depricated is used as a flag...
1027                                 this.comment.getTag(DocTagTitle.DEPRECATED).size > 0 ? 
1028                                 "This has been deprecated: "+  this.comment.getTagAsString(DocTagTitle.DEPRECATED) : 
1029                         "");
1030                         ret.set_string_member("since", this.comment.getTagAsString(DocTagTitle.SINCE));
1031                         ret.set_string_member("see", this.comment.getTagAsString(DocTagTitle.SEE));
1032                         // ?? ctor? is that listed with the outer class?
1033                         
1034                         
1035                         
1036                         // this must be for the CTOR?
1037                         ret.set_array_member("params", this.paramsToJson());
1038                         ret.set_array_member("returns", new Json.Array()); // this is a placeholder - classes dont have returns..
1039                 ret.set_string_member("throws", this.comment.getTagAsString(DocTagTitle.THROWS));
1040                         ret.set_string_member("requires", this.comment.getTagAsString(DocTagTitle.REQUIRES));
1041                         
1042                         
1043                         var props = new Json.Array(); 
1044                         ret.set_array_member("config", props);
1045                         var cfgProperties = this.configToArray();
1046                         for(var i =0; i < cfgProperties.size;i++) {
1047                                 props.add_object_element(cfgProperties.get(i).toPropertyJSON(this));
1048                 }
1049                         // methods
1050  
1051                         var methods = new Json.Array();
1052                         ret.set_array_member("methods", methods);                    
1053                         foreach(var m in this.methods) {
1054                                 if (m.isEvent || m.isIgnored) {
1055                                         continue;
1056                                 }
1057                                 methods.add_object_element(m.toMethodJSON(this));
1058                         }
1059                         
1060                         // events
1061                         var events = new Json.Array();
1062                         ret.set_array_member("events", events);              
1063                     foreach(var m in this.methods) {
1064                         if (!m.isEvent || m.isIgnored) {
1065                                 continue;
1066                         }
1067                         events.add_object_element(m.toEventJSON(this));
1068                 }
1069                 return ret;
1070                 }
1071                 
1072                 // ?? can this be replaced with ???
1073                 public Json.Array paramsToJson()
1074                 {
1075                         var ret = new Json.Array();
1076                         foreach(var p in this.params) {
1077                                 //GLib.debug("got param: %s", p.asString());
1078                                 if (p.name.contains(".")) continue;// ?? why?                           
1079                                 var add = new Json.Object();
1080                                 add.set_string_member("name",p.name);                           
1081                                 add.set_string_member("type",p.type);
1082                                 add.set_string_member("desc",p.desc);
1083                                 add.set_boolean_member("isOptional",p.isOptional);
1084                                 ret.add_object_element(add) ;
1085                         }
1086                          
1087                         return ret;
1088                 
1089                 }
1090                 
1091                 // ?? can this be replaced with ???
1092         public Json.Array returnsToJson()
1093                 {
1094                         var ret = new Json.Array();
1095                         foreach(var p in this.returns) {
1096                                 //GLib.debug("got param: %s", p.asString());
1097                                 if (p.name.contains(".")) continue;// ?? why?                           
1098                                 var add = new Json.Object();
1099                                 add.set_string_member("name",p.name);                           
1100                                 add.set_string_member("type",p.type);
1101                                 add.set_string_member("desc",p.desc);
1102                  
1103                                 ret.add_object_element(add) ;
1104                         }
1105                          
1106                         return ret;
1107                 
1108                 }
1109                 
1110                  /**
1111                  * JSON files are lookup files for the documentation
1112                  * - can be used by IDE's or AJAX based doc tools
1113                  *  This is a simplified version..
1114                  * 
1115                  */
1116                 public Json.Object toClassJSON ()
1117                 {
1118                     // what we need to output to be usefull...
1119                     // a) props..
1120                     var cfgProperties = new Gee.ArrayList<DocTag>();
1121                     if (this.comment.getTag(DocTagTitle.SINGLETON).size < 1) {
1122                          cfgProperties = this.configToArray();
1123                          cfgProperties.sort((a,b) =>{
1124                                 return a.name.collate(b.name);
1125                         }); 
1126                     } 
1127                     var props = new Json.Array(); 
1128                     for(var i =0; i < cfgProperties.size;i++) {
1129                         props.add_object_element(  cfgProperties.get(i).toPropertyJSON(this) );
1130                     }
1131                     
1132                     ///// --- events
1133                     var ownEvents = new Gee.ArrayList<Symbol>();
1134                     for(var i =0; i < this.methods.size;i++) {
1135                                 var e = this.methods.get(i);
1136                                 if (e.isEvent && !e.isIgnored) {
1137                                         ownEvents.add(e);
1138                                 }
1139                         }; 
1140                         ownEvents.sort((a,b) => {
1141                                 return a.name.collate(b.name);
1142                         });
1143                     
1144                     var events = new Json.Array();
1145                      
1146                     for(var i =0; i < ownEvents.size;i++) {
1147                         events.add_object_element(ownEvents.get(i).toEventJSON(this));
1148                     } 
1149                      
1150                     // methods
1151                     var ownMethods = new Gee.ArrayList<Symbol>();
1152                     for(var i =0; i < this.methods.size;i++) {
1153                                 var e = this.methods.get(i);
1154                                 if (!e.isEvent && !e.isIgnored) {
1155                                         ownMethods.add(e);
1156                                 }
1157                         };
1158                         ownMethods.sort((a,b) => {
1159                                 return a.name.collate(b.name);
1160                         });
1161                     
1162                         var methods = new Json.Array();
1163                     for(var i =0; i < ownMethods.size;i++) {
1164                         methods.add_object_element(ownMethods.get(i).toMethodJSON(this));
1165                     }
1166                      
1167                     //println(props.toSource());
1168                     // we need to output:
1169                     //classname => {
1170                     //    propname => 
1171                     //        type=>
1172                     //        desc=>
1173                     //    }
1174                         var ret =  new Json.Object();
1175                         ret.set_array_member("props", props);
1176                         ret.set_array_member("events", events);
1177                         ret.set_array_member("methods", methods);
1178                         ret.set_boolean_member("isAbstract", this.isAbstract);
1179                         ret.set_boolean_member("isBuilderTop", this.isBuilderTop);
1180                         ret.set_object_member("childClasses", this.assocStringToJson(this.childClasses));                       
1181                         ret.set_array_member("tree_children", this.stringArrayToJson(this.tree_children));
1182                         ret.set_array_member("tree_parent", this.stringArrayToJson(this.tree_parent));
1183
1184                         
1185                 
1186                     return ret;
1187                     
1188                     
1189                     // b) methods
1190                     // c) events
1191                     
1192                     
1193                 }
1194                  
1195                 
1196                 public Json.Object toEventJSON (Symbol parent)
1197                 {
1198                         var add = new Json.Object();
1199                         add.set_string_member("name",this.name.substring(1,-1)); // remove'*' on events..
1200                         add.set_string_member("type","function");
1201                         add.set_string_member("desc",this.desc);
1202                         add.set_string_member("sig", this.makeFuncSkel());
1203                         add.set_string_member("memberOf", this.memberOf == parent.alias ? "" : this.memberOf);  
1204                         add.set_string_member("example", this.comment.getTagAsString(DocTagTitle.EXAMPLE));
1205                         add.set_string_member("deprecated", // as depricated is used as a flag...
1206                                         this.comment.getTag(DocTagTitle.DEPRECATED).size > 0 ? 
1207                                         "This has been deprecated: "+  this.comment.getTagAsString(DocTagTitle.DEPRECATED) : 
1208                                         "");
1209                         add.set_string_member("since", this.comment.getTagAsString(DocTagTitle.SEE));
1210                         add.set_string_member("see", this.comment.getTagAsString(DocTagTitle.SEE));
1211                         // not supported or used yet?
1212                         //add.set_string_member("exceptions", m.comment.getTagAsString(DocTagTitle.THROWS));
1213                         //add.set_string_member("requires", m.comment.getTagAsString(DocTagTitle.REQUIRES));
1214                         
1215                         add.set_array_member("params", this.paramsToJson());
1216                         add.set_array_member("returns", this.returnsToJson());
1217                         
1218                         
1219                         
1220                         
1221                         
1222                                         
1223                         return add;
1224                 }
1225                 public Json.Object toMethodJSON (Symbol parent)
1226                 {
1227                         var add = new Json.Object();
1228                         add.set_string_member("name",this.name);
1229                         add.set_string_member("type","function");
1230                         add.set_string_member("desc",this.desc);
1231                         add.set_string_member("sig", this.makeMethodSkel());
1232                         add.set_boolean_member("static", this.isStatic);
1233                         add.set_string_member("memberOf", this.memberOf == parent.alias ? "" : this.memberOf);
1234                         
1235                         // we may as well add extended data here...
1236                         add.set_boolean_member("isStatic", this.isStatic);
1237                         add.set_boolean_member("isConstructor", this.isa == "CONSTRUCTOR");
1238                         add.set_boolean_member("isPrivate", this.isPrivate);
1239
1240                         add.set_string_member("example", this.comment.getTagAsString(DocTagTitle.EXAMPLE));
1241                         add.set_string_member("deprecated", // as depricated is used as a flag...
1242                                         this.comment.getTag(DocTagTitle.DEPRECATED).size > 0 ? 
1243                                         "This has been deprecated: "+ this.comment.getTagAsString(DocTagTitle.DEPRECATED) : 
1244                                         "");
1245                         add.set_string_member("since", this.comment.getTagAsString(DocTagTitle.SINCE));
1246                         add.set_string_member("see", this.comment.getTagAsString(DocTagTitle.SEE));
1247                         // not supported or used yet?
1248                         add.set_string_member("exceptions", this.comment.getTagAsString(DocTagTitle.THROWS));
1249                         add.set_string_member("requires", this.comment.getTagAsString(DocTagTitle.REQUIRES));
1250                         add.set_array_member("params", this.paramsToJson());
1251                         add.set_array_member("returns", this.returnsToJson());
1252                          
1253                         
1254                         return add;
1255                 }
1256
1257          }
1258         //static string[] hide = { "$args" };
1259         //static string srcFile = "";    
1260 }
1261
1262
1263 /*
1264 Symbol.fromDump = function(t)
1265 {
1266     var ns = new Symbol();
1267     for (var i in t) {
1268         if (typeof(ns[i]) == "undefined") {
1269             println("ERR:no default for Symbol:"+ i);
1270         }
1271         ns[i] = t[i];
1272     }
1273     return ns;
1274 }
1275 */