1aa44da8b37104ec30c013a1339f917eaa89b815
1 if (typeof JSDOC
== "undefined") JSDOC
= {};
5 @class Represents a symbol in the source code.
7 JSDOC
.Symbol
= function() {
9 if (arguments
.length
) this.populate
.apply(this, arguments
);
12 JSDOC
.Symbol
.count
= 0;
14 JSDOC
.Symbol
.prototype.init
= function() {
24 this.defaultValue
= undefined
;
30 this.id
= JSDOC
.Symbol
.count
++;
32 this.inheritsFrom
= [];
34 this.isConstant
= false;
36 this.isIgnored
= false;
38 this.isNamespace
= false;
39 this.isPrivate
= false;
40 this.isStatic
= false;
53 JSDOC
.Symbol
.prototype.serialize
= function() {
62 if (typeof this[keys
[i
]] == "function") continue;
63 out
+= keys
[i
]+" => "+Dumper
.dump(this[keys
[i
]])+",\n";
65 return "\n{\n" + out
+ "}\n";
68 JSDOC
.Symbol
.prototype.clone
= function() {
69 var clone
= new JSDOC
.Symbol();
70 clone
.populate
.apply(clone
, this.$args
); // repopulate using the original arguments
71 clone
.srcFile
= this.srcFile
; // not the current srcFile, the one when the original was made
75 JSDOC
.Symbol
.prototype.__defineSetter__("name",
76 function(n
) { n
= n
.replace(/^_global_[.#-]/, ""); n
= n
.replace(/\.prototype\.?/g, '#'); this._name
= n
; }
78 JSDOC
.Symbol
.prototype.__defineGetter__("name",
79 function() { return this._name
; }
81 JSDOC
.Symbol
.prototype.__defineSetter__("params",
83 for (var i
= 0, l
= v
.length
; i
< l
; i
++) {
84 if (v
[i
].constructor
!= JSDOC
.DocTag
) { // may be a generic object parsed from signature, like {type:..., name:...}
85 this._params
[i
] = new JSDOC
.DocTag("param"+((v
[i
].type
)?" {"+v
[i
].type
+"}":"")+" "+v
[i
].name
);
88 this._params
[i
] = v
[i
];
93 JSDOC
.Symbol
.prototype.__defineGetter__("params",
94 function() { return this._params
; }
97 JSDOC
.Symbol
.prototype.getEvents
= function() {
99 for (var i
= 0, l
= this.methods
.length
; i
< l
; i
++) {
100 if (this.methods
[i
].isEvent
) {
101 this.methods
[i
].name
= this.methods
[i
].name
.replace("event:", "");
102 events
.push(this.methods
[i
]);
108 JSDOC
.Symbol
.prototype.getMethods
= function() {
110 for (var i
= 0, l
= this.methods
.length
; i
< l
; i
++) {
111 if (!this.methods
[i
].isEvent
) {
112 nonEvents
.push(this.methods
[i
]);
119 JSDOC
.Symbol
.prototype.populate
= function(
121 /** Object[] */ params
,
123 /** JSDOC.DocComment */ comment
125 this.$args
= arguments
;
128 this.alias
= this.name
;
130 this.params
= params
;
131 this.isa
= (isa
== "VIRTUAL")? "OBJECT":isa
;
132 this.comment
= comment
|| new JSDOC
.DocComment("");
133 this.srcFile
= JSDOC
.Symbol
.srcFile
;
135 if (this.is("FILE") && !this.alias
) this.alias
= this.srcFile
;
139 if (typeof JSDOC
.PluginManager
!= "undefined") {
140 JSDOC
.PluginManager
.run("onSymbol", this);
144 JSDOC
.Symbol
.prototype.setTags
= function() {
146 var authors
= this.comment
.getTag("author");
147 if (authors
.length
) {
148 this.author
= authors
.map(function($){return $.desc
;}).join(", ");
152 plan(34, "testing JSDOC.Symbol");
154 requires("../lib/JSDOC/DocComment.js");
155 requires("../frame/String.js");
156 requires("../lib/JSDOC/DocTag.js");
158 var sym = new JSDOC.Symbol("foo", [], "OBJECT", new JSDOC.DocComment("/**@author Joe Smith*"+"/"));
159 is(sym.author, "Joe Smith", "@author tag, author is found.");
163 var descs
= this.comment
.getTag("desc");
165 this.desc
= descs
.map(function($){return $.desc
;}).join("\n"); // multiple descriptions are concatenated into one
169 var sym = new JSDOC.Symbol("foo", [], "OBJECT", new JSDOC.DocComment("/**@desc This is a description.*"+"/"));
170 is(sym.desc, "This is a description.", "@desc tag, description is found.");
174 if (this.is("FILE")) {
175 if (!this.alias
) this.alias
= this.srcFile
;
177 var overviews
= this.comment
.getTag("overview");
178 if (overviews
.length
) {
179 this.desc
= [this.desc
].concat(overviews
.map(function($){return $.desc
;})).join("\n");
184 var sym = new JSDOC.Symbol("foo", [], "FILE", new JSDOC.DocComment("/**@overview This is an overview.*"+"/"));
185 is(sym.desc, "\nThis is an overview.", "@overview tag, description is found.");
189 var sinces
= this.comment
.getTag("since");
191 this.since
= sinces
.map(function($){return $.desc
;}).join(", ");
195 var sym = new JSDOC.Symbol("foo", [], "FILE", new JSDOC.DocComment("/**@since 1.01*"+"/"));
196 is(sym.since, "1.01", "@since tag, description is found.");
200 if (this.comment
.getTag("constant").length
) {
201 this.isConstant
= true;
205 var sym = new JSDOC.Symbol("foo", [], "FILE", new JSDOC.DocComment("/**@constant*"+"/"));
206 is(sym.isConstant, true, "@constant tag, isConstant set.");
210 var versions
= this.comment
.getTag("version");
211 if (versions
.length
) {
212 this.version
= versions
.map(function($){return $.desc
;}).join(", ");
216 var sym = new JSDOC.Symbol("foo", [], "FILE", new JSDOC.DocComment("/**@version 2.0x*"+"/"));
217 is(sym.version, "2.0x", "@version tag, version is found.");
221 var deprecateds
= this.comment
.getTag("deprecated");
222 if (deprecateds
.length
) {
223 this.deprecated
= deprecateds
.map(function($){return $.desc
;}).join("\n");
227 var sym = new JSDOC.Symbol("foo", [], "FILE", new JSDOC.DocComment("/**@deprecated Use other method.*"+"/"));
228 is(sym.deprecated, "Use other method.", "@deprecated tag, desc is found.");
232 var examples
= this.comment
.getTag("example");
233 if (examples
.length
) {
234 this.example
= examples
.map(
235 // trim trailing whitespace
237 $.desc
= $.desc
.replace(/\s+$/, "");
244 var sym = new JSDOC.Symbol("foo", [], "FILE", new JSDOC.DocComment("/**@example This\n is an example. \n*"+"/"));
245 isnt(typeof sym.example[0], "undefined", "@example tag, creates sym.example array.");
246 is(sym.example[0], "This\n is an example.", "@example tag, desc is found.");
250 var sees
= this.comment
.getTag("see");
252 var thisSee
= this.see
;
253 sees
.map(function($){thisSee
.push($.desc
);});
257 var sym = new JSDOC.Symbol("foo", [], "FILE", new JSDOC.DocComment("/**@see The other thing.*"+"/"));
258 is(sym.see, "The other thing.", "@see tag, desc is found.");
262 var classes
= this.comment
.getTag("class");
263 if (classes
.length
) {
264 this.isa
= "CONSTRUCTOR";
265 this.classDesc
= classes
[0].desc
; // desc can't apply to the constructor as there is none.
269 var sym = new JSDOC.Symbol("foo", [], "OBJECT", new JSDOC.DocComment("/**@class This describes the class.*"+"/"));
270 is(sym.isa, "CONSTRUCTOR", "@class tag, makes symbol a constructor.");
271 is(sym.classDesc, "This describes the class.", "@class tag, class description is found.");
275 var namespaces
= this.comment
.getTag("namespace");
276 if (namespaces
.length
) {
277 this.classDesc
= namespaces
[0].desc
;
278 this.isNamespace
= true;
282 var sym = new JSDOC.Symbol("foo", [], "OBJECT", new JSDOC.DocComment("/**@namespace This describes the namespace.*"+"/"));
283 is(sym.classDesc, "This describes the namespace.", "@namespace tag, class description is found.");
287 var params
= this.comment
.getTag("param");
289 // user-defined params overwrite those with same name defined by the parser
290 var thisParams
= this.params
;
292 if (thisParams
.length
== 0) { // none exist yet, so just bung all these user-defined params straight in
293 this.params
= params
;
295 else { // need to overlay these user-defined params on to existing parser-defined params
296 for (var i
= 0, l
= params
.length
; i
< l
; i
++) {
298 if (params
[i
].type
) thisParams
[i
].type
= params
[i
].type
;
299 thisParams
[i
].name
= params
[i
].name
;
300 thisParams
[i
].desc
= params
[i
].desc
;
301 thisParams
[i
].isOptional
= params
[i
].isOptional
;
302 thisParams
[i
].defaultValue
= params
[i
].defaultValue
;
304 else thisParams
[i
] = params
[i
];
310 var sym = new JSDOC.Symbol("foo", [{type: "array", name: "pages"}], "FUNCTION", new JSDOC.DocComment("/**Description.*"+"/"));
311 is(sym.params.length, 1, "parser defined param is found.");
313 sym = new JSDOC.Symbol("foo", [], "FUNCTION", new JSDOC.DocComment("/**Description.\n@param {array} pages*"+"/"));
314 is(sym.params.length, 1, "user defined param is found.");
315 is(sym.params[0].type, "array", "user defined param type is found.");
316 is(sym.params[0].name, "pages", "user defined param name is found.");
318 sym = new JSDOC.Symbol("foo", [{type: "array", name: "pages"}], "FUNCTION", new JSDOC.DocComment("/**Description.\n@param {string} uid*"+"/"));
319 is(sym.params.length, 1, "user defined param overwrites parser defined param.");
320 is(sym.params[0].type, "string", "user defined param type overwrites parser defined param type.");
321 is(sym.params[0].name, "uid", "user defined param name overwrites parser defined param name.");
323 sym = new JSDOC.Symbol("foo", [{type: "array", name: "pages"}, {type: "number", name: "count"}], "FUNCTION", new JSDOC.DocComment("/**Description.\n@param {string} uid*"+"/"));
324 is(sym.params.length, 2, "user defined params overlay parser defined params.");
325 is(sym.params[1].type, "number", "user defined param type overlays parser defined param type.");
326 is(sym.params[1].name, "count", "user defined param name overlays parser defined param name.");
328 sym = new JSDOC.Symbol("foo", [], "FUNCTION", new JSDOC.DocComment("/**Description.\n@param {array} pages The pages description.*"+"/"));
329 is(sym.params.length, 1, "user defined param with description is found.");
330 is(sym.params[0].desc, "The pages description.", "user defined param description is found.");
334 if (this.comment
.getTag("constructor").length
) {
335 this.isa
= "CONSTRUCTOR";
339 var sym = new JSDOC.Symbol("foo", [], "OBJECT", new JSDOC.DocComment("/**@constructor*"+"/"));
340 is(sym.isa, "CONSTRUCTOR", "@constructor tag, makes symbol a constructor.");
344 if (this.comment
.getTag("static").length
) {
345 this.isStatic
= true;
346 if (this.isa
== "CONSTRUCTOR") {
347 this.isNamespace
= true;
352 var sym = new JSDOC.Symbol("foo", [], "OBJECT", new JSDOC.DocComment("/**@static\n@constructor*"+"/"));
353 is(sym.isStatic, true, "@static tag, makes isStatic true.");
354 is(sym.isNamespace, true, "@static and @constructor tag, makes isNamespace true.");
358 if (this.comment
.getTag("inner").length
) {
360 this.isStatic
= false;
364 var sym = new JSDOC.Symbol("foo", [], "OBJECT", new JSDOC.DocComment("/**@inner*"+"/"));
365 is(sym.isStatic, false, "@inner tag, makes isStatic false.");
366 is(sym.isInner, true, "@inner makes isInner true.");
370 var names
= this.comment
.getTag("name");
372 this.name
= names
[0].desc
;
380 if (this.comment
.getTag("field").length
) {
385 var sym = new JSDOC.Symbol("foo", [], "FUNCTION", new JSDOC.DocComment("/**@field*"+"/"));
386 is(sym.isa, "OBJECT", "@field tag, makes symbol an object.");
390 if (this.comment
.getTag("function").length
) {
391 this.isa
= "FUNCTION";
392 if (/event:/.test(this.alias
)) this.isEvent
= true;
396 var sym = new JSDOC.Symbol("foo", [], "OBJECT", new JSDOC.DocComment("/**@function*"+"/"));
397 is(sym.isa, "FUNCTION", "@function tag, makes symbol a function.");
401 var events
= this.comment
.getTag("event");
403 this.isa
= "FUNCTION";
405 if (!/event:/.test(this.alias
))
406 this.alias
= this.alias
.replace(/^(.*[.#-])([^.#-]+)$/, "$1event:$2");
410 var sym = new JSDOC.Symbol("foo", [], "OBJECT", new JSDOC.DocComment("/**@event*"+"/"));
411 is(sym.isa, "FUNCTION", "@event tag, makes symbol a function.");
412 is(sym.isEvent, true, "@event makes isEvent true.");
416 var fires
= this.comment
.getTag("fires");
418 for (var i
= 0; i
< fires
.length
; i
++) {
419 this.fires
.push(fires
[i
].desc
);
428 var properties
= this.comment
.getTag("property");
429 if (properties
.length
) {
430 thisProperties
= this.properties
;
431 for (var i
= 0; i
< properties
.length
; i
++) {
432 var property
= new JSDOC
.Symbol(this.alias
+"#"+properties
[i
].name
, [], "OBJECT", new JSDOC
.DocComment("/**"+properties
[i
].desc
+"*/"));
433 // TODO: shouldn't the following happen in the addProperty method of Symbol?
434 if (properties
[i
].type
) property
.type
= properties
[i
].type
;
435 if (properties
[i
].defaultValue
) property
.defaultValue
= properties
[i
].defaultValue
;
436 this.addProperty(property
);
437 if (!JSDOC
.Parser
.symbols
.getSymbolByName(property
.name
))
438 JSDOC
.Parser
.addSymbol(property
);
447 var returns
= this.comment
.getTag("return");
448 if (returns
.length
) { // there can be many return tags in a single doclet
449 this.returns
= returns
;
450 this.type
= returns
.map(function($){return $.type
}).join(", ");
458 this.exceptions
= this.comment
.getTag("throws");
465 var requires
= this.comment
.getTag("requires");
466 if (requires
.length
) {
467 this.requires
= requires
.map(function($){return $.desc
});
475 var types
= this.comment
.getTag("type");
477 this.type
= types
[0].desc
; //multiple type tags are ignored
485 if (this.comment
.getTag("private").length
|| this.isInner
) {
486 this.isPrivate
= true;
490 if (this.comment
.getTag("ignore").length
) {
491 this.isIgnored
= true;
498 // @inherits ... as ...
499 var inherits
= this.comment
.getTag("inherits");
500 if (inherits
.length
) {
501 for (var i
= 0; i
< inherits
.length
; i
++) {
502 if (/^\s*([a-z$0-9_.#:-]+)(?:\s+as\s+([a-z$0-9_.#:-]+))?/i.test(inherits
[i
].desc
)) {
503 var inAlias
= RegExp
.$1;
504 var inAs
= RegExp
.$2 || inAlias
;
506 if (inAlias
) inAlias
= inAlias
.replace(/\.prototype\.?/g, "#");
509 inAs
= inAs
.replace(/\.prototype\.?/g, "#");
510 inAs
= inAs
.replace(/^this\.?/, "#");
513 if (inAs
.indexOf(inAlias
) != 0) { //not a full namepath
515 if (this.alias
.charAt(this.alias
.length
-1) == "#" || inAs
.charAt(0) == "#") {
518 inAs
= this.alias
+ joiner
+ inAs
;
521 this.inherits
.push({alias
: inAlias
, as
: inAs
});
530 this.augments
= this.comment
.getTag("augments");
533 var defaults
= this.comment
.getTag("default");
534 if (defaults
.length
) {
535 if (this.is("OBJECT")) {
536 this.defaultValue
= defaults
[0].desc
;
545 var memberOfs
= this.comment
.getTag("memberOf");
546 if (memberOfs
.length
) {
547 this.memberOf
= memberOfs
[0].desc
;
548 this.memberOf
= this.memberOf
.replace(/\.prototype\.?/g, "#");
556 if (this.comment
.getTag("public").length
) {
557 this.isPrivate
= false;
564 if (JSDOC
.PluginManager
) {
565 JSDOC
.PluginManager
.run("onSetTags", this);
569 JSDOC
.Symbol
.prototype.is
= function(what
) {
570 return this.isa
=== what
;
573 JSDOC
.Symbol
.prototype.isBuiltin
= function() {
574 return JSDOC
.Lang
.isBuiltin(this.alias
);
577 JSDOC
.Symbol
.prototype.setType
= function(/**String*/comment
, /**Boolean*/overwrite
) {
578 if (!overwrite
&& this.type
) return;
579 var typeComment
= JSDOC
.DocComment
.unwrapComment(comment
);
580 this.type
= typeComment
;
583 JSDOC
.Symbol
.prototype.inherit
= function(symbol
) {
584 if (!this.hasMember(symbol
.name
) && !symbol
.isInner
) {
585 if (symbol
.is("FUNCTION"))
586 this.methods
.push(symbol
);
587 else if (symbol
.is("OBJECT"))
588 this.properties
.push(symbol
);
592 JSDOC
.Symbol
.prototype.hasMember
= function(name
) {
593 return (this.hasMethod(name
) || this.hasProperty(name
));
596 JSDOC
.Symbol
.prototype.addMember
= function(symbol
) {
597 if (symbol
.is("FUNCTION")) { this.addMethod(symbol
); }
598 else if (symbol
.is("OBJECT")) { this.addProperty(symbol
); }
601 JSDOC
.Symbol
.prototype.hasMethod
= function(name
) {
602 var thisMethods
= this.methods
;
603 for (var i
= 0, l
= thisMethods
.length
; i
< l
; i
++) {
604 if (thisMethods
[i
].name
== name
) return true;
605 if (thisMethods
[i
].alias
== name
) return true;
610 JSDOC
.Symbol
.prototype.addMethod
= function(symbol
) {
611 var methodAlias
= symbol
.alias
;
612 var thisMethods
= this.methods
;
613 for (var i
= 0, l
= thisMethods
.length
; i
< l
; i
++) {
614 if (thisMethods
[i
].alias
== methodAlias
) {
615 thisMethods
[i
] = symbol
; // overwriting previous method
619 thisMethods
.push(symbol
); // new method with this alias
622 JSDOC
.Symbol
.prototype.hasProperty
= function(name
) {
623 var thisProperties
= this.properties
;
624 for (var i
= 0, l
= thisProperties
.length
; i
< l
; i
++) {
625 if (thisProperties
[i
].name
== name
) return true;
626 if (thisProperties
[i
].alias
== name
) return true;
631 JSDOC
.Symbol
.prototype.addProperty
= function(symbol
) {
632 var propertyAlias
= symbol
.alias
;
633 var thisProperties
= this.properties
;
634 for (var i
= 0, l
= thisProperties
.length
; i
< l
; i
++) {
635 if (thisProperties
[i
].alias
== propertyAlias
) {
636 thisProperties
[i
] = symbol
; // overwriting previous property
641 thisProperties
.push(symbol
); // new property with this alias
644 JSDOC
.Symbol
.srcFile
= ""; //running reference to the current file being parsed