14

I have been using Visual Studio's JavaScript Intellisense functionality for a while now and have mostly been happy with how well it provides suggestions for standard APIs, but I have found that I cannot get Visual Studio to understand configuration objects (i.e. a single object with multiple optional or required properties as an argument to a function).

The official JSDoc syntax suggests that if a parameter is expected to have properties, you create a separate @param line for each and use dot notation:

/**
 * @param {Object} config
 * @param {String} config.name
 * @param {Number} config.gold
 */
function do_it(config) { ... }

However, Visual Studio doesn't recognize this - it renders config, config.name, and config.gold as three separate top-level parameters.

do_it() registers three separate parameters

Worse, the AutoComplete functionality within the method body doesn't recognize the parameters either, much less their types:

Attempting to access methods of config.name yields yellow triangles and no help.

The only solution that appears to come even close in Visual Studio is to write never-called constructor functions with appropriate documentation (@constructor and @property tags), which makes me write a lot of dead code and also go against JavaScript's class-free mentality (which is the reason I use configuration objects in the first place). It doesn't even let me write the configuration object!

Not only that, but I also know that Visual Studio doesn't need it. For instance, when I wrote out a call to this library function, it was able to glean that the argument object needs properties called id, source, and target, and suggested those names when I created an object literal for the function's argument - and without a single line of documentation. Presumably, it came from the simple fact that they were used:

Visual Studio autosuggests these three properties with no documentation comments at all

Granted, the method does throw exceptions if these properties aren't on the object and aren't of the correct type, but still. EDIT: And I recently was able to replicate the effect in my own code somewhat with object literal parameters - I called one function with a well-defined object, and it gave me Intellisense suggestions when I called the function again elsewhere in my code. But I still don't have type information or semantic access within the function body.

Visual Studio obviously understands the concept of configuration objects and is doing some logic to provide suggested properties. What is that algorithm? And how do I exploit it without mangling my code?

Community
  • 1
  • 1
TheHans255
  • 2,059
  • 1
  • 19
  • 36

1 Answers1

8

You are using the correct JSDoc syntax, but as of today Visual Studio just doesn't build the right IntelliSense for parameter objects with named properties. There's currently no other way around this other than the one you refer to, but you can describe the config object in place and avoid writing dead code as you mentioned like this:

/**
 * @typedef  {object} TestConfig
 * @property {string} name
 * @property {number} gold
 *//**
 * @param    {TestConfig} config 
 */
function test(config) {

}

Since we are only using this object for documentation and AutoComplete purposes we don't need to actually code it. This is not much more verbose than the original syntax and has the benefit of having the configuration object documented as well.

About your second question, the IntelliSense you can see for the sigma.js library is derived from parsing the body of the function code itself, not the JSDoc comments. That's why you can still use it when you add the minified "sigma.min.js" build to you project, where comments have been stripped.

You can test this adding parameter validation similar to the one in the library function (although accessing config.name or config.gold in any other manner will also yield the same result):

function do_it(config) {
    if (Object(config) !== config || arguments.length !== 1) throw 'do_it: wrong arguments.';
    if (typeof config.name !== 'string') throw 'config must have a name string field.';
    if (typeof config.gold !== 'number') throw 'config must have a gold number field.';
    ...
}

Results in:

enter image description here

In a similar manner, once you provide enough information the correct type will be inferred:

enter image description here

cviejo
  • 4,388
  • 19
  • 30
  • 1
    The documentation part doesn't work - it does not appear as though VS supports `@typedef`. However, I have found that VS will give the correct types with either a dummy constructor and typedef, or with the parameters of the first call to the function. – TheHans255 Jan 05 '16 at 17:20
  • That's true, it's not documented, but it works, you will get the right parameter properties and their types. As stated above, you don't really need the dummy constructor at all, just to document the ' config' object which can happen right before the function itself. As for the first call to the function, that's assuming the function call is being passed something parseable by VS (like that object literal). I was rather trying to explain why you could see IntelliSense for some libraries, since you're already using JSDoc I'd personally go with the first approach.. – cviejo Jan 05 '16 at 17:30
  • Tested with Visual Studio Community 2015 Version 14.0.23107.0, what version are you using? – cviejo Jan 05 '16 at 17:34
  • Vs 2015 Enterprise 14.0.24720.00 Update 1 – TheHans255 Jan 05 '16 at 17:35
  • Sorry, `@typedef` does work. The "first call" behavior overrides any documentation you provide when trying to get Intellisense inside the function body. – TheHans255 Jan 05 '16 at 17:40
  • Sorry, i wrote non-sense, `@typedef` [is supported and documented](https://msdn.microsoft.com/en-us/library/mt162307.aspx) in Visual Studio 2015. – cviejo Jan 05 '16 at 17:41