Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

eslint 6 support #311

Merged
merged 2 commits into from
Aug 9, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 12 additions & 5 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,36 @@ language: node_js
notifications:
email: false
node_js:
- '12'
- '10'
- '8'
- '6'
- '4'
before_install:
- nvm install-latest-npm
before_script:
- 'if [ -n "${ESLINT-}" ]; then npm install --no-save "eslint@${ESLINT}"; fi'
- 'if [ -n "${AJV-}" ]; then npm install --no-save "ajv@${AJV}"; fi'
- npm ls > /dev/null
- npm prune > /dev/null && npm ls > /dev/null
script:
- 'if [ -n "${LINTONLY-}" ]; then npm run lint; else npm run cover && npm run check-coverage; fi'
after_success:
- npm run travis-after-all
env:
matrix:
- ESLINT=6
- ESLINT=5 AJV=6
- ESLINT=4 AJV=5
- ESLINT=3
matrix:
include:
- node_js: "node"
env: LINTONLY=true
exclude:
- node_js: "6"
env: ESLINT=5 AJV=5
- node_js: "6"
env: ESLINT=4 AJV=5
- node_js: "6"
env: ESLINT=3
- node_js: "4"
env: ESLINT=5 AJV=6
env: ESLINT=4 AJV=5
- node_js: "4"
env: ESLINT=3
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"description": "Find built-in ESLint rules you don't have in your custom config.",
"main": "dist/lib/rule-finder.js",
"scripts": {
"cover": "nyc --reporter=lcov --reporter=text npm test",
"cover": "nyc --reporter=lcov --reporter=text --reporter=html npm test",
"lint": "eslint --ext .js,.json .",
"test": "mocha --recursive",
"update-contributors": "all-contributors generate",
Expand Down Expand Up @@ -32,6 +32,7 @@
"dependencies": {
"cliui": "^3.2.0",
"eslint-rule-documentation": "^1.0.0",
"glob": "^7.1.4",
"path-is-absolute": "^1.0.1",
"which": "^1.2.8",
"window-size": "0.3.0",
Expand All @@ -46,7 +47,7 @@
"codecov": "^2.2.0",
"commitizen": "^2.9.6",
"cz-conventional-changelog": "^2.0.0",
"eslint": "^3.12.0 || ^4 || ^5",
"eslint": "^3.12.0 || ^4 || ^5 || ^6",
"eslint-plugin-json": "^1.4.0",
"ghooks": "^2.0.0",
"mocha": "^3.0.1",
Expand All @@ -60,7 +61,7 @@
"validate-commit-msg": "^2.12.2"
},
"peerDependencies": {
"eslint": "^3.12.0 || ^4 || ^5"
"eslint": "^3.12.0 || ^4 || ^5 || ^6"
},
"nyc": {
"exclude": [
Expand Down
17 changes: 14 additions & 3 deletions src/lib/rule-finder.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const path = require('path');

const eslint = require('eslint');
const glob = require('glob');
const isAbsolute = require('path-is-absolute');
const difference = require('./array-diff');
const getSortedRules = require('./sort-rules');
Expand All @@ -16,14 +17,22 @@ function _getConfigFile(specifiedFile) {
return require(path.join(process.cwd(), 'package.json')).main; // eslint-disable-line import/no-dynamic-require
}

function _getConfig(configFile) {
function _getConfigs(configFile, files) {
const cliEngine = new eslint.CLIEngine({
// Ignore any config applicable depending on the location on the filesystem
useEslintrc: false,
// Point to the particular config
configFile
});
return cliEngine.getConfigForFile();
return new Set(files
.map(filePath => cliEngine.isPathIgnored(filePath) ? false : cliEngine.getConfigForFile(filePath))
.filter(Boolean));
}

function _getConfig(configFile, files) {
return Array.from(_getConfigs(configFile, files)).reduce((prev, item) => {
return Object.assign(prev, item, {rules: Object.assign({}, prev.rules, item.rules)});
}, {});
}

function _getCurrentNamesRules(config) {
Expand Down Expand Up @@ -69,6 +78,7 @@ function _notDeprecated(rule) {
function _getPluginRules(config) {
const pluginRules = new Map();
const plugins = config.plugins;
/* istanbul ignore else */
if (plugins) {
plugins.forEach(plugin => {
const normalized = _normalizePluginName(plugin);
Expand Down Expand Up @@ -98,7 +108,8 @@ function _isNotCore(rule) {
function RuleFinder(specifiedFile, options) {
const {omitCore, includeDeprecated} = options;
const configFile = _getConfigFile(specifiedFile);
const config = _getConfig(configFile);
const files = glob.sync('**/*.js', {dot: true, matchBase: true});
const config = _getConfig(configFile, files);
let currentRuleNames = _getCurrentNamesRules(config);
if (omitCore) {
currentRuleNames = currentRuleNames.filter(_isNotCore);
Expand Down
51 changes: 51 additions & 0 deletions test/lib/rule-finder.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,21 @@ const path = require('path');
const assert = require('assert');
const proxyquire = require('proxyquire');

let ModuleResolver;
try {
// eslint 6 and over: load the actual module
// eslint-disable-next-line import/no-unresolved
ModuleResolver = require('eslint/lib/shared/relative-module-resolver');
} catch (err) {
if (err.code !== 'MODULE_NOT_FOUND') {
throw err;
}
// eslint < 6: ModuleResolver is `undefined`, which is okay. The proxyquire
// override for ../shared/relative-module-resolver won't be used because
// eslint < 6 does not have that module and so does not try to load it.
ModuleResolver = undefined;
}

const processCwd = process.cwd;

const eslintVersion = process.env.ESLINT === '3' || process.env.ESLINT === '4' ? '<v5' : 'v5+';
Expand All @@ -19,6 +34,31 @@ const getRuleFinder = proxyquire('../../src/lib/rule-finder', {
}
}
},
//
// This following module override is needed for eslint v6 and over. The module
// path that we pass here is literally the one used in eslint (specifially in
// eslint/lib/cli-engine/config-array-factory.js)
//
// The stock `resolve` method attempts to resolve to a file path the module
// name passed in `name` relative to the path in `relative`. We have to
// override that function, otherwise eslint fails to "load" our plugins.
//
'../shared/relative-module-resolver': {
resolve(name, relative) {
// The strategy is simple: if called with one of our plugins, just return
// the module name, as-is. This is a lie because what we return is not a
// path, but it is simple, and works. Otherwise, we just call the original
// `resolve` from the stock module.
return ['eslint-plugin-plugin',
'eslint-plugin-no-rules',
'@scope/eslint-plugin-scoped-plugin',
'@scope/eslint-plugin'].includes(name) ?
name :
ModuleResolver.resolve(name, relative);
},
'@global': true,
'@noCallThru': true
},
'eslint-plugin-plugin': {
rules: {
'foo-rule': {},
Expand Down Expand Up @@ -83,6 +123,17 @@ const getRuleFinderForDedupeTests = proxyquire('../../src/lib/rule-finder', {
}
}
},
// See the long comment in `getRuleFinder` above to learn what the point of
// this override is.
'../shared/relative-module-resolver': {
resolve(name, relative) {
return name === 'eslint-plugin-plugin' ?
name :
ModuleResolver.resolve(name, relative);
},
'@global': true,
'@noCallThru': true
},
'eslint-plugin-plugin': {
rules: {
'duplicate-foo-rule': {},
Expand Down