Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JSDoc object methods with @method or @property?

JSDoc 3's documentation includes this example:

/**
 * The complete Triforce, or one or more components of the Triforce.
 * @typedef {Object} WishGranter~Triforce
 * @property {boolean} hasCourage - Indicates whether the Courage component is present.
 * @property {boolean} hasPower - Indicates whether the Power component is present.
 * @property {boolean} hasWisdom - Indicates whether the Wisdom component is present.
 */

/**
 * A class for granting wishes, powered by the Triforce.
 * @class
 * @param {...WishGranter~Triforce} triforce - One to three {@link WishGranter~Triforce} objects
 * containing all three components of the Triforce.
 */
function WishGranter() {}

I am essentially creating a class that takes an object that implements an interface MessageQueueConnector, which should have one method connectAndSubscribe implemented. Since Javascript does not distinguish between member functions and member variables, it makes sense to use property, and JSDoc's documentation implies that @method is unrelated. However, method sound a lot more correct so I'm wondering if this is preferred, or if I'm just doing all of this wrong anyway (i.e. if there is a simpler way to document this situation in the first place, without creating a type).

like image 955
djechlin Avatar asked Apr 15 '14 22:04

djechlin


2 Answers

I'm currently using BOTH:

  • @tryAnyTag in the method comment, and
  • @property in the class comment
    • Since only method comments have namepaths (@property tags in class comments do not), we insert the namepath of the method comment as the description of the @property.

Example:

/** @module Example */

/**
 * @class module:Example.Car
 * @property {Function} start {@link module:Example.Car#start}
 * @property {Function} stop {@link module:Example.Car#stop}
 *
 */
class Car {

    /**
    * @method module:Example.Car#start
    *
    */
    function start () { /* function body */ }

    /**
    * @description You could use various other tags here, 
    * and JSDoc will still auto-assign the following namepath 
    * "module:Example.Car#stop" to this method
    *
    */
    function stop () { /* function body */ }
}

It's unfortunate that documenters have to pull double-duty because the JSDoc compiler doesn't automatically figure this out. At some point, there should be only one way to do this all at once - but it would imply breaking changes to the JSDoc compiler.

like image 35
jerng Avatar answered Sep 24 '22 19:09

jerng


@typedef is extremely limited in what it can do. You could define the methods as properties but then you would not be able to document parameters in the same way you would on a real class. What I've done to get around this limitation is to cheat. I use @class so that I can document it the way I want and put a warning that it is not a real class. So:

/**
 * @classdesc Not a real class but an interface. Etc...
 *
 * @name MessageQueueConnector
 * @class
 */

/**
 * This method does...
 *
 * @method
 * @name MessageQueueConnector#connectAndSubscribe
 * @param {string} whatever Whatever this is.
 * @returns {Object} Description of return value.
 * @throws {SomeException} blah.
 */

Note that the two doclets above do not need to have any associated JavaScript code. You don't need to create a fake class in JavaScript, you don't need to create a fake method, etc. This is why you need to use @name.

I don't like telling jsdoc that this is a class and then put in the doc that it is not but I found this to be the least objectionable way to get jsdoc to do what I want. I expect this workaround to become obsolete eventually as jsdoc evolves.

like image 91
Louis Avatar answered Sep 24 '22 19:09

Louis