Using JSHint inside Visual Studio – the basics
JSHint is great. It’s a linting tool for JavaScript: a simple tool that can very often spot your mistakes before you do. It can save you from a lot of tedious debugging, lets you refactor JavaScript code with greater confidence, and reduces the chances of you deploying broken code to your production server.
I’ve been relying on it day-to-day for the last few months while working on a large JavaScript application, and now I’d be very distressed if I had to work without this instant, zero-effort safety net. So, what does it do?
- It identifies definite, objective errors in your code (e.g., mistyped keywords, mistyped variable names, mismatched parentheses, and other syntactical slip-ups) before they end up in your browser.
- Optionally, it enforces some basic code style consistency rules (e.g., no trailing whitespace, no use of the == operator, etc.), depending on how you configure it</ol> Feature 2 – enforcing style consistency – isn’t hugely beneficial for small, single-developer projects. But for longer-lived, multiple-developer projects, your team will surely benefit in the long run from a few consistency guarantees.
Feature 1 – typo detection – is the killer benefit from my point of view. I’ll show you a good example in a moment.
As you can probably guess, there are two common ways to use JSHint on a project:
* **By integrating it into your build process** (on a CI server). This enforces team-wide consistency.
* **By integrating it into your IDE**. This gives you instant feedback as you code.</ul>
My current project uses both, but primarily I appreciate having it in my IDE. So, **in this post I’ll focus on a Visual Studio extension that makes it easy**. Of course you can also find JSHint plugins for many other IDEs or code editors, such as my other favourite: <a href="https://github.com/uipoet/sublime-jshint" onclick="javascript:_gaq.push(['_trackEvent','outbound-article','http://github.com']);">Sublime Text 2</a>.
#### Why it matters
Here’s an exaggeratedly simple example. Let’s say you have a perfectly OK function like this:
<div class="wp_syntax">
<div class="code">
<pre class="javascript"><span style="color: #003366; font-weight: bold;">function</span> averageHeight<span style="color: #009900;">(</span>heights<span style="color: #009900;">)</span> <span style="color: #009900;">{</span>
<span style="color: #003366; font-weight: bold;">var</span> sum <span style="color: #339933;">=</span> <span style="color: #CC0000;"></span><span style="color: #339933;">,</span> index<span style="color: #339933;">;</span>
<span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">(</span>index <span style="color: #339933;">=</span> <span style="color: #CC0000;"></span><span style="color: #339933;">;</span> index <span style="color: #339933;"><</span> heights.<span style="color: #660066;">length</span><span style="color: #339933;">;</span> index <span style="color: #339933;">+=</span> <span style="color: #CC0000;">1</span><span style="color: #009900;">)</span> <span style="color: #009900;">{</span>
sum <span style="color: #339933;">+=</span> heights<span style="color: #009900;">[</span>index<span style="color: #009900;">]</span><span style="color: #339933;">;</span>
<span style="color: #009900;">}</span>
<span style="color: #000066; font-weight: bold;">return</span> sum <span style="color: #339933;">/</span> heights.<span style="color: #660066;">length</span><span style="color: #339933;">;</span> <span style="color: #009900;">}</span> <span style="color: #003366; font-weight: bold;">var</span> myAverageHeight <span style="color: #339933;">=</span> averageHeight<span style="color: #009900;">(</span><span style="color: #009900;">[</span><span style="color: #CC0000;">1.75</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">1.78</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">1.82</span><span style="color: #009900;">]</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span></pre>
</div>
</div>
Now you decide you want to rename the function just to “average”, since it’s not really specific to heights at all. So you go ahead and change the function signature. But you forget to the change anything else:
<div class="wp_syntax">
<div class="code">
<pre class="javascript"><span style="color: #003366; font-weight: bold;">function</span> average<span style="color: #009900;">(</span>values<span style="color: #009900;">)</span> <span style="color: #009900;">{</span> <span style="color: #006600;">// <-- This is the only line I remembered to change</span>
<span style="color: #003366; font-weight: bold;">var</span> sum <span style="color: #339933;">=</span> <span style="color: #CC0000;"></span><span style="color: #339933;">,</span> index<span style="color: #339933;">;</span>
<span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">(</span>index <span style="color: #339933;">=</span> <span style="color: #CC0000;"></span><span style="color: #339933;">;</span> index <span style="color: #339933;"><</span> heights.<span style="color: #660066;">length</span><span style="color: #339933;">;</span> index <span style="color: #339933;">+=</span> <span style="color: #CC0000;">1</span><span style="color: #009900;">)</span> <span style="color: #009900;">{</span>
sum <span style="color: #339933;">+=</span> heights<span style="color: #009900;">[</span>index<span style="color: #009900;">]</span><span style="color: #339933;">;</span>
<span style="color: #009900;">}</span>
<span style="color: #000066; font-weight: bold;">return</span> sum <span style="color: #339933;">/</span> heights.<span style="color: #660066;">length</span><span style="color: #339933;">;</span> <span style="color: #009900;">}</span> <span style="color: #003366; font-weight: bold;">var</span> myAverageHeight <span style="color: #339933;">=</span> averageHeight<span style="color: #009900;">(</span><span style="color: #009900;">[</span><span style="color: #CC0000;">1.75</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">1.78</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">1.82</span><span style="color: #009900;">]</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span></pre>
</div>
</div>
Now you press Ctrl+S to save the changes. In the tiniest fraction of a second, and without waiting to build your server-side code, the JSHint extension I’m about to show you will return its verdict about your file:
[<img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.stevensanderson.com/wp-content/uploads/2012/08/image_thumb.png" width="651" height="206" />][1]
Well, you’re going to notice this! The first three errors tell you exactly where you’ve forgotten to change “heights” to “values”, and they won’t go away until you fix every last one. The fourth warns you that you’re trying to invoke a function that no longer exists. The fifth tells you it’s quite pointless to have this new “average” function, because nobody uses it.
Even in this simple case it’s very nice to know exactly how many times you forgot to rename the “heights” variable. You can imagine how valuable (and reassuring) it is in more complex refactorings such as extracting a function.
I’m not saying this eliminates the need for automated testing. This merely adds to JavaScript a subset of the kinds of code validity checks that you might be accustomed to in C# or another strongly-typed language.
In addition, the kinds of optional common stylistic rules that JSHint can enforce include:
* Require braces around for/if/while/etc blocks
* Don’t leave “debugger” statements in your code
* Always use single/double quote characters
* Allow only one “var” statement per function scope, to ensure you don’t get hit by the subtle [that-closure-isn’t-really-closed][2] bug
* Well, just look at the <a href="http://www.jshint.com/" onclick="javascript:_gaq.push(['_trackEvent','outbound-article','http://www.jshint.com']);">list of “warn” options on the homepage</a>
#### Possible drawbacks of JSHint
In the interest of balance, let me try to give you advance notice of a few downsides to using JSHint, which actually apply to pretty much any linting tool:
* **It’s best when you’re writing fresh new code**. When writing new code files, you can keep them compliant with your rules with little effort right from the beginning. But it’s not easy to start using JSHint on a large legacy codebase, because it will initially report thousands of violations. You can either invest a big chunk of time in cleaning everything up, or you can use **/\*ignore jslint \*/** comments to ignore your old files, removing those comments one-by-one as you clean up each file over the long term.
* **It’s reliable, but not deeply sophisticated**. JavaScript is fully dynamic, so the linter can’t know whether or not a given object will have a certain property at runtime. So, if for example you’re renaming *properties* as opposed to *variables*, don’t expect JSHint to find all the places where the old property name is still referenced. Don’t get caught believing that “*no JSHint errors”* guarantees “*no bugs”*.
* **It needs a bit of configuration to give the best results**. Depending on how you and your IDE work, you’ll need to toggle a bunch of checkboxes in the early days. You’ll get very annoyed if your IDE persistently inserts or reformats code in a way that violates your JSHint rules. Change the IDE settings or the JSHint settings or both.
* **You need to start tracking global variables**. In the long run, this is a benefit not a drawback, but it might feel like extra work at first. If you use third-party libraries whose APIs live in a global (e.g., **$** for jQuery, **ko** for Knockout), you must explicitly tell JSHint about them otherwise it thinks you’re referencing undefined things. Eventually, though, you’ll be glad to have an unambiguous list of your dependencies.
#### So, what’s JSLint and how does it relate to JSHint?
Historically, <a href="http://jshint.com/" onclick="javascript:_gaq.push(['_trackEvent','outbound-article','http://jshint.com']);">JSHint</a> is derived from the longer-established <a href="http://jslint.com/" onclick="javascript:_gaq.push(['_trackEvent','outbound-article','http://jslint.com']);">JSLint</a> project from Douglas Crockford. The <a href="http://anton.kovalyov.net/2011/02/20/why-i-forked-jslint-to-jshint/" onclick="javascript:_gaq.push(['_trackEvent','outbound-article','http://anton.kovalyov.net']);">reason why JSHint exists</a> is just to offer more flexibility: JSHint has a modest set of rules derived from common use, whereas JSLint is stricter and requires you to code exactly like the legendary Mr Crockford does.
The following Visual Studio extension lets you choose between JSLint and JSHint with a simple config option. Try out both and see which one you like.
#### Integrating JSHint into Visual Studio 2010
Yes, I know Visual Studio 2012 was just released this week! We’ll get to that in a minute. Not everyone upgrades during the first week…
The VS extension I’ve been using for the last few months is called <a href="http://visualstudiogallery.msdn.microsoft.com/961e6734-cd3a-4afb-a121-4541742b912e" onclick="javascript:_gaq.push(['_trackEvent','outbound-article','http://visualstudiogallery.msdn.microsoft.com']);">JSLint for Visual Studio 2010</a>. It’s free and <a href="http://jslint4vs2010.codeplex.com/" onclick="javascript:_gaq.push(['_trackEvent','outbound-article','http://jslint4vs2010.codeplex.com']);">open source</a>, and you can install it directly from inside VS. Go to **Tools** > **Extension Manager**. Click **Online Gallery** then in the search box (top-right), enter **jslint**.
[<img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.stevensanderson.com/wp-content/uploads/2012/08/image_thumb1.png" width="871" height="229" />][3]
Once it’s installed, you’ll find a new menu entry: **Tools** > **JS Lint Options**. Personally, I like to set it up like this:
[<img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.stevensanderson.com/wp-content/uploads/2012/08/image_thumb2.png" width="757" height="226" />][4]
[<img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.stevensanderson.com/wp-content/uploads/2012/08/image_thumb3.png" width="756" height="208" />][5]
I’m not even going to discuss the multitude of code style options represented by the big grid of checkboxes. If you’ve coded JavaScript for a while, you probably have plenty of opinions of your own.
Notice that you can export and import configurations as XML files. You’ll probably want to store a standard team-wide setup in source control.
Now when you’ve got a JavaScript file open, any time you hit **Ctrl+S**, the Visual Studio extension will populate the IDE’s “Error” pane with any issues it found – extremely quickly, because it already has a live JavaScript runtime loaded in memory. Double-click to jump to that line. Either fix it, or modify your config settings to make the linter more tolerant.
**Issues with this extension**
Of course, it’s not totally perfect. Here are a couple of minor niggles I’ve experienced with this extension:
* I don’t see a way of making it load project-specific rulesets. This means that all of the projects you work on will need to share the same configuration (or you have to keep importing different configurations manually).
* It collects errors from every JavaScript file you open. So for example if you open **jquery-x-x-x.js** to see how something is implemented, JSLint for VS2010 will freak out and report more than 1,000 errors. The errors don’t go away when you close that particular tab, so you must manually right-click on the error list and choose **Clear JS Lint Errors**. Not a big deal, but adds a touch of friction.
#### Integrating JSHint into Visual Studio 2012
Unfortunately, there isn’t yet a “JSLint for Visual Studio 2012” on the extensions gallery, or at least not one that I could find. And if you try to download <a href="http://visualstudiogallery.msdn.microsoft.com/961e6734-cd3a-4afb-a121-4541742b912e" onclick="javascript:_gaq.push(['_trackEvent','outbound-article','http://visualstudiogallery.msdn.microsoft.com']);">the .vsix file for the VS2010 version</a>, it won’t let you install it into VS2012:
[<img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.stevensanderson.com/wp-content/uploads/2012/08/image_thumb4.png" width="488" height="281" />][6]
So, how come the screenshot earlier in this blog post shows it running in VS2012? Well, I guess the extension’s developers haven’t got round to testing on VS2012 yet, but if you’re impatient and want it installed *right now*, it’s just a matter of modifying the “manifest” in the .vsix file to make it allow installation. Here’s what I did:
1. Rename **JSLint.VS2010.vsix** to **JSLint.VS2010.zip**. Turns out these things are really zip archives. Extract the files to a temporary folder.
2. Open **extension.vsixmanifest** in Notepad.
3. Find **<VisualStudio Version=”10.0″>** and change it to **<VisualStudio Version=”11.0″>**.
4. Zip all the files back up, and rename the result so it has a **.vsix** extension.
5. Install it.
This is **totally unsupported, off piste, entirely at your own risk, and no technical support questions will even be acknowledged much less answered**. But hey, it seems happy enough on my machine:
[<img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.stevensanderson.com/wp-content/uploads/2012/08/image_thumb5.png" width="734" height="156" />][7]
Hopefully the extension’s developers will get a chance to make VS2012 support official in the near future. Maybe you (yes – actually *you*!) could <a href="http://jslint4vs2010.codeplex.com/SourceControl/list/patches" onclick="javascript:_gaq.push(['_trackEvent','outbound-article','http://jslint4vs2010.codeplex.com']);">submit a patch</a>. This is open source, after all.