1 if (typeof JSDOC == "undefined") JSDOC = {};
   2 
   3 /**
   4  * <p class="org_comment" >Create a new Symbol.</p>
   5  * @class
   6  * Symbolクラスは1つのシンボルを表します。
   7  * 通常このクラスのインスタンスは[[JSDOC.SymbolSet]]オブジェクトのメソッドから取得されます。 
   8  * <p class="org_comment" >Represents a symbol in the source code.</p>
   9  */
  10 JSDOC.Symbol = function() {
  11     this.init();
  12     if (arguments.length) this.populate.apply(this, arguments);
  13 }
  14 
  15 JSDOC.Symbol.count = 0;
  16 
  17 /** @ignore */
  18 JSDOC.Symbol.prototype.init = function() {
  19     this._name = "";
  20     this._params = [];
  21     this.$args = [];
  22     this.addOn = "";
  23     
  24     /**
  25      * シンボルの完全なネームパスで表される一意な名称
  26      * @type String
  27      */
  28     this.alias = "";
  29     
  30     /**
  31      * このシンボルの継承元クラス情報を保持する、@augmentsタグから作成されたタグオブジェクトの配列
  32      * @type JSDOC.DocTag[]
  33      */
  34     this.augments = [];
  35     
  36     /**
  37      * 作者情報。@authorタグが複数記述されていた場合、カンマ区切りの文字列に結合されています。
  38      * @type String
  39      */
  40     this.author = "";
  41 
  42     /**
  43      * クラスの説明文。@classタグまたは@namespaceタグの説明文が設定されています。 
  44      * @type String
  45      */
  46     this.classDesc = "";
  47     
  48     /**
  49      * このシンボルのドックコメントをパースしたドックコメントオブジェクト 
  50      * @type JSDOC.DocComment
  51      */
  52     this.comment = {};
  53     
  54     /**
  55      * デフォルト値。@defaultタグの内容が設定されています。 
  56      * @type String
  57      */
  58     this.defaultValue = undefined;
  59     
  60     /**
  61      * 非推奨情報。@deprecatedタグが複数記述されていた場合、改行文字区切りの文字列に結合されています。
  62      * @type String
  63      */
  64     this.deprecated = "";
  65     
  66     /**
  67      * シンボルの説明文。ドックコメントの先頭に書かれたタグなしの説明文や、@descriptionタグの説明文が設定されています。
  68      * またシンボル種別が FILE の場合、@fileOverviewタグの説明文が設定されています。 <br>
  69      * これらが複数記述されていた場合、改行文字区切りの文字列に結合されています。
  70      * @type String
  71      */
  72     this.desc = "";
  73 
  74     /**
  75      * サンプルコード。@exampleタグをパースしたタグオブジェクトの配列です。
  76      * @type JSDOC.DocTag[]
  77      */
  78     this.example = [];
  79     
  80     /**
  81      * 例外。@throwsタグをパースしたDocTagオブジェクトの配列です。
  82      * @type JSDOC.DocTag[]
  83      */
  84     this.exceptions = [];
  85     
  86     this.fires = [];
  87     
  88     /**
  89      * システムによって全シンボルに付与された一意の番号
  90      * @type Number
  91      */
  92     this.id = JSDOC.Symbol.count++;
  93     
  94     /**
  95      * メンバの借用関係を示す無名オブジェクトの配列。@borrowsタグから作成されます。 <br>
  96      * 無名オブジェクトは以下のプロパティを持ちます。
  97      * @type Object[]
  98      * @field {String} .alias 借用元メンバのエイリアス
  99      * @field {String} .as    借用先メンバのエイリアス
 100      */
 101     this.inherits = [];
 102     
 103     /**
 104      * このシンボルの継承元クラスを表すシンボルオブジェクトの配列。@augmentsタグから作成されます。
 105      * @type JSDOC.Symbol[]
 106      */
 107     this.inheritsFrom = [];
 108     
 109     /**
 110      * シンボルの種別を表す文字列
 111      * <table class="table_in_desc" >
 112      * <tr><th>CONSTRUCTOR</th><td>クラス(コンストラクタ)、名前空間</td></tr>
 113      * <tr><th>FILE</th><td>ファイル</td></tr>
 114      * <tr><th>FUNCTION</th><td>関数、メソッド、イベント</td></tr>
 115      * <tr><th>OBJECT</th><td>上記以外のオブジェクト(変数、プロパティなど)</td></tr>
 116      * </table>
 117      * @type String
 118      */
 119     this.isa = "OBJECT";
 120 
 121     /**
 122      * このシンボルが定数ならtrue
 123      * @type Boolean
 124      */
 125     this.isConstant = false;
 126     
 127     /**
 128      * このシンボルがイベントならtrue
 129      * @type Boolean
 130      */
 131     this.isEvent = false;
 132     
 133     this.isIgnored = false;
 134     
 135     /**
 136      * このシンボルが内部関数ならtrue
 137      * @type Boolean
 138      */
 139     this.isInner = false;
 140 
 141     /**
 142      * このシンボルが名前空間ならtrue 
 143      * @type Boolean
 144      */
 145     this.isNamespace = false;
 146     
 147     /**
 148      * このシンボルのスコープがprivateならtrue 
 149      * @type Boolean
 150      */
 151     this.isPrivate = false;
 152     
 153     /**
 154      * このシンボルが静的メンバならtrue
 155      * @type Boolean
 156      */
 157     this.isStatic = false;
 158     
 159     /**
 160      * このシンボルがメンバとして定義されているシンボルのエイリアス
 161      * @type String
 162      */
 163     this.memberOf = "";
 164     
 165     /**
 166      * このシンボルがメンバとしているメソッドシンボルの配列。他のクラスから継承しているものも含みます。
 167      * @type JSDOC.Symbol[]
 168      */
 169     this.methods = [];
 170     
 171     /**
 172      * このシンボルがメンバとしているプロパティシンボルの配列。他のクラスから継承しているものも含みます。
 173      * @type JSDOC.Symbol[]
 174      */
 175     this.properties = [];
 176 
 177     /**
 178      * このシンボルが依存するシンボルのエイリアスの配列
 179      * @type String[]
 180      */
 181     this.requires = [];
 182     
 183     /**
 184      * メソッドの戻り値。@returnsタグをパースしたタグオブジェクトの配列です。
 185      * @type JSDOC.DocTag[]
 186      */
 187     this.returns = [];
 188     
 189     /**
 190      * 関連項目へのリンクを含むHTMLテキストまたはシンボルエイリアスの配列
 191      * @type String[]
 192      */
 193     this.see = [];
 194     
 195     /**
 196      * このシンボルが使用可能になったバージョンに関する情報。@sinceタグから作成されます。 <br>
 197      * タグが複数記述されていた場合、カンマ区切りの文字列に結合されています。
 198      * @type String
 199      */
 200     this.since = "";
 201     
 202     /**
 203      * このシンボルが定義されているソースファイルのパス
 204      * @type String
 205      */
 206     this.srcFile = {};
 207     
 208     /**
 209      * データ型(クラスの場合はエイリアス)
 210      * @type String
 211      */
 212     this.type = "";
 213     
 214     /**
 215      * バージョン。@versionタグから作成されます。 <br>
 216      * タグが複数記述されていた場合、カンマ区切りの文字列に結合されています。
 217      * @type String
 218      */
 219     this.version = "";
 220 }
 221 
 222 /** @ignore */
 223 JSDOC.Symbol.prototype.serialize = function() {
 224     var keys = [];
 225     for (var p in this) {
 226         keys.push (p);
 227     }
 228     keys = keys.sort();
 229     
 230     var out = "";
 231     for (var i in keys) {
 232         if (typeof this[keys[i]] == "function") continue;
 233         out += keys[i]+" => "+Dumper.dump(this[keys[i]])+",\n";
 234     }
 235     return "\n{\n" + out + "}\n";
 236 }
 237 
 238 /**
 239  * このシンボルの複製を返します。
 240  * @return {JSDOC.Symbol} シンボルの複製
 241  */
 242 JSDOC.Symbol.prototype.clone = function() {
 243     var clone = new JSDOC.Symbol();
 244     clone.populate.apply(clone, this.$args); // repopulate using the original arguments
 245     clone.srcFile = this.srcFile; // not the current srcFile, the one when the original was made
 246     return clone;
 247 }
 248 
 249 /**
 250  * @name JSDOC.Symbol#name
 251  * @desc このシンボルの名前。
 252  *       [[alias]]プロパティがネームパスによるシンボルの一意な識別子であるのに対し、
 253  *       nameプロパティにはメソッド名のような単純な名称が設定されます。
 254  * @type String
 255  */
 256 JSDOC.Symbol.prototype.__defineSetter__("name",
 257     function(n) { n = n.replace(/^_global_[.#-]/, ""); n = n.replace(/\.prototype\.?/g, '#'); this._name = n; }
 258 );
 259 JSDOC.Symbol.prototype.__defineGetter__("name",
 260     function() { return this._name; }
 261 );
 262 
 263 /**
 264  * @name JSDOC.Symbol#params
 265  * @desc シンボルのパラメータを表すタグオブジェクトの配列
 266  * @type JSDOC.DocTag[]
 267  */
 268 JSDOC.Symbol.prototype.__defineSetter__("params", 
 269     function(v) {
 270         for (var i = 0, l = v.length; i < l; i++) {
 271             if (v[i].constructor != JSDOC.DocTag) { // may be a generic object parsed from signature, like {type:..., name:...}
 272                 this._params[i] = new JSDOC.DocTag("param"+((v[i].type)?" {"+v[i].type+"}":"")+" "+v[i].name);
 273             }
 274             else {
 275                 this._params[i] = v[i];
 276             }
 277         }
 278     }
 279 );
 280 JSDOC.Symbol.prototype.__defineGetter__("params",
 281     function() { return this._params; }
 282 );
 283 
 284 /**
 285  * このシンボルに含まれる全てのイベントシンボルの配列を返します。
 286  * @return {JSDOC.Symbol[]} イベントシンボルの配列
 287  */
 288 JSDOC.Symbol.prototype.getEvents = function() {
 289     var events = [];
 290     for (var i = 0, l = this.methods.length; i < l; i++) {
 291         if (this.methods[i].isEvent) {
 292             this.methods[i].name = this.methods[i].name.replace("event:", "");
 293             events.push(this.methods[i]);
 294         }
 295     }
 296     return events;
 297 }
 298 
 299 /**
 300  * このシンボルに含まれる全てのメソッドシンボルの配列を返します。
 301  * @return {JSDOC.Symbol[]} メソッドシンボルの配列
 302  */
 303 JSDOC.Symbol.prototype.getMethods = function() {
 304     var nonEvents = [];
 305     for (var i = 0, l = this.methods.length; i < l; i++) {
 306         if (!this.methods[i].isEvent) {
 307             nonEvents.push(this.methods[i]);
 308         }
 309     }
 310     return nonEvents;
 311 }
 312 
 313 /** @ignore */
 314 JSDOC.Symbol.prototype.populate = function(
 315         /** String */ name,
 316         /** Object[] */ params,
 317         /** String */ isa,
 318         /** JSDOC.DocComment */ comment
 319 ) {
 320     this.$args = arguments;
 321     
 322     this.name = name;
 323     this.alias = this.name;
 324     
 325     this.params = params;
 326     this.isa = (isa == "VIRTUAL")? "OBJECT":isa;
 327     this.comment = comment || new JSDOC.DocComment("");
 328     this.srcFile = JSDOC.Symbol.srcFile;
 329     
 330     if (this.is("FILE") && !this.alias) this.alias = this.srcFile;
 331 
 332     this.setTags();
 333     
 334     if (typeof JSDOC.PluginManager != "undefined") {
 335         JSDOC.PluginManager.run("onSymbol", this);
 336     }
 337 }
 338 
 339 /** @ignore */
 340 JSDOC.Symbol.prototype.setTags = function() {
 341     // @author
 342     var authors = this.comment.getTag("author");
 343     if (authors.length) {
 344         this.author = authors.map(function($){return $.desc;}).join(", ");
 345     }
 346     
 347     /*t:
 348         plan(34, "testing JSDOC.Symbol");
 349         
 350         requires("../lib/JSDOC/DocComment.js");
 351         requires("../frame/String.js");
 352         requires("../lib/JSDOC/DocTag.js");
 353 
 354         var sym = new JSDOC.Symbol("foo", [], "OBJECT", new JSDOC.DocComment("/**@author Joe Smith*"+"/"));
 355         is(sym.author, "Joe Smith", "@author tag, author is found.");
 356     */
 357     
 358     // @desc
 359     var descs = this.comment.getTag("desc");
 360     if (descs.length) {
 361         this.desc = descs.map(function($){return $.desc;}).join("\n"); // multiple descriptions are concatenated into one
 362     }
 363     
 364     /*t:
 365         var sym = new JSDOC.Symbol("foo", [], "OBJECT", new JSDOC.DocComment("/**@desc This is a description.*"+"/"));
 366         is(sym.desc, "This is a description.", "@desc tag, description is found.");
 367     */
 368     
 369     // @overview
 370     if (this.is("FILE")) {
 371         if (!this.alias) this.alias = this.srcFile;
 372         
 373         var overviews = this.comment.getTag("overview");
 374         if (overviews.length) {
 375             this.desc = [this.desc].concat(overviews.map(function($){return $.desc;})).join("\n");
 376         }
 377     }
 378     
 379     /*t:
 380         var sym = new JSDOC.Symbol("foo", [], "FILE", new JSDOC.DocComment("/**@overview This is an overview.*"+"/"));
 381         is(sym.desc, "\nThis is an overview.", "@overview tag, description is found.");
 382     */
 383     
 384     // @since
 385     var sinces = this.comment.getTag("since");
 386     if (sinces.length) {
 387         this.since = sinces.map(function($){return $.desc;}).join(", ");
 388     }
 389     
 390     /*t:
 391         var sym = new JSDOC.Symbol("foo", [], "FILE", new JSDOC.DocComment("/**@since 1.01*"+"/"));
 392         is(sym.since, "1.01", "@since tag, description is found.");
 393     */
 394     
 395     // @constant
 396     if (this.comment.getTag("constant").length) {
 397         this.isConstant = true;
 398     }
 399     
 400     /*t:
 401         var sym = new JSDOC.Symbol("foo", [], "FILE", new JSDOC.DocComment("/**@constant*"+"/"));
 402         is(sym.isConstant, true, "@constant tag, isConstant set.");
 403     */
 404     
 405     // @version
 406     var versions = this.comment.getTag("version");
 407     if (versions.length) {
 408         this.version = versions.map(function($){return $.desc;}).join(", ");
 409     }
 410     
 411     /*t:
 412         var sym = new JSDOC.Symbol("foo", [], "FILE", new JSDOC.DocComment("/**@version 2.0x*"+"/"));
 413         is(sym.version, "2.0x", "@version tag, version is found.");
 414     */
 415     
 416     // @deprecated
 417     var deprecateds = this.comment.getTag("deprecated");
 418     if (deprecateds.length) {
 419         this.deprecated = deprecateds.map(function($){return $.desc;}).join("\n");
 420     }
 421     
 422     /*t:
 423         var sym = new JSDOC.Symbol("foo", [], "FILE", new JSDOC.DocComment("/**@deprecated Use other method.*"+"/"));
 424         is(sym.deprecated, "Use other method.", "@deprecated tag, desc is found.");
 425     */
 426     
 427     // @example
 428     var examples = this.comment.getTag("example");
 429     if (examples.length) {
 430         this.example = examples.map(
 431             // trim trailing whitespace
 432             function($) {
 433                 $.desc = $.desc.replace(/\s+$/, "");
 434                 return $;
 435             }
 436         );
 437     }
 438     
 439     /*t:
 440         var sym = new JSDOC.Symbol("foo", [], "FILE", new JSDOC.DocComment("/**@example This\n  is an example. \n*"+"/"));
 441         isnt(typeof sym.example[0], "undefined", "@example tag, creates sym.example array.");
 442         is(sym.example[0], "This\n  is an example.", "@example tag, desc is found.");
 443     */
 444     
 445     // @see
 446     var sees = this.comment.getTag("see");
 447     if (sees.length) {
 448         var thisSee = this.see;
 449         sees.map(function($){thisSee.push($.desc);});
 450     }
 451     
 452     /*t:
 453         var sym = new JSDOC.Symbol("foo", [], "FILE", new JSDOC.DocComment("/**@see The other thing.*"+"/"));
 454         is(sym.see, "The other thing.", "@see tag, desc is found.");
 455     */
 456     
 457     // @class
 458     var classes = this.comment.getTag("class");
 459     if (classes.length) {
 460         this.isa = "CONSTRUCTOR";
 461         this.classDesc = classes[0].desc; // desc can't apply to the constructor as there is none.
 462     }
 463     
 464     /*t:
 465         var sym = new JSDOC.Symbol("foo", [], "OBJECT", new JSDOC.DocComment("/**@class This describes the class.*"+"/"));
 466         is(sym.isa, "CONSTRUCTOR", "@class tag, makes symbol a constructor.");
 467         is(sym.classDesc, "This describes the class.", "@class tag, class description is found.");
 468     */
 469     
 470     // @namespace
 471     var namespaces = this.comment.getTag("namespace");
 472     if (namespaces.length) {
 473         this.classDesc = namespaces[0].desc;
 474         this.isNamespace = true;
 475     }
 476     
 477     /*t:
 478         var sym = new JSDOC.Symbol("foo", [], "OBJECT", new JSDOC.DocComment("/**@namespace This describes the namespace.*"+"/"));
 479         is(sym.classDesc, "This describes the namespace.", "@namespace tag, class description is found.");
 480     */
 481     
 482     // @param
 483     var params = this.comment.getTag("param");
 484     if (params.length) {
 485         // user-defined params overwrite those with same name defined by the parser
 486         var thisParams = this.params;
 487 
 488         if (thisParams.length == 0) { // none exist yet, so just bung all these user-defined params straight in
 489             this.params = params;
 490         }
 491         else { // need to overlay these user-defined params on to existing parser-defined params
 492             for (var i = 0, l = params.length; i < l; i++) {
 493                 if (thisParams[i]) {
 494                     if (params[i].type) thisParams[i].type = params[i].type;
 495                     thisParams[i].name = params[i].name;
 496                     thisParams[i].desc = params[i].desc;
 497                     thisParams[i].isOptional = params[i].isOptional;
 498                     thisParams[i].defaultValue = params[i].defaultValue;
 499                 }
 500                 else thisParams[i] = params[i];
 501             }
 502         }
 503     }
 504     
 505     /*t:
 506         var sym = new JSDOC.Symbol("foo", [{type: "array", name: "pages"}], "FUNCTION", new JSDOC.DocComment("/**Description.*"+"/"));
 507         is(sym.params.length, 1, "parser defined param is found.");
 508         
 509         sym = new JSDOC.Symbol("foo", [], "FUNCTION", new JSDOC.DocComment("/**Description.\n@param {array} pages*"+"/"));
 510         is(sym.params.length, 1, "user defined param is found.");
 511         is(sym.params[0].type, "array", "user defined param type is found.");
 512         is(sym.params[0].name, "pages", "user defined param name is found.");
 513         
 514         sym = new JSDOC.Symbol("foo", [{type: "array", name: "pages"}], "FUNCTION", new JSDOC.DocComment("/**Description.\n@param {string} uid*"+"/"));
 515         is(sym.params.length, 1, "user defined param overwrites parser defined param.");
 516         is(sym.params[0].type, "string", "user defined param type overwrites parser defined param type.");
 517         is(sym.params[0].name, "uid", "user defined param name overwrites parser defined param name.");
 518     
 519         sym = new JSDOC.Symbol("foo", [{type: "array", name: "pages"}, {type: "number", name: "count"}], "FUNCTION", new JSDOC.DocComment("/**Description.\n@param {string} uid*"+"/"));
 520         is(sym.params.length, 2, "user defined params  overlay parser defined params.");
 521         is(sym.params[1].type, "number", "user defined param type overlays parser defined param type.");
 522         is(sym.params[1].name, "count", "user defined param name overlays parser defined param name.");
 523 
 524         sym = new JSDOC.Symbol("foo", [], "FUNCTION", new JSDOC.DocComment("/**Description.\n@param {array} pages The pages description.*"+"/"));
 525         is(sym.params.length, 1, "user defined param with description is found.");
 526         is(sym.params[0].desc, "The pages description.", "user defined param description is found.");
 527     */
 528     
 529     // @constructor
 530     if (this.comment.getTag("constructor").length) {
 531         this.isa = "CONSTRUCTOR";
 532     }
 533     
 534     /*t:
 535         var sym = new JSDOC.Symbol("foo", [], "OBJECT", new JSDOC.DocComment("/**@constructor*"+"/"));
 536         is(sym.isa, "CONSTRUCTOR", "@constructor tag, makes symbol a constructor.");
 537     */
 538     
 539     // @static
 540     if (this.comment.getTag("static").length) {
 541         this.isStatic = true;
 542         if (this.isa == "CONSTRUCTOR") {
 543             this.isNamespace = true;
 544         }
 545     }
 546     
 547     /*t:
 548         var sym = new JSDOC.Symbol("foo", [], "OBJECT", new JSDOC.DocComment("/**@static\n@constructor*"+"/"));
 549         is(sym.isStatic, true, "@static tag, makes isStatic true.");
 550         is(sym.isNamespace, true, "@static and @constructor tag, makes isNamespace true.");
 551     */
 552     
 553     // @inner
 554     if (this.comment.getTag("inner").length) {
 555         this.isInner = true;
 556         this.isStatic = false;
 557     }
 558     
 559     /*t:
 560         var sym = new JSDOC.Symbol("foo", [], "OBJECT", new JSDOC.DocComment("/**@inner*"+"/"));
 561         is(sym.isStatic, false, "@inner tag, makes isStatic false.");
 562         is(sym.isInner, true, "@inner makes isInner true.");
 563     */
 564     
 565     // @name
 566     var names = this.comment.getTag("name");
 567     if (names.length) {
 568         this.name = names[0].desc;
 569     }
 570     
 571     /*t:
 572         // todo
 573     */
 574     
 575     // @field
 576     if (this.comment.getTag("field").length) {
 577         this.isa = "OBJECT";
 578     }
 579     
 580     /*t:
 581         var sym = new JSDOC.Symbol("foo", [], "FUNCTION", new JSDOC.DocComment("/**@field*"+"/"));
 582         is(sym.isa, "OBJECT", "@field tag, makes symbol an object.");
 583     */
 584     
 585     // @function
 586     if (this.comment.getTag("function").length) {
 587         this.isa = "FUNCTION";
 588         if (/event:/.test(this.alias)) this.isEvent = true;
 589     }
 590     
 591     /*t:
 592         var sym = new JSDOC.Symbol("foo", [], "OBJECT", new JSDOC.DocComment("/**@function*"+"/"));
 593         is(sym.isa, "FUNCTION", "@function tag, makes symbol a function.");
 594     */
 595     
 596     // @event
 597     var events = this.comment.getTag("event");
 598     if (events.length) {
 599         this.isa = "FUNCTION";
 600         this.isEvent = true;
 601         if (!/event:/.test(this.alias))
 602             this.alias = this.alias.replace(/^(.*[.#-])([^.#-]+)$/, "$1event:$2");
 603     }
 604     
 605     /*t:
 606         var sym = new JSDOC.Symbol("foo", [], "OBJECT", new JSDOC.DocComment("/**@event*"+"/"));
 607         is(sym.isa, "FUNCTION", "@event tag, makes symbol a function.");
 608         is(sym.isEvent, true, "@event makes isEvent true.");
 609     */
 610     
 611     // @fires
 612     var fires = this.comment.getTag("fires");
 613     if (fires.length) {
 614         for (var i = 0; i < fires.length; i++) {
 615             this.fires.push(fires[i].desc);
 616         }
 617     }
 618     
 619     /*t:
 620         // todo
 621     */
 622     
 623     // @property
 624     var properties = this.comment.getTag("property");
 625     if (properties.length) {
 626         thisProperties = this.properties;
 627         for (var i = 0; i < properties.length; i++) {
 628             var property = new JSDOC.Symbol(this.alias+"#"+properties[i].name, [], "OBJECT", new JSDOC.DocComment("/**"+properties[i].desc+"\n@name "+properties[i].name+"\n@memberOf "+this.alias+"#*/"));
 629             // TODO: shouldn't the following happen in the addProperty method of Symbol?
 630             property.name = properties[i].name;
 631             property.memberOf = this.alias;
 632             if (properties[i].type) property.type = properties[i].type;
 633             if (properties[i].defaultValue) property.defaultValue = properties[i].defaultValue;
 634             this.addProperty(property);
 635             JSDOC.Parser.addSymbol(property);
 636         }
 637     }
 638     
 639     /*t:
 640         // todo
 641     */
 642 
 643     // @return
 644     var returns = this.comment.getTag("return");
 645     if (returns.length) { // there can be many return tags in a single doclet
 646         this.returns = returns;
 647         this.type = returns.map(function($){return $.type}).join(", ");
 648     }
 649     
 650     /*t:
 651         // todo
 652     */
 653     
 654     // @exception
 655     this.exceptions = this.comment.getTag("throws");
 656     
 657     /*t:
 658         // todo
 659     */
 660     
 661     // @requires
 662     var requires = this.comment.getTag("requires");
 663     if (requires.length) {
 664         this.requires = requires.map(function($){return $.desc});
 665     }
 666     
 667     /*t:
 668         // todo
 669     */
 670     
 671     // @type
 672     var types = this.comment.getTag("type");
 673     if (types.length) {
 674         this.type = types[0].desc; //multiple type tags are ignored
 675     }
 676     
 677     /*t:
 678         // todo
 679     */
 680     
 681     // @private
 682     if (this.comment.getTag("private").length || this.isInner) {
 683         this.isPrivate = true;
 684     }
 685     
 686     // @ignore
 687     if (this.comment.getTag("ignore").length) {
 688         this.isIgnored = true;
 689     }
 690     
 691     /*t:
 692         // todo
 693     */
 694     
 695     // @inherits ... as ...
 696     var inherits = this.comment.getTag("inherits");
 697     if (inherits.length) {
 698         for (var i = 0; i < inherits.length; i++) {
 699             if (/^\s*([a-z$0-9_.#:-]+)(?:\s+as\s+([a-z$0-9_.#:-]+))?/i.test(inherits[i].desc)) {
 700                 var inAlias = RegExp.$1;
 701                 var inAs = RegExp.$2 || inAlias;
 702 
 703                 if (inAlias) inAlias = inAlias.replace(/\.prototype\.?/g, "#");
 704                 
 705                 if (inAs) {
 706                     inAs = inAs.replace(/\.prototype\.?/g, "#");
 707                     inAs = inAs.replace(/^this\.?/, "#");
 708                 }
 709 
 710                 if (inAs.indexOf(inAlias) != 0) { //not a full namepath
 711                     var joiner = ".";
 712                     if (this.alias.charAt(this.alias.length-1) == "#" || inAs.charAt(0) == "#") {
 713                         joiner = "";
 714                     }
 715                     inAs = this.alias + joiner + inAs;
 716                 }
 717             }
 718             this.inherits.push({alias: inAlias, as: inAs});
 719         }
 720     }
 721     
 722     /*t:
 723         // todo
 724     */
 725     
 726     // @augments
 727     this.augments = this.comment.getTag("augments");
 728     
 729     // @default
 730     var defaults = this.comment.getTag("default");
 731     if (defaults.length) {
 732         if (this.is("OBJECT")) {
 733             this.defaultValue = defaults[0].desc;
 734         }
 735     }
 736     
 737     /*t:
 738         // todo
 739     */
 740     
 741     // @memberOf
 742     var memberOfs = this.comment.getTag("memberOf");
 743     if (memberOfs.length) {
 744         this.memberOf = memberOfs[0].desc;
 745         this.memberOf = this.memberOf.replace(/\.prototype\.?/g, "#");
 746     }
 747 
 748     /*t:
 749         // todo
 750     */
 751     
 752     // @public
 753     if (this.comment.getTag("public").length) {
 754         this.isPrivate = false;
 755     }
 756     
 757     /*t:
 758         // todo
 759     */
 760         
 761     if (JSDOC.PluginManager) {
 762         JSDOC.PluginManager.run("onSetTags", this);
 763     }
 764 }
 765 
 766 /**
 767  * 引数で指定したシンボル種別文字列が[[isa]]プロパティの値と一致していればtrueを返します。
 768  * @param {String} what シンボル種別
 769  * @return {Boolean} 引数とシンボル種別が一致していればtrue、そうでなければfalse
 770  * @see JSDOC.Symbol#isa
 771  */
 772 JSDOC.Symbol.prototype.is = function(what) {
 773     return this.isa === what;
 774 }
 775 
 776 /**
 777  * このシンボルがJavaScriptの組み込み関数やオブジェクトを表していればtrueを返します。
 778  * @return {Boolean} このシンボルがJavaScriptの組み込み関数やオブジェクトならtrue、そうでなければfalse
 779  */
 780 JSDOC.Symbol.prototype.isBuiltin = function() {
 781     return JSDOC.Lang.isBuiltin(this.alias);
 782 }
 783 
 784 /** @ignore */
 785 JSDOC.Symbol.prototype.setType = function(/**String*/comment, /**Boolean*/overwrite) {
 786     if (!overwrite && this.type) return;
 787     var typeComment = JSDOC.DocComment.unwrapComment(comment);
 788     this.type = typeComment;
 789 }
 790 
 791 /** @ignore */
 792 JSDOC.Symbol.prototype.inherit = function(symbol) {
 793     if (!this.hasMember(symbol.name) && !symbol.isInner) {
 794         if (symbol.is("FUNCTION"))
 795             this.methods.push(symbol);
 796         else if (symbol.is("OBJECT"))
 797             this.properties.push(symbol);
 798     }
 799 }
 800 
 801 /**
 802  * 引数で指定された名前かエイリアスのシンボルをメンバに持っていればtrueを返します。
 803  * @param {String} name シンボルの名前またはエイリアス
 804  * @return {Boolean} シンボルをメンバに持っていればtrue、そうでなければfalse
 805  */
 806 JSDOC.Symbol.prototype.hasMember = function(name) {
 807     return (this.hasMethod(name) || this.hasProperty(name));
 808 }
 809 
 810 /**
 811  * このシンボルにメンバを追加します。 
 812  * 追加しようとするシンボルの種別によって、メソッドかプロパティかが自動的に判定されます。
 813  * @param {JSDOC.Symbol} symbol メンバとして追加するシンボル
 814  */
 815 JSDOC.Symbol.prototype.addMember = function(symbol) {
 816     if (symbol.is("FUNCTION")) { this.addMethod(symbol); }
 817     else if (symbol.is("OBJECT")) { this.addProperty(symbol); }
 818 }
 819 
 820 /**
 821  * 引数で指定された名前かエイリアスのメソッドを持っていればtrueを返します。
 822  * @param {String} name シンボルの名前またはエイリアス
 823  * @return {Boolean} シンボルをメソッドに持っていればtrue、そうでなければfalse
 824  */
 825 JSDOC.Symbol.prototype.hasMethod = function(name) {
 826     var thisMethods = this.methods;
 827     for (var i = 0, l = thisMethods.length; i < l; i++) {
 828         if (thisMethods[i].name == name) return true;
 829         if (thisMethods[i].alias == name) return true;
 830     }
 831     return false;
 832 }
 833 
 834 /**
 835  * このシンボルにメソッドを追加します。
 836  * 同名のメソッドが既に存在する場合、新しいシンボルで上書きされます。
 837  * @param {JSDOC.Symbol} symbol メソッドとして追加するシンボル
 838  */
 839 JSDOC.Symbol.prototype.addMethod = function(symbol) {
 840     var methodAlias = symbol.alias;
 841     var thisMethods = this.methods;
 842     for (var i = 0, l = thisMethods.length; i < l; i++) {
 843         if (thisMethods[i].alias == methodAlias) {
 844             thisMethods[i] = symbol; // overwriting previous method
 845             return;
 846         }
 847     }
 848     thisMethods.push(symbol); // new method with this alias
 849 }
 850 
 851 /**
 852  * 引数で指定された名前かエイリアスのプロパティを持っていればtrueを返します。
 853  * @param {String} name シンボルの名前またはエイリアス
 854  * @return {Boolean} シンボルをプロパティに持っていればtrue、そうでなければfalse
 855  */
 856 JSDOC.Symbol.prototype.hasProperty = function(name) {
 857     var thisProperties = this.properties;
 858     for (var i = 0, l = thisProperties.length; i < l; i++) {
 859         if (thisProperties[i].name == name) return true;
 860         if (thisProperties[i].alias == name) return true;
 861     }
 862     return false;
 863 }
 864 
 865 /**
 866  * このシンボルにプロパティを追加します。
 867  * 同名のプロパティが既に存在する場合、新しいシンボルで上書きされます。
 868  * @param {JSDOC.Symbol} symbol プロパティとして追加するシンボル
 869  */
 870 JSDOC.Symbol.prototype.addProperty = function(symbol) {
 871     var propertyAlias = symbol.alias;
 872     var thisProperties = this.properties;
 873     for (var i = 0, l = thisProperties.length; i < l; i++) {
 874         if (thisProperties[i].alias == propertyAlias) {
 875             thisProperties[i] = symbol; // overwriting previous property
 876             return;
 877         }
 878     }
 879 
 880     thisProperties.push(symbol); // new property with this alias
 881 }
 882 
 883 JSDOC.Symbol.srcFile = ""; //running reference to the current file being parsed
 884