If you look around within the WinJS source code files, you’ll see a curious structure for commenting functions. For example, here’s what we see for WinJS.Namespace.define:

function define(name, members) {
    /// <signature helpKeyword=”WinJS.Namespace.define”>
    /// <summary locid=”WinJS.Namespace.define”>
/// Defines a new namespace with the specified name.
    /// </summary>
    /// <param name=”name” type=”String” locid=”WinJS.Namespace.define_p:name”>
    /// The name of the namespace. This could be a dot-separated name for nested namespaces.
    /// </param>
    /// <param name=”members” type=”Object” locid=”WinJS.Namespace.define_p:members”>
    /// The members of the new namespace.
    /// </param>
    /// <returns type=”Object” locid=”WinJS.Namespace.define_returnValue”>
/// The newly-defined namespace.
/// </returns>
/// </signature>
return defineWithParent(global, name, members);

On first glance, you’ll wonder why someone wrote comments like this that are somewhat hard to read. But there is a real purpose: they are what provide IntelliSense data to Visual Studio. That is, because IntelliSense provides you with immediate, in-line documentation when you start writing code, there’s no need for you to look at the source code for functions that you’re consuming to understand how they work. That is, when you type out WinJS.Namespace. and highlight define, you’ll see this pop up:

Intellisense comments 1b

When you continue to enter in define, IntelliSense will pop up the details of the function–you can see that all this information is coming straight from those code comments:

Intellisense comments 2b

There is nothing special about WinJS’ use of these kinds of comments: you can use them in your own code to provide IntelliSense for your own functions. The documentation for doing this is on JavaScript IntelliSense (the overview) and XML Documentation Comments (the details). Here’s a simple example with a function that doesn’t actually do anything meaningful:

function myFunction(item, identifier, options) {
    /// <signature helpKeyword=”MyNamespace.myFunction”>
    /// <summary locid=”MyNamespace.myFunction”>
    /// Does some nifty stuff with the parameters you provide.
    /// </summary>
    /// <param name=”item” type=”Object” locid=”MyNamespace.myFunction_p:item”>
    /// The object to process.
    /// </param>
    /// <param name=”identifier” type=”String” locid=”MyNamespace.myFunction_p:identifier”>
    /// Another parameter that I just made up.
    /// </param>
    /// <param name=”options” type=”Object” locid=”MyNamespace.myFunction_p:options”>
    /// A fine ubiquitous catch-all parameter.
    /// </param>
    /// <returns type=”Object” locid=”MyNamespace.myFunction_returnValue”>
    /// Whatever it is we emit from this function.
    /// </returns>
    /// </signature>
    item.identifier = identifier;
    item.options = options;
    return item;

Now when you start typing out myFunction(, you’ll see this:

Intellisense comments 3

As you enter each parameter, the bold highlight in the first line will change and the description at the bottom will update as well.

The other piece to this story is that if you’re working in another .js file and referencing functions in another, you’ll want to add a reference comment at the top to those other files:

/// <reference path=”ScriptFile1.js” />

This is what tells Visual Studio to scan that other file and extract those IntelliSense comments from it. You’ll see this at the top of the WinJS file ui.js, in fact:

/// <reference path=”ms-appx://Microsoft.WinJS.1.0/js/base.js” />
/// <reference path=”ms-appx://Microsoft.WinJS.1.0/js/ui.js” />


One Comment

  1. philk
    Posted May 8, 2013 at 9:41 am | Permalink

    I still find the use of XML and /// offensive. JavaDoc would have been much easier to write and parse with the eye.