4 @class Represents a symbol in the source code.
11 public class Symbol : Object
16 public static bool regex_init = false;
19 private string private_string_name = "";
20 private string _assigned_name = "";
21 // called by symbolset...
22 public string private_name {
24 this._assigned_name = name;
25 var n = /^_global_[.#-]/.replace(value, value.length, 0, "");
26 n = /\.prototype\.?/.replace(n,n.length, 0, "#");
28 if (!n.has_suffix("#")) {
31 n = n.substring(0, n.length-1);
34 this.private_string_name = n;
40 get { return this.private_string_name; }
44 string defaultValue = "";
46 private Gee.ArrayList<DocTag> private_doctag_params = null;
48 private Gee.ArrayList<DocTag> private_params{
50 if (this.private_doctag_params == null) {
51 this.private_doctag_params = new Gee.ArrayList<DocTag>();
53 for (var i = 0; i < value.size; i++) {
55 this.private_doctag_params.add(value.get(i));
57 //this.params = this._params;
61 Gee.ArrayList<string> private_string_params{
63 if (this.private_doctag_params == null) {
64 this.private_doctag_params = new Gee.ArrayList<DocTag>();
66 for (var i = 0; i < value.size; i++) {
68 //var ty = v[i].hasOwnProperty('type') ? v[i].type : '';
69 this.private_doctag_params.add( new DocTag(value.get(i)));
71 //"param"+((ty)?" {"+ty+"}":"")+" "+v.get(i).name);
77 public Gee.ArrayList<DocTag> params {
79 if (this.private_doctag_params == null) {
80 this.private_doctag_params = new Gee.ArrayList<DocTag>();
82 return this.private_doctag_params;
87 public Gee.ArrayList<string> augments ;
90 private Gee.ArrayList<DocTag> exceptions ;
92 //public Gee.ArrayList<DocTag> inherits;
93 public Gee.ArrayList<Symbol> methods;
95 public Gee.ArrayList<Symbol> properties;
96 private Gee.ArrayList<string> requires;
97 public Gee.ArrayList<DocTag> returns;
98 private Gee.ArrayList<string> see ;
100 public Gee.ArrayList<string> childClasses;
101 public Gee.ArrayList<string> inheritsFrom;
102 public Gee.HashMap<string,DocTag>cfgs;
105 public DocComment comment;
107 //$args : [], // original arguments used when constructing.
109 public string alias = "";
112 string classDesc = "";
114 string deprecated = "";
115 public string desc = "";
120 public string isa = "OBJECT"; // OBJECT//FUNCTION
122 public bool isEvent = false;
123 public bool isConstant = false;
124 public bool isIgnored = false;
125 public bool isInner = false;
126 public bool isNamespace = false;
127 public bool isPrivate = false;
128 public bool isStatic = false;
130 public string memberOf = "";
132 public string asString()
134 return "NAME: %s:%s ASNAME: %s : %s%s%s%s".printf(
138 isStatic ? "static": "",
140 isConstant ? "CO": "",
141 isNamespace ? "NS": ""
153 public static string srcFile = "";
157 public void initArrays()
159 // only initialize arrays / objects..
166 this.exceptions = new Gee.ArrayList<DocTag>();
167 //this.inherits = new Gee.ArrayList<DocTag>();
169 this.isa = "OBJECT"; // OBJECT//FUNCTION
170 this.methods = new Gee.ArrayList<Symbol>();
171 //this.private_params = new Gee.ArrayList<DocTag>();
172 this.properties = new Gee.ArrayList<Symbol>();
173 this.requires = new Gee.ArrayList<string>();
174 this.returns = new Gee.ArrayList<DocTag>();
175 this.see = new Gee.ArrayList<string>();
176 this.augments = new Gee.ArrayList<string>();
179 this.cfgs = new Gee.HashMap<string,DocTag>();
181 this.inheritsFrom = new Gee.ArrayList<string>();
183 this.childClasses = new Gee.ArrayList<string>();
185 this.comment = new DocComment();
186 this.comment.isUserComment = false;
191 public Symbol.new_builtin(string name)
195 this.srcFile = JSDOC.DocParser.currentSourceFile;
196 this.private_name = name ;
197 this.alias = this.name;
198 this.isa = "CONSTRUCTOR";
199 this.comment = new DocComment("");
200 this.comment.isUserComment = false;
201 this.isNamespace = false;
203 this.isPrivate = false;
213 public Symbol.new_populate_with_args(
215 Gee.ArrayList<string> params, // fixme???
221 // this.$args = arguments;
222 //println("Symbol created: " + isa + ":" + name);
223 this.private_name = name;
224 this.alias = this.name;
225 this.private_string_params = params;
226 this.isa = (isa == "VIRTUAL")? "OBJECT":isa;
227 this.comment = comment;
229 this.srcFile = DocParser.currentSourceFile;
233 if (this.is("FILE") && this.alias.length < 1) { // this will never hapen???
234 this.alias = this.srcFile;
237 this.tagsFromComment();
241 void tagsFromComment() {
243 var authors = this.comment.getTag(DocTagTitle.AUTHOR);
244 if (authors.size > 0) {
245 // turns author into a string....
247 foreach(var a in authors) {
248 this.author += (this.author == "") ? "": ", ";
249 this.author += a.desc;
254 assert("testing Symbol");
256 requires("../lib/JSDOC/DocComment.js");
257 requires("../frame/String.js");
258 requires("../lib/JSDOC/DocTag.js");
260 var sym = new Symbol("foo", [], "OBJECT", new DocComment("/**@author Joe Smith*"+"/"));
261 assertEqual(sym.author, "Joe Smith", "@author tag, author is found.");
264 var mth = this.comment.getTag(DocTagTitle.METHOD);
266 this.isa = "FUNCTION";
269 var descs = this.comment.getTag(DocTagTitle.DESC);
272 foreach(var d in descs) {
273 this.desc = this.desc == "" ? "": "\n";
280 var sym = new Symbol("foo", [], "OBJECT", new DocComment("/**@desc This is a description.*"+"/"));
281 assertEqual(sym.desc, "This is a description.", "@desc tag, description is found.");
285 if (this.is("FILE")) {
286 if (this.alias.length < 1) this.alias = this.srcFile;
288 var overviews = this.comment.getTag(DocTagTitle.OVERVIEW);
289 if (overviews.size > 0) {
290 foreach(var d in overviews) {
291 this.desc = this.desc == "" ? "": "\n";
298 var sym = new Symbol("foo", [], "FILE", new DocComment("/**@overview This is an overview.*"+"/"));
299 assertEqual(sym.desc, "\nThis is an overview.", "@overview tag, description is found.");
303 var sinces = this.comment.getTag(DocTagTitle.SINCE);
304 if (sinces.size > 0) {
306 foreach(var d in sinces) {
307 this.since = this.since == "" ? "": "\n";
308 this.since += d.desc;
313 var sym = new Symbol("foo", [], "FILE", new DocComment("/**@since 1.01*"+"/"));
314 assertEqual(sym.since, "1.01", "@since tag, description is found.");
318 if (this.comment.getTag(DocTagTitle.CONSTANT).size > 0) {
319 this.isConstant = true;
324 var sym = new Symbol("foo", [], "FILE", new DocComment("/**@constant*"+"/"));
325 assertEqual(sym.isConstant, true, "@constant tag, isConstant set.");
329 var versions = this.comment.getTag(DocTagTitle.VERSION);
330 if (versions.size > 0 ) {
332 foreach(var d in versions) {
333 this.version = this.version == "" ? "": "\n";
334 this.version += d.desc;
339 var sym = new Symbol("foo", [], "FILE", new DocComment("/**@version 2.0x*"+"/"));
340 assertEqual(sym.version, "2.0x", "@version tag, version is found.");
344 var deprecateds = this.comment.getTag(DocTagTitle.DEPRECATED);
345 if (deprecateds.size > 0) {
346 this.deprecated = "";
347 foreach(var d in deprecateds) {
348 this.deprecated = this.deprecated == "" ? "": "\n";
349 this.deprecated += d.desc;
354 var sym = new Symbol("foo", [], "FILE", new DocComment("/**@deprecated Use other method.*"+"/"));
355 assertEqual(sym.deprecated, "Use other method.", "@deprecated tag, desc is found.");
359 var examples = this.comment.getTag(DocTagTitle.EXAMPLE);
360 if (examples.size > 0) {
361 this.example = examples.get(0).desc;
365 var sym = new Symbol("foo", [], "FILE", new DocComment("/**@example This\n is an example.*"+"/"));
366 assertEqual(sym.example, "This\n is an example.", "@deprecated tag, desc is found.");
370 var sees = this.comment.getTag(DocTagTitle.SEE);
373 foreach(var s in sees) {
374 this.see.add(s.desc);
379 var sym = new Symbol("foo", [], "FILE", new DocComment("/**@see The other thing.*"+"/"));
380 assertEqual(sym.see, "The other thing.", "@see tag, desc is found.");
384 var classes = this.comment.getTag(DocTagTitle.CLASS);
385 if (classes.size > 0) {
386 //print(JSON.stringify(this,null,4));
387 this.isa = "CONSTRUCTOR";
388 this.classDesc = classes[0].desc; // desc can't apply to the constructor as there is none.
389 //if (!this.classDesc.leg) {
390 // this.classDesc = this.desc;
397 var sym = new Symbol("foo", [], "OBJECT", new DocComment("/**@class This describes the class.*"+"/"));
398 assertEqual(sym.isa, "CONSTRUCTOR", "@class tag, makes symbol a constructor.");
399 assertEqual(sym.classDesc, "This describes the class.", "@class tag, class description is found.");
403 var namespaces = this.comment.getTag(DocTagTitle.NAMESPACE);
404 if (namespaces.size > 0) {
405 this.classDesc = namespaces[0].desc+"\n"+this.desc; // desc can't apply to the constructor as there is none.
406 this.isNamespace = true;
410 var sym = new Symbol("foo", [], "OBJECT", new DocComment("/**@namespace This describes the namespace.*"+"/"));
411 assertEqual(sym.classDesc, "This describes the namespace.\n", "@namespace tag, class description is found.");
415 var params = this.comment.getTag(DocTagTitle.PARAM);
416 if (params.size > 0) {
417 // user-defined params overwrite those with same name defined by the parser
418 var thisParams = params;
420 if (thisParams.size == 0) { // none exist yet, so just bung all these user-defined params straight in
421 this.private_params = params;
423 else { // need to overlay these user-defined params on to existing parser-defined params
424 for (var i = 0, l = params.size; i < l; i++) {
425 if (thisParams.size <= i) {
426 var np = thisParams.get(i);
428 if (np.type.length > 0) np.type = params[i].type;
429 np.name = params[i].name;
430 np.desc = params[i].desc;
431 np.isOptional = params[i].isOptional;
432 np.defaultValue = params[i].defaultValue;
433 //thisParams.set(i, np); ///?? needed OO ?
435 else thisParams.set(i, params[i]);
437 this.private_params = thisParams;
444 if (this.comment.getTag(DocTagTitle.CONSTRUCTOR).size > 0) {
445 this.isa = "CONSTRUCTOR";
451 if (this.comment.getTag(DocTagTitle.STATIC).size > 0) {
452 this.isStatic = true;
453 if (this.isa == "CONSTRUCTOR") {
454 this.isNamespace = true;
459 if (this.comment.getTag(DocTagTitle.SINGLETON).size > 0) {
460 this.isStatic = true;
461 //print('------------- got singleton ---------------' + this.isa);
462 //if (this.isa == "CONSTRUCTOR") {
463 // this.isNamespace = true;
470 if (this.comment.getTag(DocTagTitle.INNER).size > 0) {
472 this.isStatic = false;
477 if (this.comment.getTag(DocTagTitle.FIELD).size > 0) {
484 if (this.comment.getTag(DocTagTitle.FUNCTION).size > 0) {
485 this.isa = "FUNCTION";
489 if (this.comment.getTag(DocTagTitle.PARAM).size > 0 && this.isa == "OBJECT" ) {
490 // change a property to a function..
491 this.isa = "FUNCTION";
498 var events = this.comment.getTag(DocTagTitle.EVENT);
499 if (events.size > 0) {
500 this.isa = "FUNCTION";
507 var names = this.comment.getTag(DocTagTitle.NAME);
508 if (names.size > 0) {
509 this.private_name = names.get(0).desc.strip();
517 var properties = this.comment.getTag(DocTagTitle.PROPERTY);
518 if (properties.size > 0) {
519 //var thisProperties = this.properties;
520 for (var i = 0; i < properties.size; i++) {
523 // if the doc tag just says @property ... but no name etc..
524 // then name will not be filled in..
525 if (properties[i].name.length < 1 ) {
529 var property = new Symbol.new_populate_with_args(
530 this.alias+"#"+properties[i].name,
531 new Gee.ArrayList<string>(),
536 "\n@name "+ properties[i].name
537 +"\n@memberOf "+this.alias+"#*/"
539 // TODO: shouldn't the following happen in the addProperty method of Symbol?
540 property.private_name = properties[i].name;
541 property.memberOf = this.alias;
542 if (properties[i].type.length > 0) property.type = properties[i].type;
543 if (properties[i].defaultValue.length > 0) property.defaultValue = properties[i].defaultValue;
544 this.addProperty(property);
545 JSDOC.DocParser.addSymbol(property);
550 var conf = this.comment.getTag(DocTagTitle.CFG);
552 for (var i = 0; i < conf.size; i++) {
553 this.addConfig(conf.get(i));
560 var returns = this.comment.getTag(DocTagTitle.RETURN);
561 if (returns.size > 0) { // there can be many return tags in a single doclet
562 this.returns = returns;
565 foreach(var r in returns) {
566 this.type += this.type == "" ? "": ", ";
574 this.exceptions = this.comment.getTag(DocTagTitle.THROWS);
578 var requires = this.comment.getTag(DocTagTitle.REQUIRES);
579 if (requires.size > 0) {
580 this.requires = new Gee.ArrayList<string>();
581 foreach(var r in requires) {
582 this.requires.add(r.desc);
588 var types = this.comment.getTag(DocTagTitle.TYPE);
589 if (types.size > 0) {
590 this.type = types.get(0).desc; //multiple type tags are ignored
596 if (this.comment.getTag(DocTagTitle.PRIVATE).size > 0 || this.isInner) {
597 this.isPrivate = true;
601 if (this.comment.getTag(DocTagTitle.IGNORE).size > 0) {
602 this.isIgnored = true;
609 // @inherits ... as ... -- not used!!!
611 var inherits = this.comment.getTag("inherits");
612 if (inherits.length) {
613 for (var i = 0; i < inherits.length; i++) {
614 if (/^\s*([a-z$0-9_.#-]+)(?:\s+as\s+([a-z$0-9_.#]+))?/i.test(inherits[i].desc)) {
615 var inAlias = RegExp.$1;
616 var inAs = RegExp.$2 || inAlias;
618 if (inAlias) inAlias = inAlias.replace(/\.prototype\.?/g, "#");
621 inAs = inAs.replace(/\.prototype\.?/g, "#");
622 inAs = inAs.replace(/^this\.?/, "#");
625 if (inAs.indexOf(inAlias) != 0) { //not a full namepath
627 if (this.alias.charAt(this.alias.length-1) == "#" || inAs.charAt(0) == "#") {
630 inAs = this.alias + joiner + inAs;
633 this.inherits.push({alias: inAlias, as: inAs});
642 foreach(var dt in this.comment.getTag(DocTagTitle.ARGUMENTS)) {
643 this.augments.add(dt.desc);
646 foreach(var dt in this.comment.getTag(DocTagTitle.EXTENDS)) {
647 this.augments.add(dt.desc);
653 var defaults = this.comment.getTag(DocTagTitle.DEFAULT);
654 if (defaults.size > 0) {
655 if (this.is("OBJECT")) {
656 this.defaultValue = defaults.get(0).desc;
665 var memberOfs = this.comment.getTag(DocTagTitle.MEMBEROF);
666 if (memberOfs.size > 0) {
667 this.memberOf = memberOfs[0].desc;
668 var pr_reg = /\.prototype\.?/;
670 this.memberOf = pr_reg.replace(this.memberOf, this.memberOf.length, 0, "#");
671 var dname = this.name.split(".");
672 var name = dname[dname.length-1];
674 var hname = name.split("#");
675 name = hname[hname.length-1];
676 this.private_name = this.memberOf + "." + name; //?? "." ???
677 this.alias = this.name;
685 if (this.comment.getTag(DocTagTitle.PUBLIC).size > 0) {
686 this.isPrivate = false;
694 public bool is (string what) {
695 return this.isa == what;
697 public bool isaClass()
700 return (this.is("CONSTRUCTOR") || this.isNamespace ); //|| this.isClass);
704 public bool isBuiltin() {
705 return SymbolSet.isBuiltin(this.alias);
708 void setType(string comment,bool overwrite) {
709 if (!overwrite && this.type.length > 0) {
712 var typeComment = DocComment.unwrapComment(comment);
713 this.type = typeComment;
716 public void inherit (Symbol symbol) {
717 if (!this.hasMember(symbol.name) && !symbol.isInner) {
718 if (symbol.is("FUNCTION"))
719 this.methods.add(symbol);
720 else if (symbol.is("OBJECT"))
721 this.properties.add(symbol);
725 bool hasMember (string name) {
726 return (this.hasMethod(name) || this.hasProperty(name));
729 public void addMember (Symbol symbol) {
730 //println("ADDMEMBER: " + this.name + " ++ " + symbol.name);
732 if (symbol.comment.getTag(DocTagTitle.CFG).size == 1) {
733 symbol.comment.getTag(DocTagTitle.CFG).get(0).memberOf = this.alias;
734 this.addConfig(symbol.comment.getTag(DocTagTitle.CFG).get(0));
738 if (symbol.is("FUNCTION")) { this.addMethod(symbol); }
739 else if (symbol.is("OBJECT")) { this.addProperty(symbol); }
742 bool hasMethod (string name) {
743 var thisMethods = this.methods;
744 for (var i = 0, l = thisMethods.size; i < l; i++) {
745 if (thisMethods.get(i).name == name) return true;
746 if (thisMethods.get(i).alias == name) return true;
751 void addMethod (Symbol symbol) {
752 var methodAlias = symbol.alias;
753 var thisMethods = this.methods;
754 for (var i = 0, l = thisMethods.size; i < l; i++) {
755 if (thisMethods.get(i).alias == methodAlias) {
756 thisMethods.set(i, symbol); // overwriting previous method
760 thisMethods.add(symbol); // new method with this alias
763 bool hasProperty(string name) {
764 var thisProperties = this.properties;
765 for (var i = 0, l = thisProperties.size; i < l; i++) {
766 if (thisProperties.get(i).name == name) return true;
767 if (thisProperties.get(i).alias == name) return true;
772 void addProperty(Symbol symbol) {
773 var propertyAlias = symbol.alias;
774 var thisProperties = this.properties;
775 for (var i = 0, l = thisProperties.size; i < l; i++) {
776 if (thisProperties.get(i).alias == propertyAlias) {
777 thisProperties.set(i, symbol); // overwriting previous property
782 thisProperties.add(symbol); // new property with this alias
785 public void addDocTag(DocTag docTag)
787 this.comment.tags.add(docTag);
788 if (docTag.title == DocTagTitle.CFG) {
789 this.addConfig(docTag);
794 public void addConfig(DocTag docTag)
796 if (docTag.memberOf == "") {
797 // remove prototype data...
798 //var a = this.alias.split('#')[0];
799 //docTag.memberOf = a;
800 docTag.memberOf = this.alias;
802 if (!this.cfgs.has_key(docTag.name)) {
803 this.cfgs.set(docTag.name, docTag);
808 public Gee.ArrayList<DocTag> configToArray()
810 var r = new Gee.ArrayList<DocTag>();
811 foreach(var ci in this.cfgs.keys) {
812 // dont show hidden!!
813 if (this.cfgs.get(ci).desc.contains("@hide")) {
816 r.add(this.cfgs.get(ci));
824 public string makeFuncSkel() {
825 if (this.params.size < 1) return "function ()\n{\n\n}";
826 var ret = "function (";
828 foreach(var p in this.params) {
829 if (p.name.contains(".")) continue;
830 ret += f ? ", " : "";
832 ret += p.name == "this" ? "_self" : p.name;
834 return ret + ")\n{\n\n}";
836 public string makeMethodSkel() {
837 if (this.params.size < 1) return "()\n{\n\n}";
840 foreach(var p in this.params) {
841 GLib.debug("got param: %s", p.asString());
842 if (p.name.contains(".")) continue;
843 ret += f ? ", " : "";
846 case "this" : ret += "this"; break;
847 case "function" : ret += "function() {\n\n}"; break;
848 default : ret += p.name; break;
854 public Json.Array paramsToJson()
856 var ret = new Json.Array();
857 foreach(var p in this.params) {
858 //GLib.debug("got param: %s", p.asString());
859 if (p.name.contains(".")) continue;// ?? why?
860 var add = new Json.Object();
861 add.set_string_member("name",p.name);
862 add.set_string_member("type",p.type);
863 add.set_string_member("desc",p.desc);
864 add.set_boolean_member("isOptional",p.isOptional);
865 ret.add_object_element(add) ;
871 public Json.Array returnsToJson()
873 var ret = new Json.Array();
874 foreach(var p in this.returns) {
875 //GLib.debug("got param: %s", p.asString());
876 if (p.name.contains(".")) continue;// ?? why?
877 var add = new Json.Object();
878 add.set_string_member("name",p.name);
879 add.set_string_member("type",p.type);
880 add.set_string_member("desc",p.desc);
882 ret.add_object_element(add) ;
892 //static string[] hide = { "$args" };
893 //static string srcFile = "";
899 Symbol.fromDump = function(t)
901 var ns = new Symbol();
903 if (typeof(ns[i]) == "undefined") {
904 println("ERR:no default for Symbol:"+ i);