Auto-Generate Visual Studio VsDoc for JavaScript l

2019-05-17 16:42发布

问题:

I'm in the process of refactoring my JavaScript library to utilize a single namespace. We have ~200 modules, which previously registered themselves as jQuery plugins or on the global object (bad). In the past dispensation, to get Intellisense working, I added module references for each module (from which I wanted Intellisense) as a

/// <reference path="" />

to the top of every module file.

Everything about the previous dispensation was flawed, fragile and inelegant.

I hope to fix that in the new dispensation. One of the primary goals of this refactoring is to make it easy for new developers to get started working in the library, and Intellisense is of great benefit.

Currently, I'm concatenating all of the *.js files into a single nameSpace-vsdoc.js file. Every method of every class is documented using vsdoc syntax. Every module uses that, single vsdoc reference. This works OK, but it's clumsy. Intellisense works 300% better than before, but it's still not accurate enough. It misses lots of my xml documentation and it doesn't recurse well into methods/classes which return even slightly complicated objects.

YUI Doc offers a way to build documentation from the JsDoc syntax, but that doesn't help with Intellisense. A deep soul-googling has failed to reveal any 3rd party solutions.

Are there any tools to generate VsDocs in a more Intellisense-intelligent way?

UPDATE:

After some extensive thought, testing and incremental refactorings, I have a basic namespace that looks like this jsFiddle.

This enables me to write loosely couple modules in self-executing functions, which register the desired methods on the namespace. All of the modules begin with:

/// <reference path="~/js/NameSpace-vsdoc.js" />

I generate this vsdoc with a simple Perl script, which I've attached to a VS 2010 build event:

use strict;

my $dir = $ARGV[0];
my $destfile = "$dir\\js\\NameSpace-vsdoc.js";

unlink($destfile);

my $js = "";
$js .= extractFile("$dir\\js\\_first-vsdoc.js");
$js .= extractFile("$dir\\js\\NameSpace.js");
$js .= extract("$dir\\js\\modules");
#Add additional directories as needed
$js .= extractFile("$dir\\js\\_last-vsdoc.js");

open(VSDOC, "> $destfile") or die("Cannot open vsdoc file: $destfile ; $!");
print VSDOC $js;
close(VSDOC); 

sub extract
{
    my $ret = "";
    my $path = $_[0];
    opendir(JSDIR, $path) or die("Cannot open js directory: $path ; $!");
    while((my $filename = readdir(JSDIR)))
    {
        if($filename =~ /.*\.js$/ &&
           $filename !~ /-vsdoc/ &&
           $filename !~ /_first/ &&
           $filename !~ /_last/ &&
           $filename !~ /.min\.js/) 
        {
            $ret .= extractFile("$path\\$filename");
        }
    }
    closedir(JSDIR);
    return $ret;
}

sub extractFile
{
    my $ret = "";
    my $filename = $_[0];
    open(JSFILE, "$filename") or die("Cannot open js file: $filename ; $!");
    while((my $line = <JSFILE>)) 
    {
        if($line !~ m/-vsdoc\.js/ )
        {
            $ret .= $line;         
        }
    }
    close(JSFILE);
    return $ret;
}

printf("Finished generating NameSpace vsdoc.\n");

The _first-vsdoc.js and _last-vsdoc.js files wrap the entire contents in a self-executing function. I then pass the resulting vsdoc to Closure Compiler, YUI Compressor and Uglify as needed/appropriate.

This process works much better than before, but it is still not without its flaws.

Starting from scratch, in NewModule.js which references NameSpace-vsdoc.js, I get proper Intellisense:

Ns.register() //visible
Ns.controls.register() //visible
Ns.actions.register() //visible

However, when I define NewModule.js as (and compile):

(function _alertClosure() {
    Ns.register('alert', function alert(someText) {
        ///insert proper vsdoc style comment
    });
}());

I do not get proper Intellisense for:

Ns.alert() //no Intellisense help

which is perplexing, because it works so well on sub-namespaces. I'm forced to do this:

Ns.alert = Ns.alert || Ns.register('alert', function ....

Compile, and suddenly (obviously) Intellisense works as expected.

Intellisense works with chained methods using jQuery's vsdoc (which I have studied closely in constructing this process) and jQuery doesn't resort to the y.x = y.x || new x() trickery to make it happen.

So here is the revised question: From a structural standpoint, the only discernible difference I can perceive between jQuery's vsdoc and my own is that jQuery assembles the entire namespace inside the same closure. My namespace and each of my modules are wrapped in individual closures. In comparison, my vsdoc looks like a long string of self-executing functions.

There is simply too much risk associated with forgoing the closure/module pattern; and it's difficult to test the hypothesis in isolation. Intellisense works well when the library is small and therefore unable to generate thousands of "Javascript Intellisense Message: C:\\js\NameSpace-vsdoc.js(40:16) : Object required" errors.

Ideas?

回答1:

I agree with @Ilya Volodin. ReSharper is a great tool for visual studio. I use it for only a month and I can not do without.

This does not answer your question but it would be very useful to you.

Here is a good summary that can be found on the official website:

"ReSharper is a renowned productivité Tool That Makes Microsoft Visual Studio IDE is much better. Thousands of. NET developers worldwide wonder how they 've ever Lived without ReSharper's code inspections, automated refactorings, blazing fast shipping, and coding assistance."