One of the more cooler updates to Brackets recently was the linting API. This came out back in October and I wrote up a review of the API for the Brackets blog. It basically took 90% of the boiler plate code for linters and made it a heck of a lot simpler.

One thing that wasn't possible with the linter (or not easy at least) was handling linters that needed to do something asynchronously. One of my extensions, W3CValidation, made use of a remote API to perform validation on HTML. (I've also got a wrapper for another HTML validator: HTMLHint.)

Brackets Sprint 38 lands new support for handling asynchronous linters. The release notes aren't terribly clear on how you use this feature. They link to the bug report, which mainly just mentions scanFileAsync. Luckily the developer who landed the feature (and one who has helped out a lot on some of my extensions) shared an example that I was able to steal from. Credit for my update goes to busykai. Here is the entirety of the main.js file for my W3CValidator extension.

/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
/*global define, brackets, $, window, W3CValidator */

define(function (require, exports, module) {
	'use strict';
	
	var CodeInspection			= brackets.getModule("language/CodeInspection"),
		AppInit                 = brackets.getModule("utils/AppInit");

	require('w3cvalidator');
	
	function _handleValidation(text, fullPath) {
		var response = new $.Deferred();
		var result = {errors:[]};
			
		W3CValidator.validate(text, function (res) {
			var messages = res.messages;
			
			if (messages.length) {
									
				messages.forEach(function (item) {
					console.log('W3CValidation messsage ',item);
					var type = CodeInspection.Type.ERROR;
					if (item.type === "warning") {
                        type = CodeInspection.Type.WARNING;
                    }
					result.errors.push({
						pos: {line:item.lastLine-1, ch:0},
						message:item.message,
						type:type
					});
					
				});
		  
			}

			response.resolve(result);        
			
		}); 

		return response.promise();

	}
		
	AppInit.appReady(function () {


		CodeInspection.register("html", {
			name: "W3CValidation",
			scanFileAsync: _handleValidation
		});
		
	});
	
	
});

First - note the use of scanFileAsync in the CodeInspection.register method. I'm telling it to use _handleValidation and to expect an async response. The function then simply creates a new deferred object and returns the promise. My handler calls off to my W3C service and when done, massages the results into the expected format and resolves the promise.

And yeah - that's it. But as I said, it wasn't immediately obvious to me based on the release notes so I hope this helps others.