This document is an introductory guide on documenting your source code using short-jsdoc.
short-jsdoc defines a language very similar to jsdoc with a strong emphasis in types and other advanced features designed to better express particularities of the semantics of the JavaScript language.
So if you are already familiar with Object Oriented Programming and tools like jsdoc, javadoc, doxygen, etc then using short-jsdoc will be straight forward.
For the impatiens, here there is a list of main jsdoc annotations. Because short-jsdoc is designed with flezibility/customizability in mind, some relevant things to understand are:
name | example | description |
---|---|---|
@module |
// @module TodoList // This module contains the front-end classes that implement // the product list user experience from Models, routers and views |
Indicates that the block describes a group of related classes. It declares that the following class declarations will be contained by this module. |
@class |
// @class TodoEntry // Instance of this class represent an entry in the TODO list. // @extends AbstractView |
Indicates that the block describes a class. In JavaScript, this is generally an object with a constructor function. Nevertheless Must be preceded by a Parents: Children: |
@method |
// @method parse it will parse given JavaScript code and return an AST object // @param {String} jscode the JavaScript code to parse // @throws {ParserError} thrown if given code is not valid JavaScript // @returns {ASTNode} |
Indicates that the block describes a method for the current class, this is the last parsed class. Parents: |
@property |
// @property {Color} color the color of this car. |
Indicates that the block describes a method for the current class, this is the last parsed class. A @property tag has the structure @property {type} description. The {type} is optional. Parents: |
@event |
// @event change // triggered when the state of this model changed. // Handlers accept the property name and new value as parameters |
Indicates that the block describes a custom event that the class can fire at some interesting moment of code execution. Ideally, an @event block should reside above the code that defines the event, even if that code is just a simple string declaration. A @event tag has the structure Parents: |
@interface |
// @interface Throwable @extends IBase @method throw // @interface SoundMaker @method play @method stop // @class LittleRadio @extends Radio @implements Throwable @implements SoundMaker |
Interfaces are very similar to classes. See Interfaces section. A class can Parents: |
@function |
// @function formatUrl @param {String} base @returns {String} // @function visitor @param {Thing} visitable // @function visit @param collection @param {visitor} visitor |
Functions belong to a module. Also, notice that functions can be referenced as types - as if they were classes/interfaces. Parents: |
name | example | description |
---|---|---|
@extend or @extends |
// @class Apple @extend Fruit // @interface Component @extend Actionable |
classes can inherit from other classes and this is declared by using the |
@implement or @implements |
// @class Button // @implements Component // @implements Actionable |
classes can implement one or more interfaces and for declaring that we use |
@return or @returns |
// @return {Number} the number of goals this player has submitted. |
Specifies a method's return value. A @return tag has the structure @return {type} description. The {type} is optional. Parents: |
@param |
// @param {Array<String>} queue the queue objectyou want to process. |
Specifies a method's return value. A @return tag has the structure @return {type} description. The {type} is optional. Parents: |
@constructor |
// @constructor // @param {Config} config the configuration for the new instances. |
constructors are similar to methods but they don't have a name. A class can declare several constructors and they describe the constructor function of the class. @return can be omitted. Parents: |
@attribute |
// @attribute {String} name the color of this car. |
Several JavaScript frameworks like Backbone.js react, YUI, etc support the concept of class attributes. Attributes are similar to properties but they can be setted/getted using getters and setters methods and also the class could trigger 'change' events when attributes change. Parents: |
@throw or @throws |
// @throws {UnexpectedError} when an unknown error raises. |
Specifies an error which method throws. A @throws tag has the structure @throws {type} description. The {type} is optional. A method can contain multiple throw declarations, often one for each type of error thrown. Parents: |
@public or @private |
// @property {Color} color the color of this fruit. // @public |
You can add @public or @private annotation to any method, property, etc to declare that it is public or private. |
For documenting our source code with short-jsdoc we will be using the Object Oriented Programming paradigm (OOP). So short-jsdoc will be better suited to document those projects that uses POO than other paradigms, like functional. You should be familiar with POO, but just in case here is a summary:
Software is organized in several Modules which are the first building block for modularization of responsibilities in a project. Modules contains classes that can be instantiated and which instances collaborate to solve a problem. classes which are the main behavior building block in POO:
jsdoc is a technology in which the programmer writes source code comments that contains some special markings to declare and describe its project's Object oriented elements like modules, classes, properties, etc.
These markings have the format @foo
and are called annotations
Then a jsdoc tool will parse the source code files and collect all these annotations to form an Abstract Syntax Tree (AST)
Alternatively, another tools will be responsible of showing this AST visually so the user can navigate through classes, modules, methods, etc.
Let's see a little example of JavaScript code that contains a jsdoc comment. It declares a class FileView
of module myapp that extends class AbstractView
and contains a property file of type FileData
and a method deleteFileHandler
that accept a Function
parameter and returns a Promise
object:
// @module myapp // @class FileView This view shows a single file @extends AbstractView // @property {FileData} file // @method deleteFileHandler Handles the delete file action // @param {Function} fn // @returns {Promise}
The tool will be consuming expressions like the following to build the AST. We call these expressions annotations:
// @param {Color} color a description for the color parameter
a description for the color parameter
is associated to the node and documents itThe structure of the generated tree is as follows.
@module
contains @class
@class
contains @method
, @property
, and @event
@method
contains @param
, @return
and @throw
In short-jsdoc only certain nodes can contain children and are the following:
@module @method @property @event @class
All other annotations are leaf nodes meaning they can't contain children and always belong to a parent node. Example of leaf nodes:
@param @throws @returns @extends @static
The parser will read your files from top to bottom parsing any annotation found in your source code comments.
When a leaf node annotation is found, it is assigned as children of the last parsed parent node.
When a parent node annotation is found it is assigned as children of the last parent node that matches the structure 'modules that contain classes that contains methods, etc'.
Any kind of comment style can be used.
Any @annotation name can be used so you can define your own semantics - they will be parsed as children of the last parent node read.
Source code files must be auto-containable - in other words you cannot make any assumptions about the order of the files being parsed.
Comments starting with the character '?' will be ignored, even if they contain annotations:
//? @class Something will be ignored b the parser /*? @method foo also will be ignored */
short-jsdoc supports class inheritance. Only single class inheritance is supported, this is, a class can only extend only other one class. Also, javascript.Object
is the root class, meaning that, if a class doesn't declare any inheritance then the tool will assume it extends from javascript.Object
.
For declaring inheritance we use the class-level annotations @extend
or @extends
. In the following example we declare that class Dog
extends from class Animal
:
// @class Animal lorem ipsum @property {Number} age // @class Dog @extends Animal @method bark @return {Sound}
Important: you can only extend simple types, for example the following won't work:
@class Apples @extends Array<Fruit>
short-jsdoc supports the concept of class's interfaces. An interface is a well known concept in Object oriented programming for describing contracts that classes/objects must respect. A class can 'implement' several interfaces and, for declaring that, we use the annotation @implement
or @implements
at the class level.
For declaring an interface we use the annotation @interface
that is very very similar to @class
annotation. interfaces can contain just the same things as classes like methods, properties, events, etc.
Also interfaces can inherit from other interfaces by using @extend
or @extends
, just as classes.
In the following code we declare a class LittleRadio that implements two interfaces Throwable and SoundMaker. Also interface Throwable extends interface IBase:
// @interface Throwable @extends IBase @method throw // @interface SoundMaker @method play @method stop // @class LittleRadio @extends Radio @implements Throwable @implements SoundMaker
Types are optional, always
Some nodes like parameters or returns can declare a type, which is a reference to class nodes. short-jsdoc heavily support types and can be of the following kinds:
Are just a reference to a class by name, for example:
// @method getModel @returns {Banana}
If you reference a JavaScript native type like String, Array, Object, etc., they will be binded to the Mozilla JavaScript Types Reference. Some native types are:
Object, Number, Boolean, String, Array, Function, Error, etc
Alternative you can instruct short-jsdoc parser to also include build in natives types documentation. In that case instead an external link you can navigate to the type as with any other types and the inherited information will be available.
These are inspired in Java or C# generics. For example we can say that a parameter is an Array but we can also say it is an Array of Bananas :
// @method addFruit @param {Array<Banana>} fruits
Generic types support arbitrary nesting:
// @method groupWires @returns {Object<String,Array<Wire>>} a map of wires by name.
Imagine a method in which its first param can be both a String or an Array. Then we can say so in jsdocs like this:
@method foo @param {String|Array} p
Because in JavaScript is very common to define Objects on the fly shortjsdoc supports an object literal type definition:
@method foo @returns {id:String,colors:Array<Color>,execute:Function}
That means that the method foo returns an object with the properties id of type String, color of type Array of Color and execute of type Function.
Marks inside a node text can be defined using the syntax @?something. This is mostly used for defining references to other nodes or to external links from within the text. It is similar to java's @see annotation.
We can use @?class AClass or @?method module.Class.method1 or @?property, @?event, etc. These markings will create a link to the referenced node in the output. Example:
// @module client // @class CustomerModel This model represent a single customer. // The attributes of this model are defined by the @?class server.CustomerService service // @extends Backbone.Model
Also, there is a @?ref that will accept any kind of node. For classes is intelligent and you can use the class' simple name, but for referencing other types like methods, properties, events, etc you need to reference them by absolute name, this is $module.$className.$methodName.
There is a very powerful annotation @alias that let declare alias for types and even for annotations.
Suppose you want to integrate an external jsdoc file in which the type 'float' is used instead of Number. You want the tool to replace each 'float' type with 'Number', so you would add the following (before):
// @alias class float Number
Even more interesting, you want to create shortcuts to common js types, so instead writing Object < String, < Array < Number>>> you can just write O < S, < A < N>>>, well that can be done by just defining class alias:
// @alias class O Object // @alias class A Array // @alias class S String // @alias class N NUmber
Then when the type 'A' is found it will be replaced by 'Array'
the @alias plugin also supports another kind of aliasing that gives the user the power of creating aliases of annotations. For example, suppose that we are not documenting js-doc but another thing, like the grunt/gulp build tasks and we want to use the annotation @gulp-task to be processed as if they were @module, then we can just write:
// @alias annotation gulp-task module
After that declaration, all annotations @gulp-task will be treated as if they were @module.