/* @flow */
import type {LintCallback} from './typedef';
import {CLIEngine} from 'eslint';
import {join} from 'path';
import forEach from 'lodash/forEach';
/* eslint-disable lodash/prefer-map */
const defaultConfigFile = join(__dirname, '..', '.eslintrc.yaml');
/**
* A JavaScript linter
*
* @class JSLint
* @param {string} [configFile="webcompiler/.eslintrc.yaml"] - path to the ESLint configuration file
* @see {@link http://eslint.org/ ESLint}
* @example
* import {JSLint} from 'webcompiler';
* // or - import {JSLint} from 'webcompiler/lib/JSLint';
* // or - var JSLint = require('webcompiler').JSLint;
* // or - var JSLint = require('webcompiler/lib/JSLint').JSLint;
*
* const linter = new JSLint();
*/
export class JSLint {
/**
* an internal linter instance
*
* @member {CLIEngine} linter
* @memberof JSLint
* @private
* @instance
*/
linter: CLIEngine;
// eslint-disable-next-line require-jsdoc
constructor(configFile: string = defaultConfigFile) {
this.linter = new CLIEngine({configFile});
}
/**
* Execute the linter
*
* @memberof JSLint
* @instance
* @method run
* @param {Array<string>} paths - an array of paths to files/directories to lint
* @param {LintCallback} callback - a callback function
* @example
* import {join} from 'path';
* import {logLintingErrors} from 'webcompiler';
*
* // lint "index.js" as well as the entire contents of the "src" directory
* linter.run([join(__dirname, 'index.js'), join(__dirname, 'src')], errors => {
* if (errors) {
* return logLintingErrors(errors);
* }
* // there were no linting errors
* });
*/
run(paths: string[], callback: LintCallback) {
const {results} = this.linter.executeOnFiles(paths),
errors = [];
forEach(results, ({messages, filePath: file}) => {
forEach(messages, ({line, column, message, ruleId: rule}) => {
errors.push({file, line, column, message, rule});
});
});
callback(errors.length ? errors : null);
}
}