Skip to content
This repository has been archived by the owner on Aug 7, 2023. It is now read-only.

Commit

Permalink
Use ESLint's CLIEngine API rather than the command line (fixes #797)
Browse files Browse the repository at this point in the history
  • Loading branch information
not-an-aardvark committed Apr 4, 2017
1 parent bd2e81f commit 154a63b
Show file tree
Hide file tree
Showing 14 changed files with 92 additions and 130 deletions.
6 changes: 0 additions & 6 deletions lib/reporter.js

This file was deleted.

39 changes: 13 additions & 26 deletions lib/worker-helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ exports.refreshModulesPath = refreshModulesPath;
exports.getESLintInstance = getESLintInstance;
exports.getConfigPath = getConfigPath;
exports.getRelativePath = getRelativePath;
exports.getArgv = getArgv;
exports.getCLIEngineOptions = getCLIEngineOptions;

var _path = require('path');

Expand Down Expand Up @@ -103,13 +103,13 @@ function getESLintFromDirectory(modulesDir, config, projectPath) {

try {
// eslint-disable-next-line import/no-dynamic-require
return require(_path2.default.join(ESLintDirectory, 'lib', 'cli.js'));
return require(ESLintDirectory);
} catch (e) {
if (config.useGlobalEslint && e.code === 'MODULE_NOT_FOUND') {
throw new Error('ESLint not found, Please install or make sure Atom is getting $PATH correctly');
}
// eslint-disable-next-line import/no-dynamic-require
return require(_path2.default.join(Cache.ESLINT_LOCAL_PATH, 'lib', 'cli.js'));
return require(Cache.ESLINT_LOCAL_PATH);
}
}

Expand Down Expand Up @@ -158,22 +158,21 @@ function getRelativePath(fileDir, filePath, config) {
return _path2.default.basename(filePath);
}

function getArgv(type, config, rules, filePath, fileDir, givenConfigPath) {
function getCLIEngineOptions(type, config, rules, filePath, fileDir, givenConfigPath) {
let configPath;
if (givenConfigPath === null) {
configPath = config.eslintrcPath || null;
} else configPath = givenConfigPath;

const argv = [process.execPath, 'a-b-c' // dummy value for eslint executable
];
if (type === 'lint') {
argv.push('--stdin');
}
argv.push('--format', _path2.default.join(__dirname, 'reporter.js'));
const cliEngineConfig = {
rules,
ignore: !config.disableEslintIgnore,
fix: type === 'fix'
};

const ignoreFile = config.disableEslintIgnore ? null : (0, _atomLinter.findCached)(fileDir, '.eslintignore');
if (ignoreFile) {
argv.push('--ignore-path', ignoreFile);
cliEngineConfig.ignorePath = ignoreFile;
}

if (config.eslintRulesDir) {
Expand All @@ -182,24 +181,12 @@ function getArgv(type, config, rules, filePath, fileDir, givenConfigPath) {
rulesDir = (0, _atomLinter.findCached)(fileDir, rulesDir);
}
if (rulesDir) {
argv.push('--rulesdir', rulesDir);
cliEngineConfig.rulePaths = [rulesDir];
}
}
if (configPath) {
argv.push('--config', (0, _resolveEnv2.default)(configPath));
}
if (rules && Object.keys(rules).length > 0) {
argv.push('--rule', JSON.stringify(rules));
}
if (config.disableEslintIgnore) {
argv.push('--no-ignore');
}
if (type === 'lint') {
argv.push('--stdin-filename', filePath);
} else if (type === 'fix') {
argv.push(filePath);
argv.push('--fix');
cliEngineConfig.configFile = (0, _resolveEnv2.default)(configPath);
}

return argv;
return cliEngineConfig;
}
72 changes: 36 additions & 36 deletions lib/worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,42 +23,40 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de

process.title = 'linter-eslint helper';

const ignoredMessages = [
// V1
'File ignored because of your .eslintignore file. Use --no-ignore to override.',
// V2
'File ignored because of a matching ignore pattern. Use --no-ignore to override.',
// V2.11.1
'File ignored because of a matching ignore pattern. Use "--no-ignore" to override.',
// supress warning that the current file is ignored by eslint by default
'File ignored by default. Use a negated ignore pattern (like "--ignore-pattern \'!<relative' + '/path/to/filename>\'") to override.', 'File ignored by default. Use "--ignore-pattern \'!node_modules/*\'" to override.', 'File ignored by default. Use "--ignore-pattern \'!bower_components/*\'" to override.'];

function lintJob(argv, contents, eslint, configPath, config) {
const noProjectConfig = configPath === null || (0, _isConfigAtHomeRoot.isConfigAtHomeRoot)(configPath);
if (noProjectConfig && config.disableWhenNoEslintConfig) {
return [];
}
eslint.execute(argv, contents);
return global.__LINTER_ESLINT_RESPONSE.filter(e => !ignoredMessages.includes(e.message));
function lintJob(_ref) {
let cliEngineOptions = _ref.cliEngineOptions,
contents = _ref.contents,
eslint = _ref.eslint,
filePath = _ref.filePath;

const cliEngine = new eslint.CLIEngine(cliEngineOptions);

return typeof contents === 'string' ? cliEngine.executeOnText(contents, filePath) : cliEngine.executeOnFiles([filePath]);
}

function fixJob(argv, eslint) {
const exit = eslint.execute(argv);
if (exit === 0) {
function fixJob(_ref2) {
let cliEngineOptions = _ref2.cliEngineOptions,
contents = _ref2.contents,
eslint = _ref2.eslint,
filePath = _ref2.filePath;

const report = lintJob({ cliEngineOptions, contents, eslint, filePath });

eslint.CLIEngine.outputFixes(report);

if (!report.results.length || !report.results[0].messages.length) {
return 'Linter-ESLint: Fix complete.';
}
return 'Linter-ESLint: Fix attempt complete, but linting errors remain.';
}

(0, _processCommunication.create)().onRequest('job', (_ref, job) => {
let contents = _ref.contents,
type = _ref.type,
config = _ref.config,
filePath = _ref.filePath,
projectPath = _ref.projectPath,
rules = _ref.rules;

global.__LINTER_ESLINT_RESPONSE = [];
(0, _processCommunication.create)().onRequest('job', (_ref3, job) => {
let contents = _ref3.contents,
type = _ref3.type,
config = _ref3.config,
filePath = _ref3.filePath,
projectPath = _ref3.projectPath,
rules = _ref3.rules;

if (config.disableFSCache) {
_atomLinter.FindCache.clear();
Expand All @@ -69,16 +67,18 @@ function fixJob(argv, eslint) {
const configPath = Helpers.getConfigPath(fileDir);
const relativeFilePath = Helpers.getRelativePath(fileDir, filePath, config);

const argv = Helpers.getArgv(type, config, rules, relativeFilePath, fileDir, configPath);
const cliEngineOptions = Helpers.getCLIEngineOptions(type, config, rules, relativeFilePath, fileDir, configPath);

if (type === 'lint') {
job.response = lintJob(argv, contents, eslint, configPath, config);
const noProjectConfig = configPath === null || (0, _isConfigAtHomeRoot.isConfigAtHomeRoot)(configPath);
if (noProjectConfig && config.disableWhenNoEslintConfig) {
job.response = [];
} else if (type === 'lint') {
const report = lintJob({ cliEngineOptions, contents, eslint, filePath });
job.response = report.results.length ? report.results[0].messages : [];
} else if (type === 'fix') {
job.response = fixJob(argv, eslint);
job.response = fixJob({ cliEngineOptions, contents, eslint, filePath });
} else if (type === 'debug') {
const modulesDir = _path2.default.dirname((0, _atomLinter.findCached)(fileDir, 'node_modules/eslint') || '');
job.response = Helpers.findESLintDirectory(modulesDir, config);
}
});

process.exit = function () {/* Stop eslint from closing the daemon */};
});

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions spec/fixtures/global-eslint/node_modules/eslint/package.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions spec/fixtures/local-eslint/node_modules/eslint/package.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 0 additions & 4 deletions src/reporter.js

This file was deleted.

37 changes: 11 additions & 26 deletions src/worker-helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,15 +75,15 @@ export function getESLintFromDirectory(modulesDir, config, projectPath) {
const { path: ESLintDirectory } = findESLintDirectory(modulesDir, config, projectPath)
try {
// eslint-disable-next-line import/no-dynamic-require
return require(Path.join(ESLintDirectory, 'lib', 'cli.js'))
return require(ESLintDirectory)
} catch (e) {
if (config.useGlobalEslint && e.code === 'MODULE_NOT_FOUND') {
throw new Error(
'ESLint not found, Please install or make sure Atom is getting $PATH correctly'
)
}
// eslint-disable-next-line import/no-dynamic-require
return require(Path.join(Cache.ESLINT_LOCAL_PATH, 'lib', 'cli.js'))
return require(Cache.ESLINT_LOCAL_PATH)
}
}

Expand Down Expand Up @@ -135,24 +135,21 @@ export function getRelativePath(fileDir, filePath, config) {
return Path.basename(filePath)
}

export function getArgv(type, config, rules, filePath, fileDir, givenConfigPath) {
export function getCLIEngineOptions(type, config, rules, filePath, fileDir, givenConfigPath) {
let configPath
if (givenConfigPath === null) {
configPath = config.eslintrcPath || null
} else configPath = givenConfigPath

const argv = [
process.execPath,
'a-b-c' // dummy value for eslint executable
]
if (type === 'lint') {
argv.push('--stdin')
const cliEngineConfig = {
rules,
ignore: !config.disableEslintIgnore,
fix: type === 'fix'
}
argv.push('--format', Path.join(__dirname, 'reporter.js'))

const ignoreFile = config.disableEslintIgnore ? null : findCached(fileDir, '.eslintignore')
if (ignoreFile) {
argv.push('--ignore-path', ignoreFile)
cliEngineConfig.ignorePath = ignoreFile
}

if (config.eslintRulesDir) {
Expand All @@ -161,24 +158,12 @@ export function getArgv(type, config, rules, filePath, fileDir, givenConfigPath)
rulesDir = findCached(fileDir, rulesDir)
}
if (rulesDir) {
argv.push('--rulesdir', rulesDir)
cliEngineConfig.rulePaths = [rulesDir]
}
}
if (configPath) {
argv.push('--config', resolveEnv(configPath))
}
if (rules && Object.keys(rules).length > 0) {
argv.push('--rule', JSON.stringify(rules))
}
if (config.disableEslintIgnore) {
argv.push('--no-ignore')
}
if (type === 'lint') {
argv.push('--stdin-filename', filePath)
} else if (type === 'fix') {
argv.push(filePath)
argv.push('--fix')
cliEngineConfig.configFile = resolveEnv(configPath)
}

return argv
return cliEngineConfig
}
52 changes: 20 additions & 32 deletions src/worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,41 +10,26 @@ import { isConfigAtHomeRoot } from './is-config-at-home-root'

process.title = 'linter-eslint helper'

const ignoredMessages = [
// V1
'File ignored because of your .eslintignore file. Use --no-ignore to override.',
// V2
'File ignored because of a matching ignore pattern. Use --no-ignore to override.',
// V2.11.1
'File ignored because of a matching ignore pattern. Use "--no-ignore" to override.',
// supress warning that the current file is ignored by eslint by default
'File ignored by default. Use a negated ignore pattern (like "--ignore-pattern \'!<relative'
+ '/path/to/filename>\'") to override.',
'File ignored by default. Use "--ignore-pattern \'!node_modules/*\'" to override.',
'File ignored by default. Use "--ignore-pattern \'!bower_components/*\'" to override.',
]
function lintJob({ cliEngineOptions, contents, eslint, filePath }) {
const cliEngine = new eslint.CLIEngine(cliEngineOptions)

function lintJob(argv, contents, eslint, configPath, config) {
const noProjectConfig = (configPath === null || isConfigAtHomeRoot(configPath))
if (noProjectConfig && config.disableWhenNoEslintConfig) {
return []
}
eslint.execute(argv, contents)
return global.__LINTER_ESLINT_RESPONSE
.filter(e => !ignoredMessages.includes(e.message))
return typeof contents === 'string'
? cliEngine.executeOnText(contents, filePath)
: cliEngine.executeOnFiles([filePath])
}

function fixJob(argv, eslint) {
const exit = eslint.execute(argv)
if (exit === 0) {
function fixJob({ cliEngineOptions, contents, eslint, filePath }) {
const report = lintJob({ cliEngineOptions, contents, eslint, filePath })

eslint.CLIEngine.outputFixes(report)

if (!report.results.length || !report.results[0].messages.length) {
return 'Linter-ESLint: Fix complete.'
}
return 'Linter-ESLint: Fix attempt complete, but linting errors remain.'
}

create().onRequest('job', ({ contents, type, config, filePath, projectPath, rules }, job) => {
global.__LINTER_ESLINT_RESPONSE = []

if (config.disableFSCache) {
FindCache.clear()
}
Expand All @@ -54,16 +39,19 @@ create().onRequest('job', ({ contents, type, config, filePath, projectPath, rule
const configPath = Helpers.getConfigPath(fileDir)
const relativeFilePath = Helpers.getRelativePath(fileDir, filePath, config)

const argv = Helpers.getArgv(type, config, rules, relativeFilePath, fileDir, configPath)
const cliEngineOptions =
Helpers.getCLIEngineOptions(type, config, rules, relativeFilePath, fileDir, configPath)

if (type === 'lint') {
job.response = lintJob(argv, contents, eslint, configPath, config)
const noProjectConfig = (configPath === null || isConfigAtHomeRoot(configPath))
if (noProjectConfig && config.disableWhenNoEslintConfig) {
job.response = []
} else if (type === 'lint') {
const report = lintJob({ cliEngineOptions, contents, eslint, filePath })
job.response = report.results.length ? report.results[0].messages : []
} else if (type === 'fix') {
job.response = fixJob(argv, eslint)
job.response = fixJob({ cliEngineOptions, contents, eslint, filePath })
} else if (type === 'debug') {
const modulesDir = Path.dirname(findCached(fileDir, 'node_modules/eslint') || '')
job.response = Helpers.findESLintDirectory(modulesDir, config)
}
})

process.exit = function () { /* Stop eslint from closing the daemon */ }

0 comments on commit 154a63b

Please sign in to comment.