Skip to content

Instantly share code, notes, and snippets.

@xt0rted
Created January 9, 2014 23:03
Show Gist options
  • Save xt0rted/8343782 to your computer and use it in GitHub Desktop.
Save xt0rted/8343782 to your computer and use it in GitHub Desktop.
A grunt task to generate JSLint style reports for use with TeamCity's XML report processing. The code is based on the built-in tslint report formatters and https://github.com/Bartvds/tslint-path-formatter
<jslint>
<file name="App/app.ts">
<issue line="1" char="13" reason="missing whitespace"/>
<issue line="2" char="5" reason="comment must start with a space"/>
</file>
<file name="App/some-folder/data.ts">
<issue line="1" char="13" reason="missing whitespace"/>
<issue line="2" char="19" reason="missing whitespace"/>
<issue line="2" char="20" reason="missing whitespace"/>
<issue line="2" char="21" reason="expected variableDeclarator: 'SOME_VARIABLE' to have a typedef."/>
<issue line="3" char="9" reason="variable name must be in camelcase or uppercase"/>
<issue line="3" char="25" reason="missing whitespace"/>
<issue line="3" char="26" reason="&quot; should be '"/>
<issue line="3" char="26" reason="missing whitespace"/>
<issue line="3" char="33" reason="expected variableDeclarator: 'ANOTHER_variable' to have a typedef."/>
<issue line="3" char="37" reason="missing whitespace"/>
<issue line="3" char="38" reason="missing whitespace"/>
<issue line="3" char="44" reason="expected variableDeclarator: 'yup' to have a typedef."/>
</file>
</jslint>
'use strict';
var XMLWriter = require('xml-writer');
var Linter = require('tslint');
var hasProp = Object.prototype.hasOwnProperty;
module.exports = function (grunt) {
grunt.registerMultiTask('tslint-teamcity', 'A linter for TypeScript', function () {
var options = this.options({
formatter: 'json'
});
if (grunt.file.exists(options.logLocation)) {
grunt.file.delete(options.logLocation);
}
var result = true;
var output = new XMLWriter(true);
output.startElement('jslint');
this.filesSrc.forEach(function (filepath) {
if (!grunt.file.exists(filepath)) {
grunt.log.warn('Source file "' + filepath + '" not found.');
} else {
var contents = grunt.file.read(filepath);
var linter = new Linter(filepath, contents, options);
var lintResult = linter.lint();
if (lintResult.failureCount > 0) {
appendErrors(output, lintResult.output);
result = false;
}
}
});
output.endElement();
if (!result) {
var xmlResult = output.toString();
grunt.log.error(xmlResult);
grunt.file.write(options.logLocation, xmlResult);
}
return result;
});
function appendErrors(output, failures) {
var files = {};
var data = [];
if (typeof failures === 'string') {
failures = JSON.parse(failures);
}
failures.forEach(function (failure) {
var fileName = failure.name;
var res;
if (hasProp.call(files, fileName)) {
res = files[fileName];
} else {
files[fileName] = res = {
file: fileName,
errors: []
};
data.push(res);
}
res.errors.push({
reason: failure.failure,
line: failure.startPosition.line + 1,
character: failure.startPosition.character + 1
});
});
data.forEach(function (res) {
var errors = res.errors;
output.startElement('file');
output.writeAttribute('name', res.file);
errors.sort(function (a, b) {
if (a && !b) {
return -1;
} else if (!a && b) {
return 1;
}
if (a.line < b.line) {
return -1;
} else if (a.line > b.line) {
return 1;
}
if (a.character < b.character) {
return -1;
} else if (a.character > b.character) {
return 1;
}
return 0;
});
errors.forEach(function (error) {
output.startElement('issue')
.writeAttribute('line', '' + error.line)
.writeAttribute('char', '' + error.character)
.writeAttribute('reason', '' + error.reason)
.endElement();
});
output.endElement();
});
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment