JSDOC on socket.io emit - javascript

If I have socketio function like this :
_sock.emit('app_version',appversion,(response)=>{
console.log(response)
})
and I want to put a proper JSDOC , explaining that appversion is a string, and response is a string, how do i write it ?
currently tried some combination like #param , or #property in WebStorm, yet Webstorm still don't recognize that appversion and response type.
Kindly help

JSDoc works best if you type things as you declare them, which doesn't work very well if you're doing things inline (such as using an inline arrow function. Try something like this, declaring and typing your variables and functions before using them:
// Use #type to indicate the type of the next following variable
/**
* #type {string}
*/
let appversion;
// Use #param to indicate the param type of the next following function
/**
* #param {string} response
*/
function doThing(response) {
console.log(response);
}
_sock.emit('app_version', appversion, doThing);

Related

Getting intellisense on function parameter object types in javascript in vs code

I'm trying to specify the types of req and res, to get intellisense to work on the parameters as I'm trying to illustrate below, but I'm not sure how to accomplish it.
var http = require('http');
http.createServer(foo).listen(8081);
/**
* #? ? ?
*/
function foo(req, res) {
req.<intellisense context menu>
}
I've looked through some of the documentation at https://github.com/Microsoft/TypeScript/wiki/JavaScript-Language-Service-in-Visual-Studio and https://github.com/Microsoft/TypeScript/wiki/JsDoc-support-in-JavaScript, but don't know if this is even possible. I'm a beginner at javascript, can somebody point me in correct direction?
Bonus question: How can I make this work also if foo is in another module/file, and that module doesn't in itself require('http')?
This is a very old question but since I stumbled upon it while looking for the same thing, here is an answer:
You need to specify the type of the parameter after #param in curly brackets like this:
/**
*
* #param {XMLHttpRequest} req Some XMLHttpRequest
* #param {string} res (Let's suppose res is a string)
*/
function foo(req, res) {
req.<intellisense context menu appears>
}
More info (with a nice video demonstration) is available in Visual Studio Code documentation:
https://code.visualstudio.com/docs/languages/javascript#_js-doc-support

JSDoc in VS code for documenting function with module's type

I want to document a function written in another module, which uses http.ClientRequest typed parameter. I want something like this, but it does not work:
/**
* #param {ClientRequest} req
*/
function setToken(req) {
}
I have tried also #param {http.ClientRequest}, but it did not work.
Update:
Basically I solved that problem by importing the required module by import http from "http";. However, I don't want to import it because this module does not use http module but provides helper functions.
After improve answer from IGx89 I got a shorter variant without typedef. I prefer this variant when I reference to another module one time:
/**
* #param {import('http').ClientRequest} req
*/
function setToken(req) {
}
But if you need reference to some type from another module with long path variant with typedef looks shorter.
Add the following to the top of your file:
/** #typedef {import('http').ClientRequest} ClientRequest */
I had this same problem myself (though regarding a module in my own app) and also had a very hard time finding the solution. I eventually figured out the above syntax by reading through this issue in the TypeScript GitHub repo: https://github.com/Microsoft/TypeScript/issues/14377
It does not work because it is a custom type JSDoc don't know. You have to setup your own definition with a #typedef.
/**
* A number, or a string containing a number.
* #typedef {(number|string)} NumberLike
*/
/**
* Set the magic number.
* #param {NumberLike} x - The magic number.
*/
function setMagicNumber(x) {
}
See the full examples on JSDoc typedef tag definition examples
I made an example which worked for me with JSDoc 3.5.3
/** #typedef {ClientRequest} TestReq */
/**
* #param {TestReq} req
*/
function setToken(req) {
}
JSDoc output image

Correct way to avoid 'Unresolved variable ...' errors when using variables returned as a JSON object from an API [duplicate]

I have a function that takes data from server:
function getData(data){
console.log(data.someVar);
}
WebStorm says that someVar is an unresolved variable.
How can I get rid of such warnings?
I see several options:
Suppress warnings in IDE settings;
Add a JSON source file with fields (details);
Use array-like syntax: data['some_unres_var'];
Also, WebStorm is offering me to create namespace for the "data" (add an annotation like /** #namespace data.some_unres_var*/), create such field, or rename it.
Use JSDoc:
/**
* #param {{some_unres_var:string}} data
*/
function getData(data){
console.log(data.some_unres_var);
}
JSDoc the object. Then its members.
/**
* #param data Information about the object.
* #param data.member Information about the object's members.
*/
function getData(data){
console.log(data.member);
}
#property for local variables (non parameters).
Tested in PyCharm. #Nicholi confirms it works in WebStorm.
The {{ member:type }} syntax Andreas suggested may conflict with Django templates.
Thanks to Jonny Buchanan's answer citing the #param wiki.
To document arrays of objects, use [] brackets as JSDoc suggests:
/**
* #param data
* #param data.array_member[].foo
*/
All other answers are incorrect for the general case. What if you don't get data as a parameter? You don't have JSDoc then:
function niceApiCall(parameters) {
const result = await ... // HTTP call to the API here
for (const e of result.entries) {
.. // decorate each entry in the result
}
return result;
}
WebStorm will warn that "result.entries" is an unresolved variable (field).
The general solution is to add an #namespace declaration:
function niceApiCall(parameters) {
/** #namespace result.entries **/
const result = await ... // HTTP call to the API here
for (const e of result.entries) {
.. // decorate each entry in the result
}
return result;
}
Destructuring use, Luke.
function getData(data){
const {member} = data;
console.log(member);
}
using a dummy js file with anonymous function expression returning the json literal, as written at http://devnet.jetbrains.com/message/5366907, may be a solution. I can also suggest creating a fake variable that will hold this json value, and use this var as a value of #param annotation to let WebStorm know what the actual type is. Like:
var jsontext = {"some_unres_var":"val"};
/** #param {jsontext} data */
function getData(data){
console.log(data.some_unres_var);
}
See also http://devnet.jetbrains.com/message/5504337#5504337
To remove the warnings on The WebStorm IDE you can simply uncheck the inspection options for:
Unresolved Javascript function
Unresolved Javascript variable
ps. this will remove the warnings on the IDE, that I don't think is the best idea, because we will lost one of the best utilities in a IDE like Webstorm, which can worsen the quality of our code.
Even so, if you want to follow in the menu: File > Settings > Editor > Inspections we can disable the Javascript warnings
Like the following picture:

Bad type annotation. Unknown type

I keep getting the warning mentioned above but can't figure out why. I've added deps.js and deps.js contains a reference to the type.
Here is the offending code:
goog.provide("MyCompany.MyApp.dom");
MyCompany.MyApp.dom.getArticleAmountInput_=function(){
return document.getElementById("articleAmount");
};
/**
* Gets the article amount input value
* #type {function(this:MyCompany.MyApp.dom):number} */
MyCompany.MyApp.dom.getArticleAmount=function(){
var tmp=this.getArticleAmountInput_();
return (tmp)?tmp.value():undefined;
};
In deps.js:
goog.addDependency('../../MyCompany/MyApp/dom.js', [ 'MyCompany.MyApp.dom'], []);
Code loads in html so it does find the class at runtime. Here is how I compile the code:
java -jar ../../compiler.jar \
--compilation_level=ADVANCED_OPTIMIZATIONS \
--formatting=PRETTY_PRINT \
--warning_level=VERBOSE \
--summary_detail_level=3 \
--js=MyCompany/MyApp/dom.js \
--js=closure/goog/deps.js \
--js_output_file=out.js
And it keeps giving me the warning:
WARNING - Bad type annotation. Unknown type MyCompany.MyApp.dom
[update]
Tried to leave out the goog.provide completely and leave out the js=closure/goog/deps.js when compiling and changed everything to lower case but keep getting the same warning on this code:
//goog.provide("mycompany.myapp.dom");
var mycompany={};
mycompany.myapp={};
mycompany.myapp.dom={};
mycompany.myapp.dom.getArticleAmountInput_=function(){
return document.getElementById("articleAmount");
};
/**
* Gets the article amount input value
* #type {function(this:mycompany.myapp.dom):number} */
mycompany.myapp.dom.getArticleAmount=function(){
var tmp=this.getArticleAmountInput_();
return (tmp)?tmp.value():undefined;
};
[update]
The thing is that when I add a typedef I get warnings that myapp.dom is never defined but when I let the code determine what the type is I get Bad type annotation.
Tried to add a typedef like so:
/**
* #typedef {{getArticleAmount:function(this:myapp.dom):?number}}
*/
myapp.dom;
But don't realy see why as goog.provide should create the myapp.dom and the compiler should know that.
[update]
I have created the following myapp.workflow from constructors. Now the compiler should recognize the type and Eclipse can code assist. Not sure if this is the way to do it but I'll try to re factor a small project.
Setting up the main types in types.js
// source: js/mmyapp/types.js
goog.provide("myapp.types");
/** #constructor */
var gooblediegoog=function(){};
/** #constructor */
gooblediegoog.prototype.WorkFlow=function(){};
/** #constructor */
gooblediegoog.prototype.Dom=function(){};
myapp.types=new gooblediegoog();
A file that isn't used at all in my code but tells Eclipse how to auto complete:
// source: js/myapp/forCodeAssist.js
/** #const {boolean} */
var ALLWAYSFALSE=false;
if(ALLWAYSFALSE){
/**needed for Eclipse autocomplete
* #constructor
*/
var MyApp=function(){};
MyApp.prototype.types=new gooblediegoog();
Window.prototype.myapp=new MyApp();
MyApp.prototype.workflow=new myapp.types.WorkFlow();
MyApp.prototype.dom=new myapp.types.Dom();
}
An implementation of workflow:
// source: js/myapp/workflow.js
goog.provide("myapp.workflow");
goog.require("myapp.types");
goog.require("myapp.dom");
/** #returns number|undefined */
myapp.types.WorkFlow.prototype.createOrder=function(){
return myapp.dom.getArticleAmout();
};
myapp.workflow=new myapp.types.WorkFlow();
window['console'].log(myapp.workflow.createOrder());
This can be converted to a myapp.workflow.createOrder=... syntax by replacing myapp.types.WorkFlow.prototype with myapp.workflow, removing myapp.workflow=new myapp.types.WorkFlow() and removing the goog.require("myapp.types"). Maybe this can be automated in the build/compile process if needed.
I am not sure if creating a single object with the help from a constructor function is much more expensive than just having goog.require create myapp.workflow and adding properties to it as I used to do (and as it's done in closure library).
Anonymous types (namespaces or singletons) don't have specific types in Closure-compiler and cannot be used as a type name in an annotation. Only constructors and interfaces can be used as new type names. (typedefs can be used but are really just shorthand annotations)
In many cases the compiler will correctly infer the types and you will not need to annotate it. In your specific case, it looks like the problem is your use of the this keyword. Using the this keyword in a static object / namespace is dangerous and not supported. The compiler will raise a warning. While you can suppress the warning with a #this annotation, that is not the correct action here as you are not specifically specifying the this reference by using .call or .apply.
The solution is to use the full object name:
/**
* Gets the article amount input value
*/
mycompany.myapp.dom.getArticleAmount=function(){
var tmp=mycompany.myapp.dom.getArticleAmountInput_();
return (tmp)?tmp.value():undefined;
};
For the full technical details, reference the This this is your this post.

Annotating a class received from JSON server call

I am trying to properly annotate all my Javascript code and am still a beginner in this field.
I get objects from a server call that are directly in json. Those objects are passed to functions and I call members directly. It obviously is very error prone while obfuscating so I am trying to annotate everything properly.
My understanding is that (i) I should create a class for this object even though it is never created directly with new and (ii) I should be careful with member names since they are fixed by the server response and should not be changed (or should be aliased beforehand).
I have two questions: are my asumptions correct ? how to do the annotation based on that.
Here is a sample code to illustrate
$.get("url.php", function(data) {
process(data);}, "json"); // <= returns {"a":"abc","b":1}
function process(data) {
$("#someElement").html(data.a + data.b);
}
Here is the class I was planning on creating for closure compilation purposes
/**
* The object that is sent back from the server
* #constructor
*/
function ServerResponse() {
/** #type {string} a */
this["a"] = "";
/** #type {number} b */
this["b"] = 0;
}
Here is the annotation for my process function
/**
* Process data from the server
* #param {ServerResponse} data: the Object sent back from the server
*/
Is my annotation correct? Is it robust to obfuscation?
Thanks a lot for your help
If you quote property names, you need to quote them consistently at every usage. If you haven't see this, you should read:
https://developers.google.com/closure/compiler/docs/api-tutorial3
So that your first snippet would be:
function process(data) {
$("#someElement").html(data['a'] + data['b']);
}
If you are trying to avoid quoting or if you would like the compiler to type check the usage of the properties (quoted properties references are not checked), you should define an extern file to include with the compilation of your source:
/**
* #fileoverview
* #externs
*/
/** #interface */
function ServerResponse() {}
/** #type {string} */
ServerResponse.prototype.a;
/** #type {number} */
ServerResponse.prototype.b;

Categories

Resources