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

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