Skip to content

Commit 31f572c

Browse files
TrottMylesBorins
authored andcommitted
tools: update to ESLint 4.3.0
PR-URL: #14417 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Teddy Katz <[email protected]> Reviewed-By: Roman Reiss <[email protected]> Reviewed-By: Refael Ackermann <[email protected]>
1 parent 438a642 commit 31f572c

File tree

304 files changed

+28501
-15865
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

304 files changed

+28501
-15865
lines changed

tools/eslint/bin/eslint.js

+5-4
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,12 @@ process.once("uncaughtException", err => {
4444
if (typeof err.messageTemplate === "string" && err.messageTemplate.length > 0) {
4545
const template = lodash.template(fs.readFileSync(path.resolve(__dirname, `../messages/${err.messageTemplate}.txt`), "utf-8"));
4646

47-
console.log("\nOops! Something went wrong! :(");
48-
console.log(`\n${template(err.messageData || {})}`);
47+
console.error("\nOops! Something went wrong! :(");
48+
console.error(`\n${template(err.messageData || {})}`);
4949
} else {
50-
console.log(err.message);
51-
console.log(err.stack);
50+
51+
console.error(err.message);
52+
console.error(err.stack);
5253
}
5354

5455
process.exitCode = 1;

tools/eslint/conf/category-list.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@
1010
],
1111
"deprecated": {
1212
"name": "Deprecated",
13-
"description": "These rules have been deprecated and replaced by newer rules:",
13+
"description": "These rules have been deprecated in accordance with the [deprecation policy](/docs/user-guide/rule-deprecation), and replaced by newer rules:",
1414
"rules": []
1515
},
1616
"removed": {
1717
"name": "Removed",
18-
"description": "These rules from older versions of ESLint have been replaced by newer rules:",
18+
"description": "These rules from older versions of ESLint (before the [deprecation policy](/docs/user-guide/rule-deprecation) existed) have been replaced by newer rules:",
1919
"rules": [
2020
{ "removed": "generator-star", "replacedBy": ["generator-star-spacing"] },
2121
{ "removed": "global-strict", "replacedBy": ["strict"] },

tools/eslint/conf/config-schema.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ const baseConfigProperties = {
1212
parserOptions: { type: "object" },
1313
plugins: { type: "array" },
1414
rules: { type: "object" },
15-
settings: { type: "object" }
15+
settings: { type: "object" },
16+
17+
ecmaFeatures: { type: "object" } // deprecated; logs a warning when used
1618
};
1719

1820
const overrideProperties = Object.assign(

tools/eslint/conf/eslint-recommended.js

+11-14
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,10 @@
66

77
"use strict";
88

9-
/* eslint sort-keys: ["error", "asc"], quote-props: ["error", "consistent"] */
10-
/* eslint-disable sort-keys */
9+
/* eslint sort-keys: ["error", "asc"] */
1110

1211
module.exports = {
1312
rules: {
14-
15-
/* eslint-enable sort-keys */
1613
"accessor-pairs": "off",
1714
"array-bracket-newline": "off",
1815
"array-bracket-spacing": "off",
@@ -25,23 +22,23 @@ module.exports = {
2522
"block-spacing": "off",
2623
"brace-style": "off",
2724
"callback-return": "off",
28-
"camelcase": "off",
25+
camelcase: "off",
2926
"capitalized-comments": "off",
3027
"class-methods-use-this": "off",
3128
"comma-dangle": "off",
3229
"comma-spacing": "off",
3330
"comma-style": "off",
34-
"complexity": "off",
31+
complexity: "off",
3532
"computed-property-spacing": "off",
3633
"consistent-return": "off",
3734
"consistent-this": "off",
3835
"constructor-super": "error",
39-
"curly": "off",
36+
curly: "off",
4037
"default-case": "off",
4138
"dot-location": "off",
4239
"dot-notation": "off",
4340
"eol-last": "off",
44-
"eqeqeq": "off",
41+
eqeqeq: "off",
4542
"for-direction": "off",
4643
"func-call-spacing": "off",
4744
"func-name-matching": "off",
@@ -55,7 +52,7 @@ module.exports = {
5552
"id-blacklist": "off",
5653
"id-length": "off",
5754
"id-match": "off",
58-
"indent": "off",
55+
indent: "off",
5956
"indent-legacy": "off",
6057
"init-declarations": "off",
6158
"jsx-quotes": "off",
@@ -234,13 +231,13 @@ module.exports = {
234231
"prefer-spread": "off",
235232
"prefer-template": "off",
236233
"quote-props": "off",
237-
"quotes": "off",
238-
"radix": "off",
234+
quotes: "off",
235+
radix: "off",
239236
"require-await": "off",
240237
"require-jsdoc": "off",
241238
"require-yield": "error",
242239
"rest-spread-spacing": "off",
243-
"semi": "off",
240+
semi: "off",
244241
"semi-spacing": "off",
245242
"semi-style": "off",
246243
"sort-imports": "off",
@@ -252,7 +249,7 @@ module.exports = {
252249
"space-infix-ops": "off",
253250
"space-unary-ops": "off",
254251
"spaced-comment": "off",
255-
"strict": "off",
252+
strict: "off",
256253
"switch-colon-spacing": "off",
257254
"symbol-description": "off",
258255
"template-curly-spacing": "off",
@@ -265,6 +262,6 @@ module.exports = {
265262
"wrap-iife": "off",
266263
"wrap-regex": "off",
267264
"yield-star-spacing": "off",
268-
"yoda": "off"
265+
yoda: "off"
269266
}
270267
};

tools/eslint/lib/config/config-file.js

+5-5
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
* @author Nicholas C. Zakas
44
*/
55

6-
/* eslint no-use-before-define: 0 */
7-
86
"use strict";
97

108
//------------------------------------------------------------------------------
@@ -418,6 +416,8 @@ function applyExtends(config, configContext, filePath, relativeTo) {
418416
);
419417
}
420418
debug(`Loading ${parentPath}`);
419+
420+
// eslint-disable-next-line no-use-before-define
421421
return ConfigOps.merge(load(parentPath, configContext, relativeTo), previousValue);
422422
} catch (e) {
423423

@@ -502,8 +502,8 @@ function resolve(filePath, relativeTo) {
502502

503503
if (filePath.startsWith("plugin:")) {
504504
const configFullName = filePath;
505-
const pluginName = filePath.substr(7, filePath.lastIndexOf("/") - 7);
506-
const configName = filePath.substr(filePath.lastIndexOf("/") + 1, filePath.length - filePath.lastIndexOf("/") - 1);
505+
const pluginName = filePath.slice(7, filePath.lastIndexOf("/"));
506+
const configName = filePath.slice(filePath.lastIndexOf("/") + 1);
507507

508508
normalizedPackageName = normalizePackageName(pluginName, "eslint-plugin");
509509
debug(`Attempting to resolve ${normalizedPackageName}`);
@@ -546,7 +546,7 @@ function loadFromDisk(resolvedPath, configContext) {
546546
}
547547

548548
// validate the configuration before continuing
549-
validator.validate(config, resolvedPath, configContext.linterContext.rules, configContext.linterContext.environments);
549+
validator.validate(config, resolvedPath.configFullName, configContext.linterContext.rules, configContext.linterContext.environments);
550550

551551
/*
552552
* If an `extends` property is defined, it represents a configuration file to use as

tools/eslint/lib/config/config-initializer.js

+123-14
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@
1212
const util = require("util"),
1313
inquirer = require("inquirer"),
1414
ProgressBar = require("progress"),
15+
semver = require("semver"),
1516
autoconfig = require("./autoconfig.js"),
1617
ConfigFile = require("./config-file"),
1718
ConfigOps = require("./config-ops"),
1819
getSourceCodeOfFiles = require("../util/source-code-util").getSourceCodeOfFiles,
20+
ModuleResolver = require("../util/module-resolver"),
1921
npmUtil = require("../util/npm-util"),
2022
recConfig = require("../../conf/eslint-recommended"),
2123
log = require("../logging");
@@ -56,12 +58,35 @@ function writeFile(config, format) {
5658
}
5759
}
5860

61+
/**
62+
* Get the peer dependencies of the given module.
63+
* This adds the gotten value to cache at the first time, then reuses it.
64+
* In a process, this function is called twice, but `npmUtil.fetchPeerDependencies` needs to access network which is relatively slow.
65+
* @param {string} moduleName The module name to get.
66+
* @returns {Object} The peer dependencies of the given module.
67+
* This object is the object of `peerDependencies` field of `package.json`.
68+
*/
69+
function getPeerDependencies(moduleName) {
70+
let result = getPeerDependencies.cache.get(moduleName);
71+
72+
if (!result) {
73+
log.info(`Checking peerDependencies of ${moduleName}`);
74+
75+
result = npmUtil.fetchPeerDependencies(moduleName);
76+
getPeerDependencies.cache.set(moduleName, result);
77+
}
78+
79+
return result;
80+
}
81+
getPeerDependencies.cache = new Map();
82+
5983
/**
6084
* Synchronously install necessary plugins, configs, parsers, etc. based on the config
6185
* @param {Object} config config object
86+
* @param {boolean} [installESLint=true] If `false` is given, it does not install eslint.
6287
* @returns {void}
6388
*/
64-
function installModules(config) {
89+
function installModules(config, installESLint) {
6590
const modules = {};
6691

6792
// Create a list of modules which should be installed based on config
@@ -73,11 +98,10 @@ function installModules(config) {
7398
if (config.extends && config.extends.indexOf("eslint:") === -1) {
7499
const moduleName = `eslint-config-${config.extends}`;
75100

76-
log.info(`Checking peerDependencies of ${moduleName}`);
77101
modules[moduleName] = "latest";
78102
Object.assign(
79103
modules,
80-
npmUtil.fetchPeerDependencies(`${moduleName}@latest`)
104+
getPeerDependencies(`${moduleName}@latest`)
81105
);
82106
}
83107

@@ -86,15 +110,17 @@ function installModules(config) {
86110
return;
87111
}
88112

89-
// Add eslint to list in case user does not have it installed locally
90-
modules.eslint = modules.eslint || "latest";
91-
92-
// Mark to show messages if it's new installation of eslint.
93-
const installStatus = npmUtil.checkDevDeps(["eslint"]);
113+
if (installESLint === false) {
114+
delete modules.eslint;
115+
} else {
116+
const installStatus = npmUtil.checkDevDeps(["eslint"]);
94117

95-
if (installStatus.eslint === false) {
96-
log.info("Local ESLint installation not found.");
97-
config.installedESLint = true;
118+
// Mark to show messages if it's new installation of eslint.
119+
if (installStatus.eslint === false) {
120+
log.info("Local ESLint installation not found.");
121+
modules.eslint = modules.eslint || "latest";
122+
config.installedESLint = true;
123+
}
98124
}
99125

100126
// Install packages
@@ -265,9 +291,10 @@ function processAnswers(answers) {
265291
/**
266292
* process user's style guide of choice and return an appropriate config object.
267293
* @param {string} guide name of the chosen style guide
294+
* @param {boolean} [installESLint=true] If `false` is given, it does not install eslint.
268295
* @returns {Object} config object
269296
*/
270-
function getConfigForStyleGuide(guide) {
297+
function getConfigForStyleGuide(guide, installESLint) {
271298
const guides = {
272299
google: { extends: "google" },
273300
airbnb: { extends: "airbnb" },
@@ -279,11 +306,74 @@ function getConfigForStyleGuide(guide) {
279306
throw new Error("You referenced an unsupported guide.");
280307
}
281308

282-
installModules(guides[guide]);
309+
installModules(guides[guide], installESLint);
283310

284311
return guides[guide];
285312
}
286313

314+
/**
315+
* Get the version of the local ESLint.
316+
* @returns {string|null} The version. If the local ESLint was not found, returns null.
317+
*/
318+
function getLocalESLintVersion() {
319+
try {
320+
const resolver = new ModuleResolver();
321+
const eslintPath = resolver.resolve("eslint", process.cwd());
322+
const eslint = require(eslintPath);
323+
324+
return eslint.linter.version || null;
325+
} catch (_err) {
326+
return null;
327+
}
328+
}
329+
330+
/**
331+
* Get the shareable config name of the chosen style guide.
332+
* @param {Object} answers The answers object.
333+
* @returns {string} The shareable config name.
334+
*/
335+
function getStyleGuideName(answers) {
336+
if (answers.styleguide === "airbnb" && !answers.airbnbReact) {
337+
return "airbnb-base";
338+
}
339+
return answers.styleguide;
340+
}
341+
342+
/**
343+
* Check whether the local ESLint version conflicts with the required version of the chosen shareable config.
344+
* @param {Object} answers The answers object.
345+
* @returns {boolean} `true` if the local ESLint is found then it conflicts with the required version of the chosen shareable config.
346+
*/
347+
function hasESLintVersionConflict(answers) {
348+
349+
// Get the local ESLint version.
350+
const localESLintVersion = getLocalESLintVersion();
351+
352+
if (!localESLintVersion) {
353+
return false;
354+
}
355+
356+
// Get the required range of ESLint version.
357+
const configName = getStyleGuideName(answers);
358+
const moduleName = `eslint-config-${configName}@latest`;
359+
const requiredESLintVersionRange = getPeerDependencies(moduleName).eslint;
360+
361+
if (!requiredESLintVersionRange) {
362+
return false;
363+
}
364+
365+
answers.localESLintVersion = localESLintVersion;
366+
answers.requiredESLintVersionRange = requiredESLintVersionRange;
367+
368+
// Check the version.
369+
if (semver.satisfies(localESLintVersion, requiredESLintVersionRange)) {
370+
answers.installESLint = false;
371+
return false;
372+
}
373+
374+
return true;
375+
}
376+
287377
/* istanbul ignore next: no need to test inquirer*/
288378
/**
289379
* Ask use a few questions on command prompt
@@ -346,6 +436,21 @@ function promptUser() {
346436
when(answers) {
347437
return ((answers.source === "guide" && answers.packageJsonExists) || answers.source === "auto");
348438
}
439+
},
440+
{
441+
type: "confirm",
442+
name: "installESLint",
443+
message(answers) {
444+
const verb = semver.ltr(answers.localESLintVersion, answers.requiredESLintVersionRange)
445+
? "upgrade"
446+
: "downgrade";
447+
448+
return `The style guide "${answers.styleguide}" requires eslint@${answers.requiredESLintVersionRange}. You are currently using eslint@${answers.localESLintVersion}.\n Do you want to ${verb}?`;
449+
},
450+
default: true,
451+
when(answers) {
452+
return answers.source === "guide" && answers.packageJsonExists && hasESLintVersionConflict(answers);
453+
}
349454
}
350455
]).then(earlyAnswers => {
351456

@@ -355,11 +460,14 @@ function promptUser() {
355460
log.info("A package.json is necessary to install plugins such as style guides. Run `npm init` to create a package.json file and try again.");
356461
return void 0;
357462
}
463+
if (earlyAnswers.installESLint === false && !semver.satisfies(earlyAnswers.localESLintVersion, earlyAnswers.requiredESLintVersionRange)) {
464+
log.info(`Note: it might not work since ESLint's version is mismatched with the ${earlyAnswers.styleguide} config.`);
465+
}
358466
if (earlyAnswers.styleguide === "airbnb" && !earlyAnswers.airbnbReact) {
359467
earlyAnswers.styleguide = "airbnb-base";
360468
}
361469

362-
config = getConfigForStyleGuide(earlyAnswers.styleguide);
470+
config = getConfigForStyleGuide(earlyAnswers.styleguide, earlyAnswers.installESLint);
363471
writeFile(config, earlyAnswers.format);
364472

365473
return void 0;
@@ -479,6 +587,7 @@ function promptUser() {
479587

480588
const init = {
481589
getConfigForStyleGuide,
590+
hasESLintVersionConflict,
482591
processAnswers,
483592
/* istanbul ignore next */initializeConfig() {
484593
return promptUser();

0 commit comments

Comments
 (0)