How do I JSDoc A Nested Object's Methods?
I've been trying to use JSDoc3 to generate documentation on a file, but I'm having some difficulty. The file (which is a Require.js module) basically looks like this:
define([], function() {
/*
* @exports mystuff/foo
*/
var foo = {
/**
* @member
*/
bar: {
/**
* @method
*/
baz: function() { /*...*/ }
}
};
return foo;
}
The problem is, I can't get baz
to show up in the generated documentation. Instead I just get a documentation file for a foo/foo
module, which lists a bar
member, but bar
has no baz
(just a link to foo
's source code).
I've tried changing bar
's directive to @property
instead, and I've tried changing baz
's directive to @member
or @property
, but none of that helps. No matter what I do, baz just doesn't seem to want to show up.
Does anyone know what directive structure I could use to get baz to appear in the generated documentation?
P.S. I've tried reading pages like this one on the JSDoc site http://usejsdoc.org/howto-commonjs-modules.html, but it only describes cases of foo.bar
, not foo.bar.baz
.
You can use a combination of @module or @namespace along with @memberof.
define([], function() {
/**
* A test module foo
* @version 1.0
* @exports mystuff/foo
* @namespace foo
*/
var foo = {
/**
* A method in first level, just for test
* @memberof foo
* @method testFirstLvl
*/
testFirstLvl: function(msg) {},
/**
* Test child object with child namespace
* @memberof foo
* @type {object}
* @namespace foo.bar
*/
bar: {
/**
* A Test Inner method in child namespace
* @memberof foo.bar
* @method baz
*/
baz: function() { /*...*/ }
},
/**
* Test child object without namespace
* @memberof foo
* @type {object}
* @property {method} baz2 A child method as property defination
*/
bar2: {
/**
* A Test Inner method
* @memberof foo.bar2
* @method baz2
*/
baz2: function() { /*...*/ }
},
/**
* Test child object with namespace and property def.
* @memberof foo
* @type {object}
* @namespace foo.bar3
* @property {method} baz3 A child method as property defination
*/
bar3: {
/**
* A Test Inner method in child namespace
* @memberof foo.bar3
* @method baz3
*/
baz3: function() { /*...*/ }
},
/**
* Test child object
* @memberof foo
* @type {object}
* @property {method} baz4 A child method
*/
bar4: {
/**
* The @alias and @memberof! tags force JSDoc to document the
* property as `bar4.baz4` (rather than `baz4`) and to be a member of
* `Data#`. You can link to the property as {@link foo#bar4.baz4}.
* @alias bar4.baz4
* @memberof! foo#
* @method bar4.baz4
*/
baz4: function() { /*...*/ }
}
};
return foo;
});
EDIT as per Comment: (Single page solution for module)
bar4 without that ugly property table. ie @property removed from bar4.
define([], function() {
/**
* A test module foo
* @version 1.0
* @exports mystuff/foo
* @namespace foo
*/
var foo = {
/**
* A method in first level, just for test
* @memberof foo
* @method testFirstLvl
*/
testFirstLvl: function(msg) {},
/**
* Test child object
* @memberof foo
* @type {object}
*/
bar4: {
/**
* The @alias and @memberof! tags force JSDoc to document the
* property as `bar4.baz4` (rather than `baz4`) and to be a member of
* `Data#`. You can link to the property as {@link foo#bar4.baz4}.
* @alias bar4.baz4
* @memberof! foo#
* @method bar4.baz4
*/
baz4: function() { /*...*/ },
/**
* @memberof! for a memeber
* @alias bar4.test
* @memberof! foo#
* @member bar4.test
*/
test : true
}
};
return foo;
});
References -
- Another Question about nested namespaces
- For alternative way of using Namespaces
- Documenting literal objects
*Note I haven't tried it myself. Please try and share the results.
Here's a simple way to do it:
/**
* @module mystuff/foo
* @version 1.0
*/
define([], function() {
/** @lends module:mystuff/foo */
var foo = {
/**
* A method in first level, just for test
*/
testFirstLvl: function(msg) {},
/**
* @namespace
*/
bar4: {
/**
* This is the description for baz4.
*/
baz4: function() { /*...*/ },
/**
* This is the description for test.
*/
test : true
}
};
return foo;
});
Note that jsdoc can infer the types baz4.baz4
and test
without having to say @method and @member.
As far as having jsdoc3 put documentation for classes and namespaces on the same page as the module that defines them, I don't know how to do it.
I've been using jsdoc3 for months, documenting a small library and a large application with it. I prefer to bend to jsdoc3's will in some areas than have to type reams of @-directives to bend it to my will.
You can't document nested functions directly. I didn't like Prongs solution, so I used a different implementation without namespaces (it's JS, not Java!).
Update:
I updated my answer to reflect the exact use case given by the OP (which is fair, since JSdoc is pretty painful to use). Here is how it would work:
/** @module foobar */
/** @function */
function foobarbaz() {
/*
* You can't document properties inside a function as members, like you
* can for classes. In Javascript, functions are first-class objects. The
* workaround is to make it a @memberof it's closest parent (the module).
* manually linking it to the function using (see: {@link ...}), and giving
* it a @name.
*/
/**
* Foo object (see: {@link module:foobar~foobarbaz})
* @name foo
* @inner
* @private
* @memberof module:foobar
* @property {Object} foo - The foo object
* @property {Object} foo.bar - The bar object
* @property {function} foo.bar.baz - The baz function
*/
var foo = {
/*
* You can follow the same steps that was done for foo, with bar. Or if the
* @property description of foo.bar is enough, leave this alone.
*/
bar: {
/*
* Like the limitation with the foo object, you can only document members
* of @classes. Here I used the same technique as foo, except with baz.
*/
/**
* Baz function (see: {@link module:foobar~foo})
* @function
* @memberof module:foobar
* @returns {string} Some string
*/
baz: function() { /*...*/ }
}
};
return foo;
}
Unfortunately JSdoc is a port of Java, so it has a lot of features that make sense for Java but not for JS, and vice-versa. For example, since in JS functions are first-class objects, they can be treated as objects or functions. So doing something like this should work:
/** @function */
function hello() {
/** @member {Object} */
var hi = {};
}
But it won't, because JSdoc recognizes it as a function. You would have to use namespaces, my technique with @link
, or to make it a class:
/** @class */
function Hello() {
/** @member {Object} */
var hi = {};
}
But then that doesn't make sense either. Do classes exist in JS? no, they don't.
I think we really need to find a better documentation solution. I've even seen inconsistencies in the documentation for with how types should be displayed (e.g. {object}
vs {Object}
).
You can also use my technique to document closures.