How to get #borrows tag working in JSDoc - jsdoc

I have been having a hard time getting the #borrows tag working in JSDoc. I have been trying to get the documentation from one function and us it as documentation for a second function. But I don't seem to be able to even get a simple example working!
/**
* This is the description for funcA
*/
var funcA = function() {};
/**
* #borrows funcA as funcB
*/
var funcB = function() {};
I was expecting this to output documentation for both functions with both exactly the same. However only funcA is only has a description.

The #borrows tag doesn't seem to work directly on a symbol, but only indirectly. For example I had:
/** does amazing things */
function origFunc = function() {};
/**
* #borrows origFunc as exportedFunc
*/
exports.exportedFunc = origFunc;
but I, like you, got nothing useful in the generated doc.
That is because, it seems, that the #borrows tag operates on a container. (If you'll notice in the examples the #borrows tag is on the "util" module/namespace, not the renamed symbol.)
So this worked for me:
/** does amazing things */
function origFunc = function() {};
/**
* #borrows origFunc as exportedFunc
*/
exports = {
exportedFunc: origFunc,
}
Seems like a bug in #borrows though. (Or at least a bug in the documentation.)

I recently had a usage of it, what I was trying to do is to create a module and add some functions to it. The problem is that I don't have anything directly related to this module, since the export is just a line. Here's how I ended up with using #borrows.
/**
* A typehead with options filtered by user input.
*
* #module Typehead
* #borrows Typehead
* #borrows TypedOption
* #example
* <Typehead />
*/
export { default } from './Typehead'
In this case, Typehead will be borrowed in either Function or Classes section of module page depending on the kind of Typehead, and it will be displayed under #example render.
Note: However #borrows will add some extra entries to the system, after some experimentation, maybe #see is a better use.

Related

Doyxgen onetime macro expansion / expansion command

I have some code like the following example:
/** #file HelloPi.c */
/** The definition of pi */
#define PI 3.1415
/** #brief The main function.
* #details Prints the value of #PI, which is actual defined as 3.1415. */
void main()
{
printf("The value of pi is %f\n",PI);
}
In my doxygen dokumentation I would like to to have NO macro expansion for PI (and other defines) in general.
But on one paragraph in the documentation I need the value of pi (e.g. #details description of the main function).
Is there any possibility to expand the macro at this single part of documentation with a command or something? Something like /** #details ...the value of #PI is $(PI).*/
I only know the build-in MACRO_EXPANSION tag which works for the whole documentation: https://www.doxygen.nl/manual/preprocessing.html :-/
Thanks for help :)
Jan
Edit:
Add an other example which maybe better describes my Problem:
/** #file ErrorHandling.c */
#define ERR_CODE_POWERUNIT 1001 ///< Error in power unit */
/** #page errors
* [value of ERR_CODE_POWERUNIT ] means \copybrief ERR_CODE_POWERUNIT */
void errHandler(int error)
{
if(error=ERR_CODE_POWERUNIT)
printf("Error %d occur\n",ERR_CODE_POWERUNIT);
}
In the documentation I would like to have:
"1001 means Error in power unit"
In doxygen there is no possibility to do a conversion of a predefined variable (only) in the documentation.
You used in your documentation the an environment variable $(PI) but ths is quite cumbersome as you have to st the environment variable each time.
A better solution would be to use an ALIASES like:
ALIASES += pi=3.1415
or
ALIASES +\= "The value of PI = 3.14159265359..."
with which you define a command \pi that can be used in the documentation and will be replaced with the text / commands in the alias.
/** #details ...the value of #PI is \pi.*/
would result in something like (by head:
...the value of #PI is 3.1415

JSDoc typedef in a separate file

Can I define all custom types in a separate file (e.g. types.jsdoc), so that they can be reused throughout the application? What's the right way to do it?
/**
* 2d coordinates.
* #typedef {Object} Coordinates
* #property {Number} x - Coordinate x.
* #property {Number} y - Coordinate y.
*/
You can define types in a module (eg. typedefs.js). The module contains your JSDoc typdefs and can simply export an unused property.
// typedefs.js
/**
* #typdef foo
* #property {string} bar
*/
// etc.
exports.unused = {};
To use it, import the module where you need to reference these typdefs:
const typedefs = require("./typedefs");
/** #type {typedefs.foo} */
const fb = { bar: "hello" };
You may wish to annotate typedefs.js as a #module or #namespace. Because I'm using "tsd-jsdoc" to generate a types.d.ts file, and due to the way TypeScript now interprets modules vs. namespaces, I've annotated my typedefs.js file as a #namespace and documented each typedef as a member of that namespace:
/**
* #namespace typedefs
*/
/**
* #typedef foo
* #property {string} bar
* #memberof typdefs
*/
Hope that helps.
This is a TypeScript-flavored JSDoc specific answer, but I'm having success using a triple-slash directive to "import" all the types from another file. This has the advantage of not actually adding an unused import which can upset linters and bundlers.
I'm putting my shared types in one file called typedefs.js like this:
// typedefs.js
/**
* #typedef {Object} Foo
* #property {string} bar
*/
/**
* #typedef {Object} Baz
* #property {number} buzz
*/
and then using /// <reference path="typedefs.js" /> in the other files to access the shared types like this:
// randomThing.js
/// <reference path="typedefs.js" />
/**
* Turn a Foo into a Baz
*
* #param {Foo} a
* #return {Baz}
export function (a) {
return { buzz: a.bar.length };
}
The tricky thing though is that now typedefs.js is just being referenced in a comment, bundlers like rollup miss it completely. So I'm combining it with my old consts.js that exports a few constants and is imported in at least one place. That way the typedefs are still included in the rollup output.
I hope someone else finds this helpful.
p.s. rollup will completely exclude a pure JSDoc typedefs.js file _even if you have import './typedefs.js' because of tree-shaking! Gotta run rollup with --no-treeshake to keep those comments in the rollup output.
In vscode, the import('./path/to/types.js').def tag works perfectly fine.
For e.g.
types.js
/**
* #typedef {Object} connection
* #property {String} id
* #property {Number} pingRetries
* #property {(data:Object) => void} sendJSON
*/
exports.unused = {};
And someFile.js
/**
* #param {import('./types').connection} param
*/
const someFunc = (param) => {}
Also, note that the exports.unused = {} is necessary in the types.js file, otherwise the auto-import of import('./types') would not work and you may have to type it by yourself.
I just tried with VSCode and it works only if the separate file is opened in the editor. If not, external typedefs are typed as any
I usually do something similar in my projects, the difference being I use the extension .js to name the file. Webstorm works perfectly and is able to check types and auto-complete just fine. It won't recognize the .jsdoc extension (I just checked), so stick to .js even if the file doesn't contain any code statement.
I've had success with simply creating my types in a typedefs.js file and referencing using the ts/vscode import(path/to/file).Foo tag. JSDoc does not support this syntax out of the box, so I suggest also using jsdoc-tsimport-plugin in order to parse your docs.
Eg: typedef.js:
/**
* #typedef {Object} Foo
* #property {string} id
*/
/**
* #typedef {Object} Bar
* #property {string[]} things
*/
// having to export an empty object here is annoying,
// but required for vscode to pass on your types.
export {};
coolFunction.js
/**
* This function is super dope
* #param {import('../typedef').Foo[]} foo - a foo
* #return {import('../typedef').Bar[]} bar - an array of bars
*/
export function (foo) {
// do cool things
return bar;
}
I'm also using tsd-jsdoc to create a types.d.ts file, and this implementation is successfully creating the types. I had trouble with declaring modules and namespaces with the types file— just creating standalone typedefs for said models worked best for me.

JSDoc3 - Tidy organization of object literals

I'm an absolute newcomer to JSDoc and the Javadoc-like conventions; I am looking for some low-hanging fruit to get up and running, and I'm coming up short.
My code is organized like this, primarily as a matter of personal style:
var app = app || {};
app.ui = {
someUIfunction: function() {},
someUIparams: {},
anotherFunction: function(string, object) {}
}
app.rest = {
someRESTCall: function(url,data) {},
someRESTparams: {},
moreRESTCall: function(url,data) {}
}
Theoretically everything could just be one monolithic object under "app", but I like breaking down the next-level objects separately for handy cold-folding and searching in the IDE. Plus it just feels tidy to me that way.
What I cannot manage to do is drill down into the third-level functions and objects. JSDoc3 doesn't seem to want to render it for me; moreover, I'm not in love with having a starting page that is just "app" (or whatever I give the app in the end) as the namespace... I want its members to be in the index as well. Here's my attempt (forgive the silly examples!):
/**
* Application Namespace for this marvellous application
*
* #namespace app
*/
var app = app || {};
/**
* An object containing methods and parameters used for UI presentation logic
*
* #type {object}
* #memberOf app
* #property {string} title - a string used as the title of the UI
* #property {function} init - a function to initialize the UI
*/
app.ui = {
// not bothering to document this for whatever reason
title: "some title",
/**
* #memberOf app.ui
* #params {object} params - an object containing necessary initialization parameters
*/
init: function(params) {
// some initialization logic
}
}
There are two problems:
Ideally I'd like app.ui to have its own page. Is #namespace the right way to do this? It works, but visually it masquerades in the Index as being at the same level as app itself.
app.ui.init isn't documented at all.
It seems to me (and admittedly, this is probably just ignorance!) that JSDoc3 would be happier if I were to use:
app.ui.init = function() {} // (etc)
But that's going to be rather ugly as far as I'm concerned. Any pointers for the syntax I need to use to indicate nested members is what I'm after.

How to declare unlimited/variadic parameters in DocBlock?

Lets say I have a function (obviously a trivial example):
public function dot(){
return implode('.', func_get_args());
}
Now I know I could modify this to be
public function dot(array $items){
return implode('.', $array);
}
but with some functions that is not an option. So, how would you document the first version of the function with a docBlock so an IDE can interpret that it can receive unlimited parameters?
I have seen some methods that use:
/**
* Joins one or more strings together with a . (dot)
* #param string $string1
* #param string $string2
* #param string $_ [optional]
* #return string
*/
public function dot($string1, $string2, $_ = null) {
return implode('.', func_get_args());
}
Which in an IDE looks like
But that feels like a hack to me, is there no way to do it just with docBlock?
[UPDATED 2015-01-08]
Old way to do this in PHPDoc was:
http://manual.phpdoc.org/HTMLSmartyConverter/HandS/phpDocumentor/tutorial_tags.param.pkg.html
/**
* #param int $param,...
**/
However, this is no longer supported. As of PHP 5.6 Variadic Method Parameters are a part of the PHP language, and the PHPDoc's have been updated to reflect this as of PHPDoc 2.4 if I recall correctly. This is also in the PhpStorm IDE as of EAP 139.659 (should be in 8.0.2 and up). Not sure about implementation of other IDEs.
https://youtrack.jetbrains.com/issue/WI-20157
In any case, proper syntax for DocBlocks going forward for variadic parameters is:
/**
* #param int ...$param
**/
As Variadics are implemented in PHP 5.6 PHPDocumentor should support the following syntax as of version 2.4.
/**
* #param Type ...$value
* Note: PHP 5.6+ syntax equal to func_get_args()
*/
public function abc(Type ...$value) {}
This should be the correct way to describe such a signature. This will likely be included in PSR-5. Once that is accepted IDE's should follow to support this "official" recommendation.
However, in the mean time some IDE's have an improved understanding of what they consider correct. Hit hard on the IDE vendor to support the offical PHP syntax that is supported as of 5.6 or use whatever works in the meantime.
In php the concept of valist or list of "optional arguments" does not exist.
the $_ variable will just contain, here the third string you give.
The only way to allow an array OR a string is to test the first argument with is_array()
public function dot($arg1){
if(is_array($arg1)){
return implode('.',$arg1);
}
else if $arg1 instanceof \Traversable){
return implode('.',iterator_to_array($arg1));
}
else{
return implode('.',func_get_args());
}
}
Now that you handled the behaviour you want, you have to document it. In php, as overloading is not allowed, a convention is to use "mixed" as a type if you want to provide multiple types.
/**
*#param mixed $arg1 an array, iterator that will be joined OR first string of the list
*#return string a string with all strings of the list joined with a point
*#example dot("1","2","3"); returns 1.2.3 dot(array(1,2,3)); returns 1.2.3
*/
Moreover, according to phpdocumentor documentation you can declare sort of valist with
/**
*#param string ... list of strings
*/

Make Doxygen document a struct/class defined inside a macro call

I have this PACKED macro, that receives a struct definition and returns it with a compiler annotation to make it packed.
For example:
/**
* ...
*/
PACKED(struct A {
/**
* ...
*/
int x;
});
I have tried several Doxygen options to include that documentation, but I've had no success so far. Closest I've come up with is this:
ENABLE_PREPROCESSING = YES
PREDEFINED = PACKED(type)=type
MACRO_EXPANSION = YES
But that messes up the struct and members' documentation (confirmed via doxygen -d Preprocessor).
Ideas?
Turns out it's a bug in Doxygen.
One possible workaround is to use #class, and so on.