can generate jsdoc; private methods marked as such
[dygraphs.git] / jsdoc-toolkit / app / lib / JSDOC / SymbolSet.js
diff --git a/jsdoc-toolkit/app/lib/JSDOC/SymbolSet.js b/jsdoc-toolkit/app/lib/JSDOC/SymbolSet.js
new file mode 100644 (file)
index 0000000..8e3a2eb
--- /dev/null
@@ -0,0 +1,243 @@
+/** @constructor */
+JSDOC.SymbolSet = function() {
+       this.init();
+}
+
+JSDOC.SymbolSet.prototype.init = function() {
+       this._index = new Hash();
+}
+
+JSDOC.SymbolSet.prototype.keys = function() {
+       return this._index.keys();
+}
+
+JSDOC.SymbolSet.prototype.hasSymbol = function(alias) {
+       return this._index.hasKey(alias);
+}
+
+JSDOC.SymbolSet.prototype.addSymbol = function(symbol) {
+       if (JSDOC.opt.a && this.hasSymbol(symbol.alias)) {
+               LOG.warn("Overwriting symbol documentation for: " + symbol.alias + ".");
+               this.deleteSymbol(symbol.alias);
+       }
+       this._index.set(symbol.alias, symbol);
+}
+
+JSDOC.SymbolSet.prototype.getSymbol = function(alias) {
+       if (this.hasSymbol(alias)) return this._index.get(alias);
+}
+
+JSDOC.SymbolSet.prototype.getSymbolByName = function(name) {
+       for (var p = this._index.first(); p; p = this._index.next()) {
+               var symbol = p.value;
+               if (symbol.name == name) return symbol;
+       }
+}
+
+JSDOC.SymbolSet.prototype.toArray = function() {
+       return this._index.values();
+}
+
+JSDOC.SymbolSet.prototype.deleteSymbol = function(alias) {
+       if (!this.hasSymbol(alias)) return;
+       this._index.drop(alias);
+}
+
+JSDOC.SymbolSet.prototype.renameSymbol = function(oldName, newName) {
+       // todo: should check if oldname or newname already exist
+       this._index.replace(oldName, newName);
+       this._index.get(newName).alias = newName;
+       return newName;
+}
+
+JSDOC.SymbolSet.prototype.relate = function() {
+       this.resolveBorrows();
+       this.resolveMemberOf();
+       this.resolveAugments();
+}
+
+JSDOC.SymbolSet.prototype.resolveBorrows = function() {
+       for (var p = this._index.first(); p; p = this._index.next()) {
+               var symbol = p.value;
+               if (symbol.is("FILE") || symbol.is("GLOBAL")) continue;
+               
+               var borrows = symbol.inherits;
+               for (var i = 0; i < borrows.length; i++) {
+               
+if (/#$/.test(borrows[i].alias)) {
+       LOG.warn("Attempted to borrow entire instance of "+borrows[i].alias+" but that feature is not yet implemented.");
+       return;
+}
+                       var borrowed = this.getSymbol(borrows[i].alias);
+                       
+                       if (!borrowed) {
+                               LOG.warn("Can't borrow undocumented "+borrows[i].alias+".");
+                               continue;
+                       }
+
+                       if (borrows[i].as == borrowed.alias) {
+                               var assumedName = borrowed.name.split(/([#.-])/).pop();
+                               borrows[i].as = symbol.name+RegExp.$1+assumedName;
+                               LOG.inform("Assuming borrowed as name is "+borrows[i].as+" but that feature is experimental.");
+                       }
+                       
+                       var borrowAsName = borrows[i].as;
+                       var borrowAsAlias = borrowAsName;
+                       if (!borrowAsName) {
+                               LOG.warn("Malformed @borrow, 'as' is required.");
+                               continue;
+                       }
+                       
+                       if (borrowAsName.length > symbol.alias.length && borrowAsName.indexOf(symbol.alias) == 0) {
+                               borrowAsName = borrowAsName.replace(borrowed.alias, "")
+                       }
+                       else {
+                               var joiner = "";
+                               if (borrowAsName.charAt(0) != "#") joiner = ".";
+                               borrowAsAlias = borrowed.alias + joiner + borrowAsName;
+                       }
+                       
+                       borrowAsName = borrowAsName.replace(/^[#.]/, "");
+                                       
+                       if (this.hasSymbol(borrowAsAlias)) continue;
+
+                       var clone = borrowed.clone();
+                       clone.name = borrowAsName;
+                       clone.alias = borrowAsAlias;
+                       this.addSymbol(clone);
+               }
+       }
+}
+
+JSDOC.SymbolSet.prototype.resolveMemberOf = function() {
+       for (var p = this._index.first(); p; p = this._index.next()) {
+               var symbol = p.value;
+
+               if (symbol.is("FILE") || symbol.is("GLOBAL")) continue;
+               
+               // the memberOf value was provided in the @memberOf tag
+               else if (symbol.memberOf) {                     
+                       // like foo.bar is a memberOf foo
+                       if (symbol.alias.indexOf(symbol.memberOf) == 0) {
+                               var memberMatch = new RegExp("^("+symbol.memberOf+")[.#-]?(.+)$");
+                               var aliasParts = symbol.alias.match(memberMatch);
+                               
+                               if (aliasParts) {
+                                       symbol.memberOf = aliasParts[1];
+                                       symbol.name = aliasParts[2];
+                               }
+                               
+                               var nameParts = symbol.name.match(memberMatch);
+
+                               if (nameParts) {
+                                       symbol.name = nameParts[2];
+                               }
+                       }
+                       // like bar is a memberOf foo
+                       else {
+                               var joiner = symbol.memberOf.charAt(symbol.memberOf.length-1);
+                               if (!/[.#-]/.test(joiner)) symbol.memberOf += ".";
+                               this.renameSymbol(symbol.alias, symbol.memberOf + symbol.name);
+                       }
+               }
+               // the memberOf must be calculated
+               else {
+                       var parts = symbol.alias.match(/^(.*[.#-])([^.#-]+)$/);
+
+                       if (parts) {
+                               symbol.memberOf = parts[1];
+                               symbol.name = parts[2];                         
+                       }
+               }
+
+               // set isStatic, isInner
+               if (symbol.memberOf) {
+                       switch (symbol.memberOf.charAt(symbol.memberOf.length-1)) {
+                               case '#' :
+                                       symbol.isStatic = false;
+                                       symbol.isInner = false;
+                               break;
+                               case '.' :
+                                       symbol.isStatic = true;
+                                       symbol.isInner = false;
+                               break;
+                               case '-' :
+                                       symbol.isStatic = false;
+                                       symbol.isInner = true;
+                               break;
+                               default: // memberOf ends in none of the above
+                                       symbol.isStatic = true;
+                               break;
+                       }
+               }
+               
+               // unowned methods and fields belong to the global object
+               if (!symbol.is("CONSTRUCTOR") && !symbol.isNamespace && symbol.memberOf == "") {
+                       symbol.memberOf = "_global_";
+               }
+
+               // clean up
+               if (symbol.memberOf.match(/[.#-]$/)) {
+                       symbol.memberOf = symbol.memberOf.substr(0, symbol.memberOf.length-1);
+               }
+               // add to parent's methods or properties list
+               if (symbol.memberOf) {
+
+                       var container = this.getSymbol(symbol.memberOf);
+                       if (!container) {
+                               if (JSDOC.Lang.isBuiltin(symbol.memberOf)) container = JSDOC.Parser.addBuiltin(symbol.memberOf);
+                               else {
+                                       LOG.warn("Trying to document "+symbol.name +" as a member of undocumented symbol "+symbol.memberOf+".");
+                               }
+                       }
+                       
+                       if (container) container.addMember(symbol);
+               }
+       }
+}
+
+JSDOC.SymbolSet.prototype.resolveAugments = function() {
+       for (var p = this._index.first(); p; p = this._index.next()) {
+               var symbol = p.value;
+               
+               if (symbol.alias == "_global_" || symbol.is("FILE")) continue;
+               JSDOC.SymbolSet.prototype.walk.apply(this, [symbol]);
+       }
+}
+
+JSDOC.SymbolSet.prototype.walk = function(symbol) {
+       var augments = symbol.augments;
+       for(var i = 0; i < augments.length; i++) {
+               var contributer = this.getSymbol(augments[i]);
+               if (!contributer && JSDOC.Lang.isBuiltin(''+augments[i])) {
+                       contributer = new JSDOC.Symbol("_global_."+augments[i], [], augments[i], new JSDOC.DocComment("Built in."));
+                       contributer.isNamespace = true;
+                       contributer.srcFile = "";
+                       contributer.isPrivate = false;
+                       JSDOC.Parser.addSymbol(contributer);
+               }
+               
+               if (contributer) {                      
+                       if (contributer.augments.length) {
+                               JSDOC.SymbolSet.prototype.walk.apply(this, [contributer]);
+                       }
+                       
+                       symbol.inheritsFrom.push(contributer.alias);
+                       //if (!isUnique(symbol.inheritsFrom)) {
+                       //      LOG.warn("Can't resolve augments: Circular reference: "+symbol.alias+" inherits from "+contributer.alias+" more than once.");
+                       //}
+                       //else {
+                               var cmethods = contributer.methods;
+                               var cproperties = contributer.properties;
+                               
+                               for (var ci = 0, cl = cmethods.length; ci < cl; ci++) {
+                                       if (!cmethods[ci].isStatic) symbol.inherit(cmethods[ci]);
+                               }
+                               for (var ci = 0, cl = cproperties.length; ci < cl; ci++) {
+                                       if (!cproperties[ci].isStatic) symbol.inherit(cproperties[ci]);
+                               }       
+                       //}
+               }
+               else LOG.warn("Can't augment contributer: "+augments[i]+", not found.");
+       }
+}