I'm trying to use jsDoc on my js code in which I want to define:
- A Namespace.
- A Class.
- A Static Method.
Note that the code does exactly what I expect at runtime, but I have problems to getting started with jsDoc, so I question myself if code is correct...
/** #namespace
* #name myNamespace
* #description myNamespace description.
*/
if (typeof (myNamespace) == "undefined") myNamespace = { };
/** #class
* #name myClass
* #description myClass description.
* #memberof myNamespace
* #inner
*/
myNamespace.myClass = function () { };
/** #method
* #name myStaticMethod
* #description myStaticMethod description.
* #param {String} myParam. Required. myParam description.
* #return myReturnValue description.
* #remarks remarks description.
* #memberof myNamespace.myClass
* #inner
*/
myNamespace.myClass.myStaticMethod = function (myParam) {
var myReturnValue = myParam;
return myReturnValue;
};
When I generate with jsDoc I see in the index:
- Correct myNamespace definition.
- Correct myClass definition.
When I go inside myClass I cannot see myStaticMethod...
myStaticMethod is not present anywhere.
My JS is coded correctly?
If is correctly coded... Is the comments correctly written?
What's wrong?
Thanks a lot...
If you're going to use #name, you need to tell JsDoc what the member is; using #name tells JsDoc to completely ignore context.
In your case, I think you need to add #static (you already have #memberof, so that's good).
T.J. Crowder was right, I cannot vote becouse I'm young in community, this is the corrected code comments for jsDoc if someone need:
/** #namespace
* #name myNamespace
* #description myNamespace description.
*/
if (typeof (myNamespace) == "undefined") myNamespace = { };
/** #class
* #name myNamespace.myClass
* #description myClass description.
* #memberof myNamespace
* #inner
*/
myNamespace.myClass = function () { };
/** #function
* #static
* #name myNamespace.myClass.myStaticMethod
* #description myStaticMethod description.
* #param {String} myParam. Required. myParam description.
* #return myReturnValue description.
* #remarks remarks description.
* #memberof myNamespace.myClass
* #inner
*/
myNamespace.myClass.myStaticMethod = function (myParam) {
var myReturnValue = myParam;
return myReturnValue;
};
Related
I'm trying to document some old code with JSDoc3, and I'm stuck trying to get it to include in the documentation the parameters to instance methods - or to show anything as an instance property at all. I suspect the problem is that the code does not follow the expected idiom for faking classes in javascript, but I want to get everything documented before I start rewriting anything. I've tried to make a small example of the problem, with the structure of the actual code:
/**
* Global function
* #param {Object} v Stuff that they're trying to avoid making global
* #return {Object} Updated v
*/
jsdoc_test = function( v ) {
/**
* Some stuff is defined in this namespace
* #namespace space
*/
var space = {};
/**
* Something that acts like a class
* #name space.someclass
* #memberOf space
* #constructor
* #type {function}
* #param {any} y blah blah
* #return {Object} The constructed object
*/
space.someclass = function( w ) {
var obj = {
source: w, // might need this again
derived: foo( w ), // what we usually need
etc: "etc" // and so on
};
/**
* This should be a member function, but it appears as a static property
* #name space.someclass.methodA
* #memberOf space.someclass
* #type {function}
* #instance
* #param {any} x Parameters do not appear in documentation
* #return {Object} this
*/
obj.methodA = function( x ) {
bar( x ); // or whatever methodA does
return this;
}
/**
* This should be a member function, but it doesn't show up at all
* #name space.someclass.methodB
* #memberOf space.someclass#
* #type {function}
* #param {any} y Parameters do not appear in documentation
* #return {Object} this
*/
obj.methodB = function( y ) {
baz( y ); // or whatever methodB does
return this;
}
return obj;
/**
* This should be a member function, but it doesn't show up at all
* #name space.someclass.methodC
* #memberOf space.someclass.prototype
* #type {function}
* #param {any} z Parameters do not appear in documentation
* #return {Object} this
*/
obj.methodC = function( z ) {
qux( z ); // or whatever methodC does
return this;
}
return obj;
}
// ...
}
I want all three methods to appear in the generated documentation as instance methods. As it is, methodA appears as a static property, while methodB and methodC (which follow suggestions from here) do not appear at all
How do I get JSDoc3 to document instance methods, with their parameters, without rewriting the code?
A combination of #instance, #memberOf & #method should do it:
/**
* This should now be a member function.
* #instance
* #memberOf space.someclass
* #method methodA
* #param {*} x Some parameter of any type.
* #return {Object} this.
*/
Looks like you're using too many tags on your code. When you use #constructor, you shouldn't need #name or #type, since those are covered by using constructor.
So, you've got two options, I think.
Use #constructor and remove the redundant (conflicting) tags:
/**
* Something that acts like a class
* #constructor space.someclass
* #memberOf space
* #param {any} y blah blah
* #return {Object} The constructed object
*/
Or, if you don't want to use the #constructor tag, add the appropriate hinting yourself:
/**
* Something that acts like a class
* #name space.someclass
* #memberOf space
* #kind class
* #param {any} y blah blah
* #return {Object} The constructed object
*/
In both cases, #type is redundant since you're documenting a class; the type would technically be the full name of your function (i.e., #type {space.someclass}).
I have the following JavaScript.
It is a RequireJS module that has its functions namespaced into an object literal. I referred to: How do I JSDoc A Nested Object's Methods? to find out how to mark up the JSDoc notations.
I run JSDocs 3.3.0-beta3 with private: true in a grunt task but on the modules page there are no private methods or arguments for the publich method.
/**
* A module doing a lot of Foo.
* #module Foo
* #requires jquery
* #author Markus Falk
*/
define(['jquery'], function($) {
'use strict';
/**
* #property {Object} Container
*/
var Foo = {
/**
* Caches all jQuery Objects for later use
* #function
* #private
*/
_cacheElements: function() {
this.$foo = $('.foo');
},
/**
* inits the app and returns the Message Text
* #function
* #public
* #param {Object} msg - The message.
* #param {string} msg.text - The message's Text.
* #param {string} msg.author - The message's author.
* #returns {String} Sentence with given message.text
*/
init: function(msg) {
this._cacheElements();
return "Say " + msg.text;
}
};
return /** #alias module:Foo */ {
/** init */
init: Foo.init
};
});
Here is the output of this JSDoc code:
Try #function init and #function _cacheElements
/**
* A module representing a Foo.
* #module Foo
* #requires jquery
* #author Markus Falk
*/
define(['jquery'], function($) {
'use strict';
/**
* #property {Object} Container
*/
var Foo = {
/**
* Caches all jQuery Objects for later use
* #function _cacheElements
* #private
*/
_cacheElements: function() {
this.$foo = $('.foo');
},
/**
* inits the app and returns the Message Text
* #function init
* #public
* #param {Object} msg - The message.
* #param {string} msg.text - The message's Text.
* #param {string} msg.author - The message's author.
* #returns {String} Sentence with given message.text
*/
init: function(msg) {
this._cacheElements();
return "Say " + msg.text;
}
};
return /** #alias module:Foo */ {
/** init */
init: Foo.init
};
});
Given an angular app with a factory that returns a class, as such:
angular.module('fooApp').factory('User', function(){
function User(name){
this.name = name;
}
User.prototype.greet = function(){
return "Howdy, " + this.name;
}
return User;
});
Using ngdoc (the special flavor of jsdoc angular uses), how do I document the initializer without defining it as a method?
Right now, this is what I've tried:
/**
* #ngdoc service
* #name fooApp.User
* #description User factory.
*/
angular.module('fooApp').factory('User', function(){
/**
* #ngdoc method
* #methodOf fooApp.User
* #name Initializer
* #description Initializes a new User object with a name
*/
function User(name){
this.name = name;
}
User.prototype.greet = function(){
return "Howdy, " + this.name;
}
return User;
});
But this results in the User initializer (the User function that accepts the parameter name) being treated like a method with the name Initializer, which is confusing to people trying to use this code.
I've tried adding the #constructor flag, but this has no effect of the html dgeni ends up generating.
Thank you.
UPDATE: Removed references to dgeni. I was under the impression that the plugin I was using (grunt-ngdocs) uses dgeni behind the scenes, but this is not the case.
This is how I would do it not having any experience with Angular in particular:
/**
* #ngdoc service
* #name fooApp.User
* #description User factory.
*/
angular.module('fooApp').factory('User', function(){
/**
* #ngdoc method
* #constructs fooApp.User
* #description Initializes a new User object with a name
*/
function User(name){
this.name = name;
}
User.prototype.greet = function(){
return "Howdy, " + this.name;
}
return User;
});
This is opinionated answer.
I had trouble with Angular documentation, and I even wrote a blog about it, Sigh, AngularJS Documentation
My conclusion was to build a new one. Angular-jsdoc is the outcome.
Here is excerpts from github.
Angular-JSDoc
JSDoc 3 Template for AngularJS.
A JSDoc plugin and template for AngularJS, nothing else!
Features
Right side TOC, table of contents, for navigation by Directives, Services, Controllers, etc
Read and process #ngdoc tag
How Does It Look Like
angularjs-google-maps Documentation
I created a fork/pull request to add #constructor support to gulp-ngdocs as available in grunt-ngdocs: https://github.com/nikhilmodak/gulp-ngdocs/pull/91. All this does is change the basic usage section to include the new keyword.
Then use in a fashion similar to, but slightly different from, #SGD's answer.
Make sure that #ngdoc directive on the service specifies function.
Example:
/**
* #ngdoc function
* #name yourModule.yourService
* #description
*
* Your short description
*
* #constructor
* #param {string} yourConstructorParameter A string paramter
* #returns {Object} An object instance of type YourClassName
*
*/
angular
.module('yourModule', [])
.factory('YourClassName', function() {
/**
* #ngdoc object
* #name yourModule.type:YourClassname
* #description
*
* Short description.
*
*/
function YourClassName(yourConstructorParameter) {
this.yourConstructorParameter = yourConstructorParameter;
this.yourMethod = function() {};
}
/**
* #ngdoc function
* #name yourModule.type:YourClassName#yourPrototypeMethod
* #methodOf yourModule.type:YourClassName
* #description
*
* Short Description.
*
* #returns {Object} The object passed on instantiation.
*/
YourClassName.prototype.yourPrototypeMethod = function() {
return this.yourConstructorParameter;
};
return YourClassName;
});
I'm trying to create a documentation for my system but something's always wrong.
In the following, my Class appear in the module MyModule, perfect! But my function doesn't appear in the documentation!
Do you have any idea where the problem is coming from?
define([
'underscore',
'backbone'
], function(_, Backbone) {
'use strict';
/**
* MyModule
*
* #module MyModule
*/
var MyModule = {};
/**
* Class description
*
* #class MyModule.View
* #extends Backbone.View
* #memberOf module:MyModule
* #abstract
*/
MyModule.View = Backbone.View.extend(
/** #lends MyModule.View */
{
/**
* myFunction1
*
* #param {object} hello Hello World!
*/
myFunction1: function(hello) { }
}
});
/**
* Class description
*
* #class MyModule.Model
* #extends Backbone.Model
* #memberOf module:MyModule
* #abstract
*/
MyModule.Model = Backbone.Model.extend();
//etc...
});
Thanks
You have to prefix the name passed to #lends with the module name. See the #lends statement in this snipped I adapted from the code in your question:
MyModule.View = Backbone.View.extend(
/** #lends module:MyModule.MyModule.View */
{
/**
* myFunction1
*
* #param {object} hello Hello World!
*/
myFunction1: function(hello) { }
});
With the #lends above, I'm able to get myFunction1 to show up, properly documented.
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.
Just to improve on Prongs's answer a bit for JSDoc3, I was only able to get it to work when I used the #instance annotation in lieu of #member.
ES6 example code follows:
class Test
{
/**
* #param {object} something
*/
constructor(something)
{
this.somethingElse = something;
/**
* This sub-object contains all sub-class functionality.
*
* #type {object}
*/
this.topology = {
/**
* Informative comment here!
*
* #alias topology.toJSON
* #memberof! Test#
* #instance topology.toJSON
*
* #returns {object} JSON object
*/
toJSON()
{
return deepclone(privatesMap.get(this).innerJSON);
},
...
}
}
}