Supporting Intellisense

Supporting Intellisense

Most people agree that one of the best features of Visual Studio is Intellisense. Having contextual information about class members during development makes the process more efficient. It eliminates a lot of the need to jump back and forth between coding and documentation. Not only does Intellisense give you information about what members are available, but it also provides abbreviated help about parameters and return values. This is a big improvement over the text editor I used on a monochrome monitor when I started my programming career.

A big part of the Intellisense feature is driven by the use of reflection by Visual Studio over the managed types referenced by the project. But this doesn’t work very well with a dynamic language like JavaScript. The approach that the ASP.NET team is using with JavaScript is to leverage XML doc comments. By leveraging XML doc comments, the next version of Visual Studio will be able to provide Intelisense for the ASP.NET AJAX Library as well as the new ASP.NET server controls written in C#, where reflection is more readily available.

XML doc comments provide information about JavaScript code to let the developer know how to use it. The first item typically included is a summary statement, as shown in Listing 4-18. The album object can proclaim to developers that it intends to be a repository for information about an album. This may seem obvious in this discussion, but as the number of classes grows and the use of intuitive names decreases, the need for an Intellisense aid is more apparent.

Listing 4-18
Image from book
<%@ Page Language="C#"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" 
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
    <title>ASP.NET AJAX Intellisense </title>    
    <script type="text/javascript">
    function pageLoad(sender, args) {

        Type.registerNamespace('Wrox.ASPAJAX.Samples');

        Wrox.ASPAJAX.Samples.Album = function(title, artist) {
        /// <summary>Use this method to create a new Album.</summary>
        /// <param name="title" type="String" optional="false" 
mayBeNull="false">The album title.</param>
        /// <param name="artist" type="String" optional="false" 
mayBeNull="false">The album artist.</param>
        /// <returns type="Album">An Album object.</returns>
            this._title = title;
            this._artist = artist;
        }

        Wrox.ASPAJAX.Samples.Album.prototype = {
            get_title: function() {
        /// <summary>Album title accessor.</summary>
        /// <returns  type="String">Album title.</returns>
               return this._title;
            },
            get_artist: function() {
            /// <summary>Album artist accessor.</summary>
            /// <returns type="String">Album artist.</returns.
               return this._artist;
            }
        }


        Wrox.ASPAJAX.Samples.Album.registerClass('Wrox.ASPAJAX.Samples.Album');
        var anAlbum = new Wrox.ASPAJAX.Samples.Album("Round Room", "Phish");   
        alert(anAlbum.get_title()); 
    }
    </script>
</head>
<body>
    <form id="form1" runat="server">
        <asp:ScriptManager ID="ScriptManager1" runat="server" />
    </form>
</body>
</html>
Image from book

Listing 4-18 (Intellisense.aspx) repeats the Album class code from Class.aspx in Listing 4-4 and includes XML doc comments. For each function, there is a summary statement. If a function takes parameters, they are described in param entries, and finally there is information about the return type.

The parameter doc comments indicate whether including the parameter in the function call is optional and whether nulls are allowed. XML doc comments added to enums provide information about the individual fields. The album genre enum with comments is shown in listing 4-19 (also from Intellisense.aspx).

Listing 4-19
Image from book

Wrox.ASPAJAX.Samples.MusicGenre = function() {
    /// <summary>Classifies types of music into a distinct genre.</summary>
    /// <field name="Blues" type="Number" integer="true" static="true" />
    /// <field name="Classical" type="Number" integer="true" static="true" />
    /// <field name="Electronic" type="Number" integer="true" static="true" />
    /// <field name="Folk" type="Number" integer="true" static="true" />
    /// <field name="Industrial" type="Number" integer="true" static="true" />
    /// <field name="Jazz" type="Number" integer="true" static="true" />
    /// <field name="NewAge" type="Number" integer="true" static="true" />
    /// <field name="HipHop" type="Number" integer="true" static="true" />
    /// <field name="Rock" type="Number" integer="true" static="true" />
    /// <field name="WorldFusion" type="Number" integer="true" static="true" />
    throw Error.invalidOperation();
}
Wrox.ASPAJAX.Samples.MusicGenre.prototype = {
    Blues: 1,
    Classical: 2,
    Electronic: 3,
    Folk: 4,
    Industrial: 5,
    Jazz: 6,
    NewAge: 7,
    HipHop: 8,
    Rock: 9,
    WorldFusion: 10
}
Wrox.ASPAJAX.Samples.MusicGenre.registerEnum('Wrox.ASPAJAX.Samples.MusicGenre');
Image from book

For enumerations, the information looks somewhat redundant, but for Visual Studio to consistently pick up and display the correct Intellisense information, the comments should be complete. Another use of the XML doc comments is to include example usage. This can be helpful in providing the developer a quick sample without requiring him or her to switch to the more complete documentation. It is especially useful when working with complex functions for which some contextual information is needed to understand usage; seeing it used in one code snippet is often as helpful as many paragraphs of help information. Listing 4-20 is an example directly from the Error object of the ASP.NET AJAX Library. The popStackFrame function merits an example to aid in its use.

Listing 4-20
Image from book

Error.prototype.popStackFrame = function() {
    /// <summary>
    /// Updates the fileName and lineNumber fields based on the next frame in the
    /// stack trace. Call this method whenever an instance of Error is returned
    /// from a function. This makes the fileName and lineNumber reported in the
    /// FireFox console point to the location where the exception was thrown, not
    /// the location where the instance of Error was created.
    /// </summary>
    /// <example>
    /// function checkParam(param, expectedType) {
    ///     if (!expectedType.isInstanceOfType(param)) {
    ///         var e = new Error("invalid type");
    ///         e.popStackFrame();
    ///         return e;
    ///     }
    /// }
    /// </example>
Image from book