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 = "";
45 private Gee.ArrayList<DocTag> private_doctag_params = null;
47 private Gee.ArrayList<DocTag> private_params{
49 if (this.private_doctag_params == null) {
50 this.private_doctag_params = new Gee.ArrayList<DocTag>();
52 for (var i = 0; i < value.size; i++) {
54 this.private_doctag_params.add(value.get(i));
56 //this.params = this._params;
60 Gee.ArrayList<string> private_string_params{
62 if (this.private_doctag_params == null) {
63 this.private_doctag_params = new Gee.ArrayList<DocTag>();
65 for (var i = 0; i < value.size; i++) {
67 //var ty = v[i].hasOwnProperty('type') ? v[i].type : '';
68 this.private_doctag_params.add( new DocTag(value.get(i)));
70 //"param"+((ty)?" {"+ty+"}":"")+" "+v.get(i).name);
76 public Gee.ArrayList<DocTag> params {
78 if (this.private_doctag_params == null) {
79 this.private_doctag_params = new Gee.ArrayList<DocTag>();
81 return this.private_doctag_params;
86 public Gee.ArrayList<string> augments ;
89 private Gee.ArrayList<DocTag> exceptions ;
91 //public Gee.ArrayList<DocTag> inherits;
92 public Gee.ArrayList<Symbol> methods;
94 public Gee.ArrayList<Symbol> properties;
95 private Gee.ArrayList<string> requires;
96 public Gee.ArrayList<DocTag> returns;
97 private Gee.ArrayList<string> see ;
99 public Gee.ArrayList<string> childClasses;
100 public Gee.ArrayList<string> inheritsFrom;
101 public Gee.HashMap<string,DocTag>cfgs;
104 public DocComment comment;
106 //$args : [], // original arguments used when constructing.
108 public string alias = "";
111 string classDesc = "";
113 string deprecated = "";
114 public string desc = "";
119 public string isa = "OBJECT"; // OBJECT//FUNCTION
121 public bool isEvent = false;
122 public bool isConstant = false;
123 public bool isIgnored = false;
124 public bool isInner = false;
125 public bool isNamespace = false;
126 public bool isPrivate = false;
127 public bool isStatic = false;
129 public string memberOf = "";
131 public string asString()
133 return "NAME: %s:%s ASNAME: %s : %s%s%s%s".printf(
137 isStatic ? "static": "",
139 isConstant ? "CO": "",
140 isNamespace ? "NS": ""
152 public static string srcFile = "";
156 public void initArrays()
158 // only initialize arrays / objects..
165 this.exceptions = new Gee.ArrayList<DocTag>();
166 //this.inherits = new Gee.ArrayList<DocTag>();
168 this.isa = "OBJECT"; // OBJECT//FUNCTION
169 this.methods = new Gee.ArrayList<Symbol>();
170 //this.private_params = new Gee.ArrayList<DocTag>();
171 this.properties = new Gee.ArrayList<Symbol>();
172 this.requires = new Gee.ArrayList<string>();
173 this.returns = new Gee.ArrayList<DocTag>();
174 this.see = new Gee.ArrayList<string>();
175 this.augments = new Gee.ArrayList<string>();
178 this.cfgs = new Gee.HashMap<string,DocTag>();
180 this.inheritsFrom = new Gee.ArrayList<string>();
182 this.childClasses = new Gee.ArrayList<string>();
184 this.comment = new DocComment();
185 this.comment.isUserComment = false;
190 public Symbol.new_builtin(string name)
194 this.srcFile = JSDOC.DocParser.currentSourceFile;
195 this.private_name = name ;
196 this.alias = this.name;
197 this.isa = "CONSTRUCTOR";
198 this.comment = new DocComment("");
199 this.comment.isUserComment = false;
200 this.isNamespace = false;
202 this.isPrivate = false;
212 public Symbol.new_populate_with_args(
214 Gee.ArrayList<string> params, // fixme???
220 // this.$args = arguments;
221 //println("Symbol created: " + isa + ":" + name);
222 this.private_name = name;
223 this.alias = this.name;
224 this.private_string_params = params;
225 this.isa = (isa == "VIRTUAL")? "OBJECT":isa;
226 this.comment = comment;
228 this.srcFile = DocParser.currentSourceFile;
232 if (this.is("FILE") && this.alias.length < 1) { // this will never hapen???
233 this.alias = this.srcFile;
236 this.tagsFromComment();
240 void tagsFromComment() {
242 var authors = this.comment.getTag(DocTagTitle.AUTHOR);
243 if (authors.size > 0) {
244 // turns author into a string....
246 foreach(var a in authors) {
247 this.author += (this.author == "") ? "": ", ";
248 this.author += a.desc;
253 assert("testing Symbol");
255 requires("../lib/JSDOC/DocComment.js");
256 requires("../frame/String.js");
257 requires("../lib/JSDOC/DocTag.js");
259 var sym = new Symbol("foo", [], "OBJECT", new DocComment("/**@author Joe Smith*"+"/"));
260 assertEqual(sym.author, "Joe Smith", "@author tag, author is found.");
263 var mth = this.comment.getTag(DocTagTitle.METHOD);
265 this.isa = "FUNCTION";
268 var descs = this.comment.getTag(DocTagTitle.DESC);
271 foreach(var d in descs) {
272 this.desc = this.desc == "" ? "": "\n";
279 var sym = new Symbol("foo", [], "OBJECT", new DocComment("/**@desc This is a description.*"+"/"));
280 assertEqual(sym.desc, "This is a description.", "@desc tag, description is found.");
284 if (this.is("FILE")) {
285 if (this.alias.length < 1) this.alias = this.srcFile;
287 var overviews = this.comment.getTag(DocTagTitle.OVERVIEW);
288 if (overviews.size > 0) {
289 foreach(var d in overviews) {
290 this.desc = this.desc == "" ? "": "\n";
297 var sym = new Symbol("foo", [], "FILE", new DocComment("/**@overview This is an overview.*"+"/"));
298 assertEqual(sym.desc, "\nThis is an overview.", "@overview tag, description is found.");
302 var sinces = this.comment.getTag(DocTagTitle.SINCE);
303 if (sinces.size > 0) {
305 foreach(var d in sinces) {
306 this.since = this.since == "" ? "": "\n";
307 this.since += d.desc;
312 var sym = new Symbol("foo", [], "FILE", new DocComment("/**@since 1.01*"+"/"));
313 assertEqual(sym.since, "1.01", "@since tag, description is found.");
317 if (this.comment.getTag(DocTagTitle.CONSTANT).size > 0) {
318 this.isConstant = true;
323 var sym = new Symbol("foo", [], "FILE", new DocComment("/**@constant*"+"/"));
324 assertEqual(sym.isConstant, true, "@constant tag, isConstant set.");
328 var versions = this.comment.getTag(DocTagTitle.VERSION);
329 if (versions.size > 0 ) {
331 foreach(var d in versions) {
332 this.version = this.version == "" ? "": "\n";
333 this.version += d.desc;
338 var sym = new Symbol("foo", [], "FILE", new DocComment("/**@version 2.0x*"+"/"));
339 assertEqual(sym.version, "2.0x", "@version tag, version is found.");
343 var deprecateds = this.comment.getTag(DocTagTitle.DEPRECATED);
344 if (deprecateds.size > 0) {
345 this.deprecated = "";
346 foreach(var d in deprecateds) {
347 this.deprecated = this.deprecated == "" ? "": "\n";
348 this.deprecated += d.desc;
353 var sym = new Symbol("foo", [], "FILE", new DocComment("/**@deprecated Use other method.*"+"/"));
354 assertEqual(sym.deprecated, "Use other method.", "@deprecated tag, desc is found.");
358 var examples = this.comment.getTag(DocTagTitle.EXAMPLE);
359 if (examples.size > 0) {
360 this.example = examples.get(0).desc;
364 var sym = new Symbol("foo", [], "FILE", new DocComment("/**@example This\n is an example.*"+"/"));
365 assertEqual(sym.example, "This\n is an example.", "@deprecated tag, desc is found.");
369 var sees = this.comment.getTag(DocTagTitle.SEE);
372 foreach(var s in sees) {
373 this.see.add(s.desc);
378 var sym = new Symbol("foo", [], "FILE", new DocComment("/**@see The other thing.*"+"/"));
379 assertEqual(sym.see, "The other thing.", "@see tag, desc is found.");
383 var classes = this.comment.getTag(DocTagTitle.CLASS);
384 if (classes.size > 0) {
385 //print(JSON.stringify(this,null,4));
386 this.isa = "CONSTRUCTOR";
387 this.classDesc = classes[0].desc; // desc can't apply to the constructor as there is none.
388 //if (!this.classDesc.leg) {
389 // this.classDesc = this.desc;
396 var sym = new Symbol("foo", [], "OBJECT", new DocComment("/**@class This describes the class.*"+"/"));
397 assertEqual(sym.isa, "CONSTRUCTOR", "@class tag, makes symbol a constructor.");
398 assertEqual(sym.classDesc, "This describes the class.", "@class tag, class description is found.");
402 var namespaces = this.comment.getTag(DocTagTitle.NAMESPACE);
403 if (namespaces.size > 0) {
404 this.classDesc = namespaces[0].desc+"\n"+this.desc; // desc can't apply to the constructor as there is none.
405 this.isNamespace = true;
409 var sym = new Symbol("foo", [], "OBJECT", new DocComment("/**@namespace This describes the namespace.*"+"/"));
410 assertEqual(sym.classDesc, "This describes the namespace.\n", "@namespace tag, class description is found.");
414 var params = this.comment.getTag(DocTagTitle.PARAM);
415 if (params.size > 0) {
416 // user-defined params overwrite those with same name defined by the parser
417 var thisParams = params;
419 if (thisParams.size == 0) { // none exist yet, so just bung all these user-defined params straight in
420 this.private_params = params;
422 else { // need to overlay these user-defined params on to existing parser-defined params
423 for (var i = 0, l = params.size; i < l; i++) {
424 if (thisParams.size <= i) {
425 var np = thisParams.get(i);
427 if (np.type.length > 0) np.type = params[i].type;
428 np.name = params[i].name;
429 np.desc = params[i].desc;
430 np.isOptional = params[i].isOptional;
431 np.defaultValue = params[i].defaultValue;
432 //thisParams.set(i, np); ///?? needed OO ?
434 else thisParams.set(i, params[i]);
436 this.private_params = thisParams;
443 if (this.comment.getTag(DocTagTitle.CONSTRUCTOR).size > 0) {
444 this.isa = "CONSTRUCTOR";
450 if (this.comment.getTag(DocTagTitle.STATIC).size > 0) {
451 this.isStatic = true;
452 if (this.isa == "CONSTRUCTOR") {
453 this.isNamespace = true;
458 if (this.comment.getTag(DocTagTitle.SINGLETON).size > 0) {
459 this.isStatic = true;
460 //print('------------- got singleton ---------------' + this.isa);
461 //if (this.isa == "CONSTRUCTOR") {
462 // this.isNamespace = true;
469 if (this.comment.getTag(DocTagTitle.INNER).size > 0) {
471 this.isStatic = false;
476 if (this.comment.getTag(DocTagTitle.FIELD).size > 0) {
483 if (this.comment.getTag(DocTagTitle.FUNCTION).size > 0) {
484 this.isa = "FUNCTION";
488 if (this.comment.getTag(DocTagTitle.PARAM).size > 0 && this.isa == "OBJECT" ) {
489 // change a property to a function..
490 this.isa = "FUNCTION";
497 var events = this.comment.getTag(DocTagTitle.EVENT);
498 if (events.size > 0) {
499 this.isa = "FUNCTION";
506 var names = this.comment.getTag(DocTagTitle.NAME);
507 if (names.size > 0) {
508 this.private_name = names.get(0).desc.strip();
516 var properties = this.comment.getTag(DocTagTitle.PROPERTY);
517 if (properties.size > 0) {
518 //var thisProperties = this.properties;
519 for (var i = 0; i < properties.size; i++) {
522 // if the doc tag just says @property ... but no name etc..
523 // then name will not be filled in..
524 if (properties[i].name.length < 1 ) {
528 var property = new Symbol.new_populate_with_args(
529 this.alias+"#"+properties[i].name,
530 new Gee.ArrayList<string>(),
535 "\n@name "+ properties[i].name
536 +"\n@memberOf "+this.alias+"#*/"
538 // TODO: shouldn't the following happen in the addProperty method of Symbol?
539 property.private_name = properties[i].name;
540 property.memberOf = this.alias;
541 if (properties[i].type.length > 0) property.type = properties[i].type;
542 if (properties[i].defaultValue.length > 0) property.defaultValue = properties[i].defaultValue;
543 this.addProperty(property);
544 JSDOC.DocParser.addSymbol(property);
549 var conf = this.comment.getTag(DocTagTitle.CFG);
551 for (var i = 0; i < conf.size; i++) {
552 this.addConfig(conf.get(i));
559 var returns = this.comment.getTag(DocTagTitle.RETURN);
560 if (returns.size > 0) { // there can be many return tags in a single doclet
561 this.returns = returns;
564 foreach(var r in returns) {
565 this.type += this.type == "" ? "": ", ";
573 this.exceptions = this.comment.getTag(DocTagTitle.THROWS);
577 var requires = this.comment.getTag(DocTagTitle.REQUIRES);
578 if (requires.size > 0) {
579 this.requires = new Gee.ArrayList<string>();
580 foreach(var r in requires) {
581 this.requires.add(r.desc);
587 var types = this.comment.getTag(DocTagTitle.TYPE);
588 if (types.size > 0) {
589 this.type = types.get(0).desc; //multiple type tags are ignored
595 if (this.comment.getTag(DocTagTitle.PRIVATE).size > 0 || this.isInner) {
596 this.isPrivate = true;
600 if (this.comment.getTag(DocTagTitle.IGNORE).size > 0) {
601 this.isIgnored = true;
608 // @inherits ... as ... -- not used!!!
610 var inherits = this.comment.getTag("inherits");
611 if (inherits.length) {
612 for (var i = 0; i < inherits.length; i++) {
613 if (/^\s*([a-z$0-9_.#-]+)(?:\s+as\s+([a-z$0-9_.#]+))?/i.test(inherits[i].desc)) {
614 var inAlias = RegExp.$1;
615 var inAs = RegExp.$2 || inAlias;
617 if (inAlias) inAlias = inAlias.replace(/\.prototype\.?/g, "#");
620 inAs = inAs.replace(/\.prototype\.?/g, "#");
621 inAs = inAs.replace(/^this\.?/, "#");
624 if (inAs.indexOf(inAlias) != 0) { //not a full namepath
626 if (this.alias.charAt(this.alias.length-1) == "#" || inAs.charAt(0) == "#") {
629 inAs = this.alias + joiner + inAs;
632 this.inherits.push({alias: inAlias, as: inAs});
641 foreach(var dt in this.comment.getTag(DocTagTitle.ARGUMENTS)) {
642 this.augments.add(dt.desc);
645 foreach(var dt in this.comment.getTag(DocTagTitle.EXTENDS)) {
646 this.augments.add(dt.desc);
652 var defaults = this.comment.getTag(DocTagTitle.DEFAULT);
653 if (defaults.size > 0) {
654 if (this.is("OBJECT")) {
655 this.defaultValue = defaults.get(0).desc;
664 var memberOfs = this.comment.getTag(DocTagTitle.MEMBEROF);
665 if (memberOfs.size > 0) {
666 this.memberOf = memberOfs[0].desc;
667 var pr_reg = /\.prototype\.?/;
669 this.memberOf = pr_reg.replace(this.memberOf, this.memberOf.length, 0, "#");
670 var dname = this.name.split(".");
671 var name = dname[dname.length-1];
673 var hname = name.split("#");
674 name = hname[hname.length-1];
675 this.private_name = this.memberOf + "." + name; //?? "." ???
676 this.alias = this.name;
684 if (this.comment.getTag(DocTagTitle.PUBLIC).size > 0) {
685 this.isPrivate = false;
693 public bool is (string what) {
694 return this.isa == what;
696 public bool isaClass()
699 return (this.is("CONSTRUCTOR") || this.isNamespace ); //|| this.isClass);
703 public bool isBuiltin() {
704 return SymbolSet.isBuiltin(this.alias);
707 void setType(string comment,bool overwrite) {
708 if (!overwrite && this.type.length > 0) {
711 var typeComment = DocComment.unwrapComment(comment);
712 this.type = typeComment;
715 public void inherit (Symbol symbol) {
716 if (!this.hasMember(symbol.name) && !symbol.isInner) {
717 if (symbol.is("FUNCTION"))
718 this.methods.add(symbol);
719 else if (symbol.is("OBJECT"))
720 this.properties.add(symbol);
724 bool hasMember (string name) {
725 return (this.hasMethod(name) || this.hasProperty(name));
728 public void addMember (Symbol symbol) {
729 //println("ADDMEMBER: " + this.name + " ++ " + symbol.name);
731 if (symbol.comment.getTag(DocTagTitle.CFG).size == 1) {
732 symbol.comment.getTag(DocTagTitle.CFG).get(0).memberOf = this.alias;
733 this.addConfig(symbol.comment.getTag(DocTagTitle.CFG).get(0));
737 if (symbol.is("FUNCTION")) { this.addMethod(symbol); }
738 else if (symbol.is("OBJECT")) { this.addProperty(symbol); }
741 bool hasMethod (string name) {
742 var thisMethods = this.methods;
743 for (var i = 0, l = thisMethods.size; i < l; i++) {
744 if (thisMethods.get(i).name == name) return true;
745 if (thisMethods.get(i).alias == name) return true;
750 void addMethod (Symbol symbol) {
751 var methodAlias = symbol.alias;
752 var thisMethods = this.methods;
753 for (var i = 0, l = thisMethods.size; i < l; i++) {
754 if (thisMethods.get(i).alias == methodAlias) {
755 thisMethods.set(i, symbol); // overwriting previous method
759 thisMethods.add(symbol); // new method with this alias
762 bool hasProperty(string name) {
763 var thisProperties = this.properties;
764 for (var i = 0, l = thisProperties.size; i < l; i++) {
765 if (thisProperties.get(i).name == name) return true;
766 if (thisProperties.get(i).alias == name) return true;
771 void addProperty(Symbol symbol) {
772 var propertyAlias = symbol.alias;
773 var thisProperties = this.properties;
774 for (var i = 0, l = thisProperties.size; i < l; i++) {
775 if (thisProperties.get(i).alias == propertyAlias) {
776 thisProperties.set(i, symbol); // overwriting previous property
781 thisProperties.add(symbol); // new property with this alias
784 public void addDocTag(DocTag docTag)
786 this.comment.tags.add(docTag);
787 if (docTag.title == DocTagTitle.CFG) {
788 this.addConfig(docTag);
793 public void addConfig(DocTag docTag)
795 if (docTag.memberOf == "") {
796 // remove prototype data...
797 //var a = this.alias.split('#')[0];
798 //docTag.memberOf = a;
799 docTag.memberOf = this.alias;
801 if (!this.cfgs.has_key(docTag.name)) {
802 this.cfgs.set(docTag.name, docTag);
807 public Gee.ArrayList<DocTag> configToArray()
809 var r = new Gee.ArrayList<DocTag>();
810 foreach(var ci in this.cfgs.keys) {
811 // dont show hidden!!
812 if (this.cfgs.get(ci).desc.contains("@hide")) {
815 r.add(this.cfgs.get(ci));
823 public string makeFuncSkel() {
824 if (this.params.size < 1) return "function ()\n{\n\n}";
825 var ret = "function (";
827 foreach(var p in this.params) {
828 if (p.name.contains(".")) continue;
829 ret += f ? ", " : "";
831 ret += p.name == "this" ? "_self" : p.name;
833 return ret + ")\n{\n\n}";
835 public string makeMethodSkel() {
836 if (this.params.size < 1) return "()\n{\n\n}";
839 foreach(var p in this.params) {
840 GLib.debug("got param: %s", p.asString());
841 if (p.name.contains(".")) continue;
842 ret += f ? ", " : "";
845 case "this" : ret += "this"; break;
846 case "function" : ret += "function() {\n\n}"; break;
847 default : ret += p.name; break;
853 public Json.Array paramsToJson()
855 var ret = new Json.Array();
856 foreach(var p in this.params) {
857 //GLib.debug("got param: %s", p.asString());
858 if (p.name.contains(".")) continue;// ?? why?
859 var add = new Json.Object();
860 add.set_string_member("name",p.name);
861 add.set_string_member("type",p.type);
862 add.set_string_member("desc",p.desc);
863 add.set_boolean_member("isOptional",p.isOptional);
864 ret.add_object_element(add) ;
870 public Json.Array returnsToJson()
872 var ret = new Json.Array();
873 foreach(var p in this.returns) {
874 //GLib.debug("got param: %s", p.asString());
875 if (p.name.contains(".")) continue;// ?? why?
876 var add = new Json.Object();
877 add.set_string_member("name",p.name);
878 add.set_string_member("type",p.type);
879 add.set_string_member("desc",p.desc);
881 ret.add_object_element(add) ;
887 public Json.Array stringArrayToJson( Gee.ArrayList<string> ar)
889 var ret = new Json.Array();
890 foreach(var a in ar) {
891 ret.add_string_element(a);
896 public Json.Array symbolArrayToJson( Gee.ArrayList<Symbol> ar)
898 var ret = new Json.Array();
899 foreach(var a in ar) {
900 ret.add_object_element(a.toJson());
905 public Json.Array docTagsArrayToJson( Gee.ArrayList<DocTag> ar)
907 var ret = new Json.Array();
908 foreach(var a in ar) {
909 ret.add_object_element(a.toJson());
917 public Json.Object assocDocTagToJson( Gee.HashMap<string,DocTag> ar)
919 var ret = new Json.Object();
920 foreach(var a in ar.keys) {
921 ret.set_object_member(a, ar.get(a).toJson());
928 public Json.Object toJson()
930 var ret = new Json.Object();
931 ret.set_string_member("name", this.name);
932 ret.set_array_member("params", this.docTagsArrayToJson(this.params));
934 ret.set_array_member("augments", this.stringArrayToJson(this.augments));
935 ret.set_array_member("exceptions", this.docTagsArrayToJson(this.exceptions));
936 ret.set_array_member("methods", this.symbolArrayToJson(this.methods));
937 ret.set_array_member("properties", this.symbolArrayToJson(this.properties));
938 ret.set_array_member("requires", this.stringArrayToJson(this.requires));
939 ret.set_array_member("returns", this.docTagsArrayToJson(this.returns));
940 ret.set_array_member("see", this.stringArrayToJson(this.see));
941 ret.set_array_member("childClasses", this.stringArrayToJson(this.childClasses));
942 ret.set_array_member("inheritsFrom", this.stringArrayToJson(this.inheritsFrom));
943 ret.set_object_member("cfgs", this.assocDocTagToJson(this.cfgs));
944 ret.set_object_member("comment", this.comment.toJson());
945 //$args : [], // original arguments used when constructing.
947 ret.set_string_member("alias", this.alias);
949 ret.set_string_member("author", this.author);
950 ret.set_string_member("classDesc" , this.classDesc);
951 ret.set_string_member("deprecated", this.deprecated);
952 ret.set_string_member("desc", this.desc);
954 ret.set_string_member("example", this.example);
956 ret.set_string_member("isa", this.isa);
958 ret.set_boolean_member("isEvent", this.isEvent);
959 ret.set_boolean_member("isConstant", this.isConstant);
960 ret.set_boolean_member("isIgnored", this.isIgnored);
961 ret.set_boolean_member("isInner", this.isInner);
962 ret.set_boolean_member("isNamespace", this.isNamespace);
963 ret.set_boolean_member("isPrivate", this.isPrivate);
964 ret.set_boolean_member("isStatic", this.isStatic);
966 ret.set_string_member("memberOf", this.memberOf);
983 //static string[] hide = { "$args" };
984 //static string srcFile = "";
990 Symbol.fromDump = function(t)
992 var ns = new Symbol();
994 if (typeof(ns[i]) == "undefined") {
995 println("ERR:no default for Symbol:"+ i);