ariya.io About Talks Articles

Tracking JavaScript Annotations

3 min read

notepad

One of the interesting features of Esprima is to retrieve every comment inside a JavaScript source. Even better, each comment can be linked to the related syntax node. This is very helpful (like in the case of JSDoc) since any additional information regarding the program can be provided via the comment serving as a form of annotation.

Let’s take a look at the simple code below:

// Give the ultimate answer
function answer() { return 42 }

If we let Esprima consume the above code (as a string) like this (mind the attachComment option):

var tree = esprima.parse(code, { attachComment: true });

then the object tree will contain an array called leadingComments which is part of the function declaration. Portions of that tree is visualized in the following diagram. Note that the leadingComments array has only one element, because there exists only one single-line comment before the function.

comment

Many documentation tools rely on a specially-formatted comment to derive additional information. For example, since JavaScript does not specify the type of every function parameter, that piece of information can be encoded in the annotation. This is very familiar for those who use JSDoc, Closure Compiler, or other similar tools. The following fragment demonstrates the usage:

/**
 * Compute the square root.
 *
 * @param {number} x number.
 * @return {number} The square root of x.
 */
 
function SquareRoot(x) {
    return Math.exp(Math.log(x)/2);
}

Here is another example:

/**
 * Adds three numbers.
 *
 * @param {number} x First number.
 * @param {number} y Second number.
 */
 
function Add(x, y, z) {
    return x + y + z;
}

Unfortunately, the annotation in the above example is missing the tag for the third parameter. It often happens, in some cases due to some refactoring which may result in out-of-sync comment. Since such a mistake is not caught during unit testing, it may go undetected for a while.

It is however possible to use Esprima to extract the comment and then process it with a JSDoc annotation parser such as Doctrine. This way, if a function parameter is not undocumented, we can warn the developer as early as possible. The proof-of-concept of such a tool exists in the repository gitlab.com/ariya/missing-doc/. The gist is in its analyze function (missing-doc.js):

data = doctrine.parse(comment.value, {unwrap: true});
    params = [];
    data.tags.forEach(function (tag) {
        if (tag.title === 'param') {
            params.push(tag.name);
        }
    });

Once we got the comment associated with a syntax node (that represents a function declaration), it got parsed by Doctrine and we just iterate through all the found tags. The next step is quite logical:

missing = [];
    node.params.forEach(function (param) {
        if (params.indexOf(param.name) < ) {
            missing.push(param.name);
        }
    });

Here we compare what is being documented (x and y) in the annotation tags with the actual function parameters (x, y, and z). When something is not listed in the annotation, it will go into our missing array for the subsequent reporting.

Running the tool with Node.js like this:

npm install
node missing-doc.js test/sample2.js

gives the following result:

In function Add (Line 8):
 Parameter z is not documented.

Easy enough! All in all, this microtool weighs less than 70 lines of JavaScript.

How do you plan to use Esprima’s comment attachment feature?

Related posts:

♡ this article? Explore more articles and follow me Twitter.

Share this on Twitter Facebook