/tags/jsdoc_toolkit-2.2.1/jsdoc-toolkit/app/lib/JSDOC/SymbolSet.js

http://jsdoc-toolkit.googlecode.com/ · JavaScript · 241 lines · 189 code · 37 blank · 15 comment · 61 complexity · f1e65facae11d3bb5b0da8b2b13cb63c MD5 · raw file

  1. /** @constructor */
  2. JSDOC.SymbolSet = function() {
  3. this.init();
  4. }
  5. JSDOC.SymbolSet.prototype.init = function() {
  6. this._index = new Hash();
  7. }
  8. JSDOC.SymbolSet.prototype.keys = function() {
  9. return this._index.keys();
  10. }
  11. JSDOC.SymbolSet.prototype.hasSymbol = function(alias) {
  12. return this._index.hasKey(alias);
  13. }
  14. JSDOC.SymbolSet.prototype.addSymbol = function(symbol) {
  15. if (this.hasSymbol(symbol.alias)) {
  16. LOG.warn("Overwriting symbol documentation for: "+symbol.alias + ".");
  17. }
  18. this._index.set(symbol.alias, symbol);
  19. }
  20. JSDOC.SymbolSet.prototype.getSymbol = function(alias) {
  21. if (this.hasSymbol(alias)) return this._index.get(alias);
  22. }
  23. JSDOC.SymbolSet.prototype.getSymbolByName = function(name) {
  24. for (var p = this._index.first(); p; p = this._index.next()) {
  25. var symbol = p.value;
  26. if (symbol.name == name) return symbol;
  27. }
  28. }
  29. JSDOC.SymbolSet.prototype.toArray = function() {
  30. return this._index.values();
  31. }
  32. JSDOC.SymbolSet.prototype.deleteSymbol = function(alias) {
  33. if (!this.hasSymbol(alias)) return;
  34. this._index.drop(alias);
  35. }
  36. JSDOC.SymbolSet.prototype.renameSymbol = function(oldName, newName) {
  37. // todo: should check if oldname or newname already exist
  38. this._index.replace(oldName, newName);
  39. this._index.get(newName).alias = newName;
  40. return newName;
  41. }
  42. JSDOC.SymbolSet.prototype.relate = function() {
  43. this.resolveBorrows();
  44. this.resolveMemberOf();
  45. this.resolveAugments();
  46. }
  47. JSDOC.SymbolSet.prototype.resolveBorrows = function() {
  48. for (var p = this._index.first(); p; p = this._index.next()) {
  49. var symbol = p.value;
  50. if (symbol.is("FILE") || symbol.is("GLOBAL")) continue;
  51. var borrows = symbol.inherits;
  52. for (var i = 0; i < borrows.length; i++) {
  53. if (/#$/.test(borrows[i].alias)) {
  54. LOG.warn("Attempted to borrow entire instance of "+borrows[i].alias+" but that feature is not yet implemented.");
  55. return;
  56. }
  57. var borrowed = this.getSymbol(borrows[i].alias);
  58. if (!borrowed) {
  59. LOG.warn("Can't borrow undocumented "+borrows[i].alias+".");
  60. continue;
  61. }
  62. if (borrows[i].as == borrowed.alias) {
  63. var assumedName = borrowed.name.split(/([#.-])/).pop();
  64. borrows[i].as = symbol.name+RegExp.$1+assumedName;
  65. LOG.inform("Assuming borrowed as name is "+borrows[i].as+" but that feature is experimental.");
  66. }
  67. var borrowAsName = borrows[i].as;
  68. var borrowAsAlias = borrowAsName;
  69. if (!borrowAsName) {
  70. LOG.warn("Malformed @borrow, 'as' is required.");
  71. continue;
  72. }
  73. if (borrowAsName.length > symbol.alias.length && borrowAsName.indexOf(symbol.alias) == 0) {
  74. borrowAsName = borrowAsName.replace(borrowed.alias, "")
  75. }
  76. else {
  77. var joiner = "";
  78. if (borrowAsName.charAt(0) != "#") joiner = ".";
  79. borrowAsAlias = borrowed.alias + joiner + borrowAsName;
  80. }
  81. borrowAsName = borrowAsName.replace(/^[#.]/, "");
  82. if (this.hasSymbol(borrowAsAlias)) continue;
  83. var clone = borrowed.clone();
  84. clone.name = borrowAsName;
  85. clone.alias = borrowAsAlias;
  86. this.addSymbol(clone);
  87. }
  88. }
  89. }
  90. JSDOC.SymbolSet.prototype.resolveMemberOf = function() {
  91. for (var p = this._index.first(); p; p = this._index.next()) {
  92. var symbol = p.value;
  93. if (symbol.is("FILE") || symbol.is("GLOBAL")) continue;
  94. // the memberOf value was provided in the @memberOf tag
  95. else if (symbol.memberOf) {
  96. // like foo.bar is a memberOf foo
  97. if (symbol.alias.indexOf(symbol.memberOf) == 0) {
  98. var memberMatch = new RegExp("^("+symbol.memberOf+")[.#-]?(.+)$");
  99. var aliasParts = symbol.alias.match(memberMatch);
  100. if (aliasParts) {
  101. symbol.memberOf = aliasParts[1];
  102. symbol.name = aliasParts[2];
  103. }
  104. var nameParts = symbol.name.match(memberMatch);
  105. if (nameParts) {
  106. symbol.name = nameParts[2];
  107. }
  108. }
  109. // like bar is a memberOf foo
  110. else {
  111. var joiner = symbol.memberOf.charAt(symbol.memberOf.length-1);
  112. if (!/[.#-]/.test(joiner)) symbol.memberOf += ".";
  113. this.renameSymbol(symbol.alias, symbol.memberOf + symbol.name);
  114. }
  115. }
  116. // the memberOf must be calculated
  117. else {
  118. var parts = symbol.alias.match(/^(.*[.#-])([^.#-]+)$/);
  119. if (parts) {
  120. symbol.memberOf = parts[1];
  121. symbol.name = parts[2];
  122. }
  123. }
  124. // set isStatic, isInner
  125. if (symbol.memberOf) {
  126. switch (symbol.memberOf.charAt(symbol.memberOf.length-1)) {
  127. case '#' :
  128. symbol.isStatic = false;
  129. symbol.isInner = false;
  130. break;
  131. case '.' :
  132. symbol.isStatic = true;
  133. symbol.isInner = false;
  134. break;
  135. case '-' :
  136. symbol.isStatic = false;
  137. symbol.isInner = true;
  138. break;
  139. default: // memberOf ends in none of the above
  140. symbol.isStatic = true;
  141. break;
  142. }
  143. }
  144. // unowned methods and fields belong to the global object
  145. if (!symbol.is("CONSTRUCTOR") && !symbol.isNamespace && symbol.memberOf == "") {
  146. symbol.memberOf = "_global_";
  147. }
  148. // clean up
  149. if (symbol.memberOf.match(/[.#-]$/)) {
  150. symbol.memberOf = symbol.memberOf.substr(0, symbol.memberOf.length-1);
  151. }
  152. // add to parent's methods or properties list
  153. if (symbol.memberOf) {
  154. var container = this.getSymbol(symbol.memberOf);
  155. if (!container) {
  156. if (JSDOC.Lang.isBuiltin(symbol.memberOf)) container = JSDOC.Parser.addBuiltin(symbol.memberOf);
  157. else {
  158. LOG.warn("Trying to document "+symbol.name +" as a member of undocumented symbol "+symbol.memberOf+".");
  159. }
  160. }
  161. if (container) container.addMember(symbol);
  162. }
  163. }
  164. }
  165. JSDOC.SymbolSet.prototype.resolveAugments = function() {
  166. for (var p = this._index.first(); p; p = this._index.next()) {
  167. var symbol = p.value;
  168. if (symbol.alias == "_global_" || symbol.is("FILE")) continue;
  169. JSDOC.SymbolSet.prototype.walk.apply(this, [symbol]);
  170. }
  171. }
  172. JSDOC.SymbolSet.prototype.walk = function(symbol) {
  173. var augments = symbol.augments;
  174. for(var i = 0; i < augments.length; i++) {
  175. var contributer = this.getSymbol(augments[i]);
  176. if (!contributer && JSDOC.Lang.isBuiltin(''+augments[i])) {
  177. contributer = new JSDOC.Symbol("_global_."+augments[i], [], augments[i], new JSDOC.DocComment("Built in."));
  178. contributer.isNamespace = true;
  179. contributer.srcFile = "";
  180. contributer.isPrivate = false;
  181. JSDOC.Parser.addSymbol(contributer);
  182. }
  183. if (contributer) {
  184. if (contributer.augments.length) {
  185. JSDOC.SymbolSet.prototype.walk.apply(this, [contributer]);
  186. }
  187. symbol.inheritsFrom.push(contributer.alias);
  188. //if (!isUnique(symbol.inheritsFrom)) {
  189. // LOG.warn("Can't resolve augments: Circular reference: "+symbol.alias+" inherits from "+contributer.alias+" more than once.");
  190. //}
  191. //else {
  192. var cmethods = contributer.methods;
  193. var cproperties = contributer.properties;
  194. for (var ci = 0, cl = cmethods.length; ci < cl; ci++) {
  195. if (!cmethods[ci].isStatic) symbol.inherit(cmethods[ci]);
  196. }
  197. for (var ci = 0, cl = cproperties.length; ci < cl; ci++) {
  198. if (!cproperties[ci].isStatic) symbol.inherit(cproperties[ci]);
  199. }
  200. //}
  201. }
  202. else LOG.warn("Can't augment contributer: "+augments[i]+", not found.");
  203. }
  204. }