The format for JavaScript doc comments
Xml documentation annotations are going to drive JavaScript IntelliSense in Visual Studio Orcas (the next version of Visual Studio). For more than a year now, we've been including xml doc comments to all public APIs in the Microsoft Ajax Library (which are a great place to check out some examples of those comments). We also use the doc comments to automatically generate parameter validation code in the debug version of our scripts.
The format we've been using is an extension of the format that C# and VB.NET are using so it should look familiar to .NET developers. The main differences are the additional attributes we added to convey the (optional) type information that is not provided by the language itself and the place where those comments are written.
Doc comment position
In C# or VB.NET, the doc comment are written before what they describe:
/// <summary> /// Summary description for Class1 /// </summary> public class Class1
In JavaScript, we decided to put that information *inside* what it describes so that it can be available at runtime: JavaScript has the interesting feature that calling toString on a function returns the code of this function (when it's propertly implemented), including the comments and thus the doc comments. Here's a similar example in JavaScript where the documentation is written inside of a class constructor:
MyNamespace.Class1 = function() { /// <summary> /// Summary description for Class1 /// </summary>
Another difference with C# or VB.NET is that property and event accessors are two different entities in JavaScript. For this reason, we had to choose where the documentation should be for those members. Properties should be documented in the getter and events in the "adder" for this reason:
get_myProperty: function() { /// <value>Documentation goes on the getter.</value> return this._myProperty; }, set_myProperty: function(value) { // No doc comments here this._myProperty = value; }
Doc comment tags
The locid attribute
Most of the tags that I'm about to describe can have their description text inside of the tag itself or the tag can reference an external description using an identifier as the value of the locid attribute. This of course enables documentation to be localized.
The choice of the identifier is free but our team is using the following convention (the identifiers are actually being automatically generated by our preprocessor):
- “T:J#MyNameSpace.MyType” for types
- “M:J#MyNameSpace.MyType.myMethod” for methods (use #ctor as the method name for the constructor)
- “P:J#MyNameSpace.MyType.myProperty” for properties (in this case the getter would be get_myProperty)
- “F:J#MyNameSpace.MyType.myField” for fields
- “E:J#MyNameSpace.MyType.myEvent” for events (in this case the adder would be add_myEvent)
Type attributes
The param, returns, value and field tags that are described below all share the same description of types using attributes. All type information is always optional but you should note that not specifying the type is not the same as specifying type="Object" as everything is not an instance of Object in JavaScript.
The type attribute is used to specify the name of the type of the parameter, return value, property or field.
There are a few cases though where that type is not enough. Namely, in JavaScript, there is no integer type, only a generic Number type. For that reason, and because it's often useful to make that distinction, you can explicitly specify that something is an integer by using both Number as the type and setting the integer attribute to true:
/// <field name="index" type="Number" integer="true"/>
Similarly, DOM elements don't have a type that's well-defined across all browsers. You can specify that somthing is a DOM element by setting the domElement attribute to true. No type should be specified in this case.
Recent research shows that non-null types are extremely useful and should probably represent the norm rather than the exception. For that reason, we added the mayBeNull attribute and made its default value false.
Finally, if the type is Array, it may be desirable to specify the type of the elements of the array (JavaScript has only one variant array type, there is no int[] or String[]). The elementType, elementInteger, elementDomElement and elementMayBeNull are the equivalents for the array elements of the type, integer, domElement and mayBeNull attributes.
<summary locid="descriptionID">Description</summary>
The summary tag can be used in a constructor to describe its class, interface or enumeration, or inside a method, property getter or event "adder" to describe respectively the method, property or event.
<param name="parameterName"
mayBeNull="true|false" optional="true|false"
type="ParameterType" parameterArray="true|false"
integer="true|false" domElement="true|false"
elementType="ArrayElementType" elementInteger="true|false"
elementDomElement="true|false"
elementMayBeNull="true|false">Description</param>
The param tag is used to describe the parameters of a method or constructor. The param tags should be in the same order as the method or constructor's parameters and have the same names.
Optional parameters (which are a way to work around the inexistence of overloads in JavaScript) can be specified using the optional attribute. Optional parameters should come last in the list of parameters and it's good practice to put the "most optional" parameters last.
The parameterArray attribute can be used on the last parameter to specify that this parameter may be repeated as many times as the caller desires. A typical example of this is String.format, which can take as many arguments as the format string enables.
<returns
type="ValueType" integer="true|false" domElement="true|false"
mayBeNull="true|false" elementType="ArrayElementType"
elementInteger="true|false" elementDomElement="true|false"
elementMayBeNull="true|false">Description</returns>
The returns tag is used to describe the return value of a method. It should be used only if the function returns a value (in other words if it contains a return statement that is not just "return;").
<value
type="ValueType" integer="true|false" domElement="true|false"
mayBeNull="true|false" elementType="ArrayElementType"
elementInteger="true|false" elementDomElement="true|false"
elementMayBeNull="true|false"
locid="descriptionID">Description</value>
The value tag describes a property (which shouldn't have a summary tag).
<field name="fieldName" type="FieldType"
integer="true|false" domElement="true|false" mayBeNull="true|false"
elementType="ArrayElementType" elementInteger="true|false"
elementDomElement="true|false" elementMayBeNull="true|false"
locid="descriptionID">Description</field>
The field tag (which doesn't exist in C# and VB.NET because in those languages the summary tag can be used) is used inside of a class, interface or enumeration constructor to describe a field. A field can't be described near the field itself in JavaScript because the field itself doesn't have a body to contain that description.
<reference path="path/to/the/script/reference.js"
assembly="Assembly.Name" name="ScriptResourceName.js"/>
The reference tag is used by Visual Studio to describe a dependency a script has with another script file. This enables the IDE to provide IntelliSense on the namespaces and types that are defined in this other file. This tag should be at the top of the file, outside of any code.
The description
The contents of the description itself, whether the tag is summary, param, returns, field or value, is described by the exact same convention that works for C# and VB.NET doc comments. It can be plain text or text containing other XML tags, as described here:
http://msdn.microsoft.com/en-us/library/5ast78ax(VS.80).aspx
What's next?
This is the convention we're using to document and enhance our scripts and we encourage you to do the same, whether you use Microsoft Ajax or not if only to give your users IntelliSense in Visual Studio.
Similarly, there is no reason why Visual Studio should be the only IDE to handle XML doc comments. We would love it if other IDEs chose to use that format to provide better IntelliSense (or auto-completion).
In a future post, I'll describe how you can extract those XML documentation comments to build usable documentation using existing tools that were designed for managed code.
UPDATE: added the optional attribute for params, which I had omitted.
UPDATE 2: Omar Khan gave a great talk at Mix 07 on the new features in Visual Studio Orcas. Around minute 45, he starts demonstrating JavaScript IntelliSense:
http://sessions.visitmix.com/default.asp?event=1011&session=2012&pid=DEV14&disc=&id=1523&year=2007&search=DEV14
UPDATE 3: added "J#" to naming convention for the locids, to enable managed code and script to implement the same namespaces without a collision in the locids. Also removed locid from param and returns.
UPDATE 4: ScriptDoc, the documentation extraction tool that builds xml files from these doc comments for consumption by Sandcastle, is now available on Codeplex.