/branches/version1.x/app/Symbol.js

http://jsdoc-toolkit.googlecode.com/ · JavaScript · 332 lines · 276 code · 40 blank · 16 comment · 102 complexity · dbf52447276f6d541ed265086820be7a MD5 · raw file

  1. /**
  2. * @fileOverview
  3. * @name Symbol
  4. * @author Michael Mathews micmath@gmail.com
  5. * @url $HeadURL: http://jsdoc-toolkit.googlecode.com/svn/branches/version1.x/app/Symbol.js $
  6. * @revision $Id: Symbol.js 420 2008-01-16 22:59:24Z micmath $
  7. * @license <a href="http://en.wikipedia.org/wiki/MIT_License">X11/MIT License</a>
  8. * (See the accompanying README file for full details.)
  9. */
  10. SYM = {
  11. OBJECT: "OBJECT",
  12. FUNCTION: "FUNCTION",
  13. CONSTRUCTOR: "CONSTRUCTOR",
  14. VIRTUAL: "VIRTUAL",
  15. EVENT: "EVENT"
  16. };
  17. RegExp.escapeMeta = function(str) {
  18. return str.replace(/([$^\\\/()|?+*\[\]{}.-])/g, "\\$1");
  19. }
  20. /**
  21. @class Represents an atomic unit of code.
  22. @constructor
  23. */
  24. function Symbol(name, params, isa, comment) {
  25. if (isa == "META") {
  26. if (comment.indexOf("/**#@+") == 0) { // start of shared doclet
  27. Symbol.shared = Doclet.unwrapComment(comment.replace("/**#@+", "/**"));
  28. }
  29. else if (comment.indexOf("/**#=+") == 0) { // start of shortcut doclet
  30. eval('Symbol.shortcuts = '+Doclet.unwrapComment(comment).replace('#=+', '').replace(/[\n\r\f]/g, ' '));
  31. }
  32. else if (comment.indexOf("/**#=-") == 0) { // end of shortcut doclet
  33. Symbol.shortcuts = {};
  34. }
  35. else if (comment.indexOf("/**#@-") == 0) { // end of shared doclet
  36. Symbol.shared = "";
  37. }
  38. return;
  39. }
  40. comment = Symbol.shared+"\n"+Doclet.unwrapComment(comment);
  41. for (var n in Symbol.shortcuts) {
  42. var pat = RegExp.escapeMeta(n);
  43. var re = new RegExp("^"+pat+"\\b");
  44. name = name.replace(re, Symbol.shortcuts[n]);
  45. }
  46. name = name.replace(/\.prototype\.?/, '/');
  47. this.name = name;
  48. this.params = (params || []);
  49. this.isa = (isa || SYM.OBJECT);
  50. this.type = "";
  51. this.alias = name;
  52. this.desc = "";
  53. this.classDesc = "";
  54. this.memberof = "";
  55. this.since = "";
  56. this.version = "";
  57. this.deprecated = "";
  58. this.augments = [];
  59. this.inherits = [];
  60. this._inheritsFrom = [];
  61. this.properties = [];
  62. this.methods = [];
  63. this.file = {};
  64. this.returns = [];
  65. this.exceptions = [];
  66. this.events = [];
  67. this.doc = new Doclet(comment);
  68. this.comment = comment;
  69. this.see = [];
  70. // move certain data out of the tags and into the Symbol
  71. var overviews;
  72. if ((overviews = this.doc.getTag("overview")) && overviews.length) {
  73. var libraries;
  74. if ((libraries = this.doc.getTag("name")) && libraries.length) {
  75. this.name = libraries[0].desc;
  76. this.doc._dropTag("name");
  77. }
  78. else {
  79. this.name = Util.fileName(this.alias)
  80. }
  81. this.desc = overviews[0].desc;
  82. this.doc._dropTag("overview");
  83. }
  84. else {
  85. var since;
  86. if ((since = this.doc.getTag("since")) && since.length) {
  87. this.since = since[0].desc;
  88. }
  89. var version;
  90. if ((version = this.doc.getTag("version")) && version.length) {
  91. this.version = version[0].desc;
  92. }
  93. var deprecated;
  94. if ((deprecated = this.doc.getTag("deprecated")) && deprecated.length) {
  95. this.deprecated = deprecated[0];
  96. this.doc._dropTag("deprecated");
  97. }
  98. var see;
  99. if ((see = this.doc.getTag("see")) && version.length) {
  100. this.see = see;
  101. this.doc._dropTag("see");
  102. }
  103. var descs;
  104. if ((descs = this.doc.getTag("desc")) && descs.length) {
  105. this.desc = descs.join("\n"); // multiple descriptions are concatenated into one
  106. this.doc._dropTag("desc");
  107. }
  108. var params;
  109. if ((params = this.doc.getTag("param")) && params.length) { // user defined params override those defined by parser
  110. this.params = params;
  111. this.doc._dropTag("param");
  112. }
  113. else { // promote parser params into DocTag objects
  114. for (var i = 0; i < this.params.length; i++) {
  115. this.params[i] = new DocTag("param "+this.params[i]);
  116. }
  117. }
  118. var constructors;
  119. if ((constructors = this.doc.getTag("constructor")) && constructors.length) {
  120. this.isa = SYM.CONSTRUCTOR;
  121. this.doc._dropTag("constructor");
  122. }
  123. var functions;
  124. if ((functions = this.doc.getTag("function")) && functions.length) {
  125. this.isa = SYM.FUNCTION;
  126. this.doc._dropTag("function");
  127. }
  128. var events;
  129. if ((events = this.doc.getTag("event")) && events.length) {
  130. this.isa = SYM.EVENT;
  131. this.doc._dropTag("event");
  132. }
  133. var methods;
  134. if ((functions = this.doc.getTag("method")) && functions.length) {
  135. this.isa = SYM.FUNCTION;
  136. this.doc._dropTag("method");
  137. }
  138. var names;
  139. if ((names = this.doc.getTag("name")) && names.length) {
  140. this.name = names[0].desc;
  141. this.doc._dropTag("name");
  142. }
  143. var properties;
  144. if ((properties = this.doc.getTag("property")) && properties.length) {
  145. for (var i = 0; i < properties.length; i++) {
  146. properties[i].alias = this.alias+"."+properties[i].name;
  147. this.properties.push(properties[i]);
  148. }
  149. this.doc._dropTag("property");
  150. }
  151. var returns;
  152. if ((returns = this.doc.getTag("return")) && returns.length) {
  153. for (var i = 0; i < returns.length; i++) {
  154. this.returns.push(returns[i]);
  155. }
  156. this.doc._dropTag("return");
  157. }
  158. var exceptions;
  159. if ((exceptions = this.doc.getTag("throws")) && exceptions.length) {
  160. for (var i = 0; i < exceptions.length; i++) {
  161. this.exceptions.push(exceptions[i]);
  162. }
  163. this.doc._dropTag("throws");
  164. }
  165. if (this.is("VIRTUAL")) this.isa = SYM.OBJECT;
  166. var types;
  167. if ((types = this.doc.getTag("type")) && types.length) {
  168. if (this.is("OBJECT"))
  169. this.type = (types[0].desc || ""); // multiple type tags are ignored
  170. this.doc._dropTag("type");
  171. }
  172. if (this.doc.getTag("static").length > 0) {
  173. this.isStatic = true;
  174. this.doc._dropTag("static");
  175. }
  176. if (this.doc.getTag("private").length > 0) {
  177. this.isPrivate = true;
  178. this.doc._dropTag("private");
  179. }
  180. var classes;
  181. if ((classes = this.doc.getTag("class")) && classes.length) {
  182. if (this.doc.getTag("static").length > 0) this.isStatic = true;
  183. this.isa = "CONSTRUCTOR"; // a class tag implies a conctuctor doclet
  184. this.classDesc += "\n"+classes[0].desc; // multiple class tags are concatenated
  185. }
  186. var inherits;
  187. if ((inherits = this.doc.getTag("inherits")) && inherits.length) {
  188. for (var i = 0; i < inherits.length; i++) {
  189. if (/^\s*([a-z$0-9_.#]+)(?:\s+as\s+([a-z$0-9_.#]+))?/i.test(inherits[i].desc)) {
  190. var inAlias = RegExp.$1;
  191. var inAs = RegExp.$2 || inAlias;
  192. if (inAs.indexOf(this.alias) != 0) {
  193. inAs = this.alias+"."+inAs;
  194. }
  195. inAs = inAs.replace(/\.this\.?/, "/");
  196. }
  197. this.inherits.push({alias: inAlias, as: inAs});
  198. }
  199. this.doc._dropTag("inherits");
  200. }
  201. var augments;
  202. if ((augments = this.doc.getTag("augments")) && augments.length) {
  203. for (var i = 0; i < augments.length; i++) {
  204. this.augments.push(augments[i].desc);
  205. }
  206. this.doc._dropTag("augments");
  207. }
  208. Symbol.index[this.alias] = this;
  209. }
  210. }
  211. Symbol.shared = ""; // holds shared doclets
  212. Symbol.shortcuts = {}; // holds map of shortcut names to full names
  213. Symbol.index = {};
  214. Symbol.builtins = ['Array', 'Boolean', 'Date', 'Function', 'Math', 'Number', 'Object', 'RegExp', 'String'];
  215. Symbol.prototype.is = function(what) {
  216. return this.isa === SYM[what];
  217. }
  218. /** Generate a comma separated list of the parameters. */
  219. Symbol.prototype.signature = function() {
  220. var result = [];
  221. for (var i = 0; i < this.params.length; i++) {
  222. if (this.params[i].name.indexOf(".") == -1) // config information does not appear in the signature
  223. result.push(this.params[i].name);
  224. }
  225. return result.join(", ");
  226. }
  227. Symbol.prototype.hasMethod = function(name) {
  228. for (var i = 0; i < this.methods.length; i++) {
  229. if (this.methods[i].name == name) return true
  230. }
  231. return false;
  232. }
  233. Symbol.prototype.hasEvent = function(name) {
  234. for (var i = 0; i < this.events.length; i++) {
  235. if (this.events[i].name == name) return true
  236. }
  237. return false;
  238. }
  239. Symbol.prototype.hasProperty = function(name) {
  240. for (var i = 0; i < this.properties.length; i++) {
  241. if (this.properties[i].name == name) return true
  242. }
  243. return false;
  244. }
  245. function isUnique(arr) {
  246. var l = arr.length;
  247. for(var i = 0; i < l; i++ ) {
  248. if (arr.lastIndexOf(arr[i]) > i) return false;
  249. }
  250. return true;
  251. }
  252. Symbol.prototype.getInheritedMethods = function(r) {
  253. var result = this.methods;
  254. for(var i = 0; i < this.augments.length; i++) {
  255. var contributer = this.file.fileGroup.getSymbol(this.augments[i]);
  256. if (contributer) {
  257. this._inheritsFrom.push(contributer.alias);
  258. if (!isUnique(this._inheritsFrom)) {
  259. LOG.warn("Circular reference: "+this.alias+" inherits from the same symbol more than once.");
  260. }
  261. else {
  262. result = result.concat(contributer.getInheritedMethods(true));
  263. this._inheritsFrom = [];
  264. }
  265. }
  266. }
  267. // remove overridden
  268. for (var i = 0; i < result.length; i++) {
  269. var j = i;
  270. while (++j < result.length) {
  271. if (result[j].name == result[i].name) result.splice(j, 1);
  272. }
  273. }
  274. if (!r) { // not recursing
  275. var s = this;
  276. function notLocal(element, index, array) {
  277. return (!s.hasMethod(element.name));
  278. }
  279. result = result.filter(notLocal);
  280. }
  281. return result;
  282. }
  283. Symbol.prototype.clone = function() {
  284. var dop = new Symbol(this.name, [], this.isa, this.comment);
  285. for (var i in this.params) {
  286. for (var j in this.params[i]) {
  287. if (this.params[i][j].constructor == String)
  288. dop.params[i][j] = this.params[i][j];
  289. }
  290. }
  291. return dop;
  292. }