Skip to content

Instantly share code, notes, and snippets.

@EWhite613
Created August 2, 2016 15:00
Show Gist options
  • Save EWhite613/0fd86b61d3c24a37a2d50469df536d54 to your computer and use it in GitHub Desktop.
Save EWhite613/0fd86b61d3c24a37a2d50469df536d54 to your computer and use it in GitHub Desktop.
Fix broccoli-lint-eslint
'use strict';
/* eslint global-require: 0, consistent-return: 0 */
var Filter = require('broccoli-persistent-filter');
var CLIEngine = require('eslint').CLIEngine;
var md5Hex = require('md5-hex');
var stringify = require('json-stable-stringify');
var path = require('path');
var escapeStringRegexp = require('escape-string-regexp');
var BUILD_DIR_REGEXP = new RegExp('(' + escapeStringRegexp(path.sep) + ')?build(' + escapeStringRegexp(path.sep) + ')?$');
var IGNORED_FILE_MESSAGE_REGEXP = /(?:File ignored by default\.)|(?:File ignored because of a matching ignore pattern\.)/;
/**
* Calculates the severity of a eslint.linter.verify result
* @param {Array} result Eslint verify result array
* @returns {Number} If the returned number is greater than 0 the result contains errors.
*/
function getResultSeverity(result) {
// count all errors
return result.reduce(function (previous, message) {
if (message.fatal) {
return previous + 1;
}
if (message.severity === 2) {
return previous + 1;
}
return previous;
}, 0);
}
/**
* Ignores messages that are about ignored files as they are intended
* but we are processing a file at a time
*
* @param {Array} errors result errors
* @returns {Array} filtered errors
*/
function filterIgnoredFileMessages(errors) {
return errors.filter(function (error) {
return !IGNORED_FILE_MESSAGE_REGEXP.test(error.message);
});
}
/**
* Filters all ignored file messages from result object
* @param {Object} result result errors
* @returns {Object} filtered results
*/
function filterAllIgnoredFileMessages(result) {
var resultOutput = result;
resultOutput.results.forEach(function (resultItem) {
resultItem.messages = filterIgnoredFileMessages(resultItem.messages);
});
return resultOutput;
}
function resolveInputDirectory(inputNode) {
if (typeof inputNode === 'string') {
return inputNode;
}
// eslint-disable-next-line no-underscore-dangle
var nodeInfo = inputNode.__broccoliGetInfo__();
if (nodeInfo.nodeType === 'source') {
return nodeInfo.sourceDirectory;
}
if (nodeInfo.inputNodes.length > 1) {
// eslint-disable-next-line max-len
var result = resolveInputDirectory(nodeInfo.inputNodes[0])
console.log(result)
for(var i = 1;i<nodeInfo.inputNodes.length; i++){
if ( resolveInputDirectory(nodeInfo.inputNodes[i]) !== result){
throw new Error('EslintValidationFilter can only handle one:* broccoli nodes, but part of the given input pipeline is a many:* node. (broccoli-merge-trees is an example of a many:* node) Please perform many:* operations after linting.');
}
}
return result
}
return resolveInputDirectory(nodeInfo.inputNodes[0]);
}
/**
* Uses the content of each file in a given tree and runs eslint validation on it.
* @param {Object} inputNode Tree from broccoli.makeTree
* @param {{config: String, rulesdir: String, format: String}} options Filter options
* @returns {EslintValidationFilter} Filter obconfig @constructor
*/
function EslintValidationFilter(inputNode, options) {
if (!(this instanceof EslintValidationFilter)) {
return new EslintValidationFilter(inputNode, options);
}
this.options = options || {};
var eslintOptions = this.options.options || {};
// default ignore:true option
if (typeof eslintOptions.ignore === 'undefined') {
eslintOptions.ignore = true;
}
// default is to persist filter output
if (typeof this.options.persist === 'undefined') {
this.options.persist = true;
}
// call base class constructor
Filter.call(this, inputNode, this.options);
// set formatter
if (typeof this.options.format === 'function') {
this.formatter = this.options.format;
} else {
// eslint-disable-next-line global-require
this.formatter = require(this.options.format || 'eslint/lib/formatters/stylish');
}
this.cli = new CLIEngine(eslintOptions);
this.eslintrc = resolveInputDirectory(inputNode);
this.testGenerator = this.options.testGenerator;
if (this.testGenerator) {
this.targetExtension = 'lint-test.js';
}
}
module.exports = EslintValidationFilter;
EslintValidationFilter.prototype = Object.create(Filter.prototype);
EslintValidationFilter.prototype.constructor = EslintValidationFilter;
EslintValidationFilter.prototype.extensions = ['js'];
EslintValidationFilter.prototype.targetExtension = 'js';
EslintValidationFilter.prototype.baseDir = function baseDir() {
return __dirname.replace(BUILD_DIR_REGEXP, '');
};
EslintValidationFilter.prototype.cacheKeyProcessString = function cacheKeyProcessString(content, relativePath) {
function functionStringifier(key, value) {
if (typeof value === 'function') {
return value.toString();
}
return value;
}
return md5Hex([content, relativePath, stringify(this.options, { replacer: functionStringifier }), stringify(this.cli.getConfigForFile(path.join(this.eslintrc, relativePath)))]);
};
EslintValidationFilter.prototype.processString = function processString(content, relativePath) {
// verify file content
var configPath = path.join(this.eslintrc, relativePath);
var output = this.cli.executeOnText(content, configPath);
var filteredOutput = filterAllIgnoredFileMessages(output);
var toCache = {
lint: output,
output: content
};
if (this.testGenerator) {
var result = filteredOutput.results[0];
var messages = result.messages;
toCache.output = this.testGenerator(relativePath, messages, result);
}
return toCache;
};
EslintValidationFilter.prototype.postProcess = function postProcess(fromCache) {
var lint = fromCache.lint;
var output = fromCache.output;
// if verification has result
if (lint.results.length && lint.results[0].messages.length) {
// log formatter output
console.log(this.formatter(lint.results));
if (getResultSeverity(lint.results) > 0) {
if ('throwOnError' in this.internalOptions && this.internalOptions.throwOnError === true) {
// throw error if severe messages exist
throw new Error('severe rule errors');
}
}
}
return {
output: output
};
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment