Skip to content

Commit c49adbf

Browse files
committedJul 25, 2017
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 50f45ff commit c49adbf

File tree

124 files changed

+8670
-1841
lines changed

Some content is hidden

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

124 files changed

+8670
-1841
lines changed
 

‎tools/eslint/bin/eslint.js

+3-4
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,10 @@ 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+
console.error(err.stack);
5251
}
5352

5453
process.exitCode = 1;

‎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)
Please sign in to comment.