object.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. "use strict";
  2. module.exports = ReflectionObject;
  3. ReflectionObject.className = "ReflectionObject";
  4. var util = require("./util");
  5. var Root; // cyclic
  6. /**
  7. * Constructs a new reflection object instance.
  8. * @classdesc Base class of all reflection objects.
  9. * @constructor
  10. * @param {string} name Object name
  11. * @param {Object.<string,*>} [options] Declared options
  12. * @abstract
  13. */
  14. function ReflectionObject(name, options) {
  15. if (!util.isString(name))
  16. throw TypeError("name must be a string");
  17. if (options && !util.isObject(options))
  18. throw TypeError("options must be an object");
  19. /**
  20. * Options.
  21. * @type {Object.<string,*>|undefined}
  22. */
  23. this.options = options; // toJSON
  24. /**
  25. * Unique name within its namespace.
  26. * @type {string}
  27. */
  28. this.name = name;
  29. /**
  30. * Parent namespace.
  31. * @type {Namespace|null}
  32. */
  33. this.parent = null;
  34. /**
  35. * Whether already resolved or not.
  36. * @type {boolean}
  37. */
  38. this.resolved = false;
  39. /**
  40. * Comment text, if any.
  41. * @type {string|null}
  42. */
  43. this.comment = null;
  44. /**
  45. * Defining file name.
  46. * @type {string|null}
  47. */
  48. this.filename = null;
  49. }
  50. Object.defineProperties(ReflectionObject.prototype, {
  51. /**
  52. * Reference to the root namespace.
  53. * @name ReflectionObject#root
  54. * @type {Root}
  55. * @readonly
  56. */
  57. root: {
  58. get: function() {
  59. var ptr = this;
  60. while (ptr.parent !== null)
  61. ptr = ptr.parent;
  62. return ptr;
  63. }
  64. },
  65. /**
  66. * Full name including leading dot.
  67. * @name ReflectionObject#fullName
  68. * @type {string}
  69. * @readonly
  70. */
  71. fullName: {
  72. get: function() {
  73. var path = [ this.name ],
  74. ptr = this.parent;
  75. while (ptr) {
  76. path.unshift(ptr.name);
  77. ptr = ptr.parent;
  78. }
  79. return path.join(".");
  80. }
  81. }
  82. });
  83. /**
  84. * Converts this reflection object to its descriptor representation.
  85. * @returns {Object.<string,*>} Descriptor
  86. * @abstract
  87. */
  88. ReflectionObject.prototype.toJSON = /* istanbul ignore next */ function toJSON() {
  89. throw Error(); // not implemented, shouldn't happen
  90. };
  91. /**
  92. * Called when this object is added to a parent.
  93. * @param {ReflectionObject} parent Parent added to
  94. * @returns {undefined}
  95. */
  96. ReflectionObject.prototype.onAdd = function onAdd(parent) {
  97. if (this.parent && this.parent !== parent)
  98. this.parent.remove(this);
  99. this.parent = parent;
  100. this.resolved = false;
  101. var root = parent.root;
  102. if (root instanceof Root)
  103. root._handleAdd(this);
  104. };
  105. /**
  106. * Called when this object is removed from a parent.
  107. * @param {ReflectionObject} parent Parent removed from
  108. * @returns {undefined}
  109. */
  110. ReflectionObject.prototype.onRemove = function onRemove(parent) {
  111. var root = parent.root;
  112. if (root instanceof Root)
  113. root._handleRemove(this);
  114. this.parent = null;
  115. this.resolved = false;
  116. };
  117. /**
  118. * Resolves this objects type references.
  119. * @returns {ReflectionObject} `this`
  120. */
  121. ReflectionObject.prototype.resolve = function resolve() {
  122. if (this.resolved)
  123. return this;
  124. if (this.root instanceof Root)
  125. this.resolved = true; // only if part of a root
  126. return this;
  127. };
  128. /**
  129. * Gets an option value.
  130. * @param {string} name Option name
  131. * @returns {*} Option value or `undefined` if not set
  132. */
  133. ReflectionObject.prototype.getOption = function getOption(name) {
  134. if (this.options)
  135. return this.options[name];
  136. return undefined;
  137. };
  138. /**
  139. * Sets an option.
  140. * @param {string} name Option name
  141. * @param {*} value Option value
  142. * @param {boolean} [ifNotSet] Sets the option only if it isn't currently set
  143. * @returns {ReflectionObject} `this`
  144. */
  145. ReflectionObject.prototype.setOption = function setOption(name, value, ifNotSet) {
  146. if (!ifNotSet || !this.options || this.options[name] === undefined)
  147. (this.options || (this.options = {}))[name] = value;
  148. return this;
  149. };
  150. /**
  151. * Sets multiple options.
  152. * @param {Object.<string,*>} options Options to set
  153. * @param {boolean} [ifNotSet] Sets an option only if it isn't currently set
  154. * @returns {ReflectionObject} `this`
  155. */
  156. ReflectionObject.prototype.setOptions = function setOptions(options, ifNotSet) {
  157. if (options)
  158. for (var keys = Object.keys(options), i = 0; i < keys.length; ++i)
  159. this.setOption(keys[i], options[keys[i]], ifNotSet);
  160. return this;
  161. };
  162. /**
  163. * Converts this instance to its string representation.
  164. * @returns {string} Class name[, space, full name]
  165. */
  166. ReflectionObject.prototype.toString = function toString() {
  167. var className = this.constructor.className,
  168. fullName = this.fullName;
  169. if (fullName.length)
  170. return className + " " + fullName;
  171. return className;
  172. };
  173. // Sets up cyclic dependencies (called in index-light)
  174. ReflectionObject._configure = function(Root_) {
  175. Root = Root_;
  176. };