Overwrite JSDoc in extending module class without redeclaration - javascript

Assumed this ...
`use strict;`
class Foo
{
/**
* Description
* #param {Type} arg blabla
*/
doSomething( arg )
{
}
}
class Bar extends Foo
{
/**
* Overwrite the description for `doSomething()` without redeclaring the method itself.
* #param {Type} arg blabla
*/
// dosomething( arg )
// {
// }
}
This is a very simplified nonsense example. The reason in reallife is ...
I have a common collection which accepts mixed elements for some methods like add, replace, remove, etc.. I have a second collection specialized for managing HTTP headers. E. g. I like to change the doc of the add() from "Adds an element to the collection" to "Adds an HTTP header to the collection". The method itself stays as is.
I tried
class Bar extends Foo
{
/**
* Overwrite the description for `doSomething()` without redeclaring the method itself.
* #param {Type} arg blabla
* #method dosomething
* #memberOf {Foo}
*/
}
in various ways ... with #override, #inheritdoc, etc.
How to achieve this?

Related

JSDoc subclass properties for prop [duplicate]

I'm using the documentation package, but cannot figure out how to get it to document class properties (that aren't defined via getters and setters).
As the following just generates class documentation for SomeClass, but omits the someProperty documentation.
/**
* SomeClass is an example class for my question.
* #class
* #constructor
* #public
*/
class SomeClass {
constructor () {
this.someProperty = true // how do I document this?
}
/**
* someProperty is an example property that is set to `true`
* #property {boolean} someProperty
* #public
*/
}
An aside: the #constructor on the class jsdoc is a documentation thing.
Move the JSDoc for someProperty into the constructor where it is first defined:
/**
* SomeClass is an example class for my question.
* #class
* #constructor
* #public
*/
class SomeClass {
constructor () {
/**
* someProperty is an example property that is set to `true`
* #type {boolean}
* #public
*/
this.someProperty = true
}
}
I'm unsure if there is a way of accomplishing it with the documentation package using an approach that doesn't involve inlining the JSDocs into the constructor.
Another way is to declare them in class documentation as follows:
/**
* Class definition
* #property {type} propName - propriety description
* ...
*/
class ClassName {
constructor () {...}
...
}
You can declare properties in a class, and use #type to declare a type for them. Worked in VSCode 1.70.2 with in a plain ECMAScript Module.
class Foo {
/**
* Some bary data
* #type { BarClass }
*/
bar;
}
let f = new Foo();
f.bar; // Intellisense can tell you type and purpose

Closure compiler typing: Refer to function (factory method)

Suppose I have a class with a factory method:
export class Foo {
constructor(options) {
this.a = options.a;
this.b = options.b;
}
/**
* #param {{
* a: number,
* b: number
* }} options
* #return {!Foo}
*/
static create(options) {
return new Foo(options);
}
}
I want to dependency inject Foo's factory method in another class, like:
/**
* #param {{
* createFoo: !function(!Object): !Foo
* }} options
*/
The problem: Closure Compiler says this does not match the formal parameter.
found : {
createFoo: function ({a: number, b: number): Foo,
}
required: {
createFoo: function (Object): Foo,
}
Obviously I can rewrite the type signature and hard code in the record, but I really want to refer to Foo.create so there's no need to update the entire codebase every time I add a new param to the options object.
How can I do this for CC?
One way is to write the type once in a typedef, and then refer to it in both places. (I haven't tried this but I think it should work)
/** #typedef {function({a: number, b:number}): Foo} */
var FooCreator;
export class Foo {
...
/**
* #type {FooCreator}
*/
static create(options) {
return new Foo(options);
}
}
/**
* #param {{
* createFoo: FooCreator
* }} options
*/
The general problem is that you are requiring a function that is more accepting than the Foo.create method. Nick Santos wrote a good explanation of this:
http://closuretools.blogspot.com/2012/06/subtyping-functions-without-poking-your.html
Using a loose function type "Function" or "!Function" will work as you would hope.
I used this definition to verify:
/** #param {{createFoo: !Function}} options */
function f(options) {}
f({createFoo: Foo.create});
CC debugger sample

How to document a member function from father class

How do I document a member function from a father class. There is a class A with a member function Afunc(), and I am gonna document class B extends A.
I do not overwrite Afunc() in B, yet I need the function Afunc() appear in my document, how do I do it?
I wrote
/**
* description
* #function Afunc
* #memberOf A
*/
It works that appears Afunc in the document, yet there is a <static> tag at the start of the function name.
How do I solve it?
Thanks everyone.
jsdoc 3.2.2 does what you want by default. In this example, the method B.foo will automatically be documented because B extends A and does not override foo:
/**
* #class
*/
function A() {
}
/**
* Foo the flerbl.
* #param {Object} flerbl The flerbl.
*/
A.prototype.foo = function (flerbl) {
};
/**
* #class
* #extends A
*/
function B() {
}
B.prototype = new A();
Otherwise, you must use # in your #memberof tag to mark the object as an belonging to an instance of the class:
/**
* description
* #function Afunc
* #memberof A#
*/

How can I correctly document instance members added via Object.defineProperties?

I have a class which defines a few instance properties via Object.defineProperties and I'm having great difficulty getting JSDoc 3 to recognize that they belong to their class.
Here's a simplified version of what I'm working with:
/** #exports mymodule */
function mymodule(exports) {
/** #constructor
* #param {String} foo A foo.
* #param {String} bar A bar.
* #classdesc Has a foo and a bar.
*/
function Example(foo, bar) {
Object.defineProperties(this, {
/** A foo and a bar
* #memberof Example
*/
foobar: { enumerable: false, value: foo + bar, writable: false }
});
}
exports.Example = Example;
}
When I run JSDoc, I get output for mymodule, Example, foo, and bar, but not foobar. If I remove the #memberof tag for foobar, it get registered as a global. I've tried #memberof mymmodule~Example, adding #lends to both the Object.defineProperties call and the object passed to it, and converting it to Object.defineProperty, but the results don't change.
How can I document foobar as belonging to Example?
After digging through every example I could find, I finally assembled the necessary incantation — #memberof is indeed the trick, but JSDoc seems to require that modules being used in namepaths be explicitly marked as such. The following worked perfectly:
/** A foo and a bar
*
* #type String
* #instance
* #memberof module:mymodule~Example
*/
You could also try the #lends annotation in place of #memberOf like this :
Object.defineProperties(this, /** #lends Example# */{
/** A foo and a bar */
foobar: { enumerable: false, value: foo + bar, writable: false }
});
Don't forget the sharp symbol after the class name to tell jsdoc members are instance members and not static members.
After fiddling around for many hours, I finally got it to work with #memberOf!. Note the uppercase "O" and the bang "!"
/**
* Description
* #memberOf! MyClass
* #type {String}
*/
var myString;
In case you want to use defineProperty instead, a #type annotation is sufficient (at least for IntelliJ to infer the proper type for the property):
/** #type SomeType */
Object.defineProperty(this, "someProperty", {
get: () => new SomeType()
});

How to document anonymous functions (closure) with jsdoc-toolkit

I am trying to document my code using JSDoc-toolkit. My code starts by being wrapped with a self-executing anonymous function. How in the world do I document this? I've spent nearly all day on this. JS Docs will not recognize anything inside of the anonymous function closure due to it not knowing what to do with it. It breaks and none of my comments come through.
My code looks something like this.
/**
* #fileoverview BLA BLA BLA
*/
/**
* This is where I don't know what to put.
*/
(function () {
"use strict";
/** or here */
var stlib = function (param, param, param) {
/** or here */
var share = {
/** or here */
config: {
button: DOM Element,
property: blablabla
},
init: function () { ...some init code here}
};
share.init();
};
widgets.add("share", stlib);
}());
Thank you!
You can use #namespace with #name and #lends like this:
/**
* #name MyNamespace
* #namespace Hold all functionality
*/
(function () {
"use strict";
/** #lends MyNamespace*/
var stlib = function (param, param, param) { ...All of my code...};
}());
You can't document nested functions directly. But you can do something like this:
/**
* #module foobar
*/
/**
* #function
* #author Baa
* #name hello
* #description Output a greeting
* #param {String} name - The name of the person to say hello
*/
(function hello(name) {
/**
* #function
* #author Baz
* #inner
* #private
* #memberof module:foobar
* #description Check if the argument is a string (see: {#link module:foobar~hello})
* #param {String} string - The string
* #returns {String} Returns true if string is valid, false otherwise
*/
var isString = function checkString(string) { return typeof string === 'string'; };
if (isString(name))
console.log('Hello ' + name + '!');
}('Mr. Bubbles'));
Here I'm setting checkString as private and inner to be descriptive (since nested functions can't be described), And then I pass in -p to document private functions. Finally, I add a link to the parent function for reference.
I think jsdoc is unnecessarily finicky and needs to be replaced with something better. It's a port of javadoc, so it has a lot of things that are relevant to Java but not JS, and vice versa. There are very common JS idioms, like closures or nested functions, that are hard or impossible to document.
I always check my namepaths and debug using the --explain flag.

Categories