aboutsummaryrefslogtreecommitdiff
path: root/tools/node_modules/eslint/lib
diff options
context:
space:
mode:
authorRich Trott <rtrott@gmail.com>2018-03-21 22:44:47 -0700
committerRich Trott <rtrott@gmail.com>2018-03-24 04:11:48 -0700
commit0863a0e528ba9ee01f960dce7ffebe8fff3a774c (patch)
tree37990f3af668c242ec1c4a9e24afd31b720ad96d /tools/node_modules/eslint/lib
parent5e00a013eb219716d952cb8eb29a134c00f5db54 (diff)
downloadandroid-node-v8-0863a0e528ba9ee01f960dce7ffebe8fff3a774c.tar.gz
android-node-v8-0863a0e528ba9ee01f960dce7ffebe8fff3a774c.tar.bz2
android-node-v8-0863a0e528ba9ee01f960dce7ffebe8fff3a774c.zip
tools: update ESLint to 4.19.1
A few bug fixes result in more stringent linting rules. PR-URL: https://github.com/nodejs/node/pull/19528 Reviewed-By: Michaƫl Zasso <targos@protonmail.com> Reviewed-By: Daniel Bevenius <daniel.bevenius@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
Diffstat (limited to 'tools/node_modules/eslint/lib')
-rw-r--r--tools/node_modules/eslint/lib/ast-utils.js54
-rw-r--r--tools/node_modules/eslint/lib/cli-engine.js57
-rw-r--r--tools/node_modules/eslint/lib/code-path-analysis/code-path-state.js10
-rw-r--r--tools/node_modules/eslint/lib/code-path-analysis/code-path.js17
-rw-r--r--tools/node_modules/eslint/lib/code-path-analysis/fork-context.js22
-rw-r--r--tools/node_modules/eslint/lib/config.js15
-rw-r--r--tools/node_modules/eslint/lib/config/config-file.js31
-rw-r--r--tools/node_modules/eslint/lib/config/config-ops.js18
-rw-r--r--tools/node_modules/eslint/lib/config/config-rule.js5
-rw-r--r--tools/node_modules/eslint/lib/config/config-validator.js11
-rw-r--r--tools/node_modules/eslint/lib/config/plugins.js20
-rw-r--r--tools/node_modules/eslint/lib/file-finder.js19
-rw-r--r--tools/node_modules/eslint/lib/ignored-paths.js8
-rw-r--r--[-rwxr-xr-x]tools/node_modules/eslint/lib/linter.js802
-rw-r--r--tools/node_modules/eslint/lib/load-rules.js13
-rw-r--r--tools/node_modules/eslint/lib/options.js14
-rw-r--r--tools/node_modules/eslint/lib/report-translator.js65
-rw-r--r--tools/node_modules/eslint/lib/rules/accessor-pairs.js18
-rw-r--r--tools/node_modules/eslint/lib/rules/array-bracket-newline.js16
-rw-r--r--tools/node_modules/eslint/lib/rules/array-bracket-spacing.js16
-rw-r--r--tools/node_modules/eslint/lib/rules/array-callback-return.js30
-rw-r--r--tools/node_modules/eslint/lib/rules/array-element-newline.js19
-rw-r--r--tools/node_modules/eslint/lib/rules/arrow-body-style.js24
-rw-r--r--tools/node_modules/eslint/lib/rules/arrow-parens.js22
-rw-r--r--tools/node_modules/eslint/lib/rules/arrow-spacing.js18
-rw-r--r--tools/node_modules/eslint/lib/rules/block-scoped-var.js8
-rw-r--r--tools/node_modules/eslint/lib/rules/block-spacing.js19
-rw-r--r--tools/node_modules/eslint/lib/rules/brace-style.js30
-rw-r--r--tools/node_modules/eslint/lib/rules/callback-return.js8
-rw-r--r--tools/node_modules/eslint/lib/rules/camelcase.js8
-rw-r--r--tools/node_modules/eslint/lib/rules/capitalized-comments.js19
-rw-r--r--tools/node_modules/eslint/lib/rules/class-methods-use-this.js10
-rw-r--r--tools/node_modules/eslint/lib/rules/comma-dangle.js11
-rw-r--r--tools/node_modules/eslint/lib/rules/comma-spacing.js23
-rw-r--r--tools/node_modules/eslint/lib/rules/comma-style.js21
-rw-r--r--tools/node_modules/eslint/lib/rules/complexity.js8
-rw-r--r--tools/node_modules/eslint/lib/rules/computed-property-spacing.js18
-rw-r--r--tools/node_modules/eslint/lib/rules/consistent-return.js19
-rw-r--r--tools/node_modules/eslint/lib/rules/consistent-this.js13
-rw-r--r--tools/node_modules/eslint/lib/rules/constructor-super.js25
-rw-r--r--tools/node_modules/eslint/lib/rules/curly.js158
-rw-r--r--tools/node_modules/eslint/lib/rules/default-case.js8
-rw-r--r--tools/node_modules/eslint/lib/rules/dot-location.js11
-rw-r--r--tools/node_modules/eslint/lib/rules/dot-notation.js15
-rw-r--r--tools/node_modules/eslint/lib/rules/eol-last.js10
-rw-r--r--tools/node_modules/eslint/lib/rules/eqeqeq.js8
-rw-r--r--tools/node_modules/eslint/lib/rules/generator-star-spacing.js3
-rw-r--r--tools/node_modules/eslint/lib/rules/guard-for-in.js42
-rw-r--r--tools/node_modules/eslint/lib/rules/indent-legacy.js17
-rw-r--r--tools/node_modules/eslint/lib/rules/indent.js86
-rw-r--r--tools/node_modules/eslint/lib/rules/key-spacing.js5
-rw-r--r--tools/node_modules/eslint/lib/rules/keyword-spacing.js31
-rw-r--r--tools/node_modules/eslint/lib/rules/max-len.js17
-rw-r--r--tools/node_modules/eslint/lib/rules/no-alert.js37
-rw-r--r--tools/node_modules/eslint/lib/rules/no-array-constructor.js8
-rw-r--r--tools/node_modules/eslint/lib/rules/no-await-in-loop.js132
-rw-r--r--tools/node_modules/eslint/lib/rules/no-bitwise.js8
-rw-r--r--tools/node_modules/eslint/lib/rules/no-buffer-constructor.js11
-rw-r--r--tools/node_modules/eslint/lib/rules/no-caller.js8
-rw-r--r--tools/node_modules/eslint/lib/rules/no-case-declarations.js8
-rw-r--r--tools/node_modules/eslint/lib/rules/no-catch-shadow.js8
-rw-r--r--tools/node_modules/eslint/lib/rules/no-class-assign.js8
-rw-r--r--tools/node_modules/eslint/lib/rules/no-compare-neg-zero.js7
-rw-r--r--tools/node_modules/eslint/lib/rules/no-cond-assign.js14
-rw-r--r--tools/node_modules/eslint/lib/rules/no-confusing-arrow.js8
-rw-r--r--tools/node_modules/eslint/lib/rules/no-console.js8
-rw-r--r--tools/node_modules/eslint/lib/rules/no-const-assign.js8
-rw-r--r--tools/node_modules/eslint/lib/rules/no-constant-condition.js9
-rw-r--r--tools/node_modules/eslint/lib/rules/no-continue.js8
-rw-r--r--tools/node_modules/eslint/lib/rules/no-control-regex.js133
-rw-r--r--tools/node_modules/eslint/lib/rules/no-debugger.js7
-rw-r--r--tools/node_modules/eslint/lib/rules/no-delete-var.js8
-rw-r--r--tools/node_modules/eslint/lib/rules/no-div-regex.js8
-rw-r--r--tools/node_modules/eslint/lib/rules/no-dupe-args.js8
-rw-r--r--tools/node_modules/eslint/lib/rules/no-dupe-class-members.js8
-rw-r--r--tools/node_modules/eslint/lib/rules/no-dupe-keys.js8
-rw-r--r--tools/node_modules/eslint/lib/rules/no-duplicate-case.js8
-rw-r--r--tools/node_modules/eslint/lib/rules/no-else-return.js22
-rw-r--r--tools/node_modules/eslint/lib/rules/no-empty-character-class.js10
-rw-r--r--tools/node_modules/eslint/lib/rules/no-empty-function.js8
-rw-r--r--tools/node_modules/eslint/lib/rules/no-empty-pattern.js10
-rw-r--r--tools/node_modules/eslint/lib/rules/no-empty.js10
-rw-r--r--tools/node_modules/eslint/lib/rules/no-eq-null.js8
-rw-r--r--tools/node_modules/eslint/lib/rules/no-eval.js23
-rw-r--r--tools/node_modules/eslint/lib/rules/no-ex-assign.js8
-rw-r--r--tools/node_modules/eslint/lib/rules/no-extend-native.js8
-rw-r--r--tools/node_modules/eslint/lib/rules/no-extra-bind.js8
-rw-r--r--tools/node_modules/eslint/lib/rules/no-extra-boolean-cast.js11
-rw-r--r--tools/node_modules/eslint/lib/rules/no-extra-label.js8
-rw-r--r--tools/node_modules/eslint/lib/rules/no-extra-parens.js15
-rw-r--r--tools/node_modules/eslint/lib/rules/no-extra-semi.js8
-rw-r--r--tools/node_modules/eslint/lib/rules/no-implicit-coercion.js15
-rw-r--r--tools/node_modules/eslint/lib/rules/no-invalid-regexp.js89
-rw-r--r--tools/node_modules/eslint/lib/rules/no-irregular-whitespace.js2
-rw-r--r--tools/node_modules/eslint/lib/rules/no-loop-func.js20
-rw-r--r--tools/node_modules/eslint/lib/rules/no-magic-numbers.js27
-rw-r--r--tools/node_modules/eslint/lib/rules/no-return-assign.js7
-rw-r--r--tools/node_modules/eslint/lib/rules/no-self-assign.js4
-rw-r--r--tools/node_modules/eslint/lib/rules/no-unexpected-multiline.js2
-rw-r--r--tools/node_modules/eslint/lib/rules/no-unsafe-finally.js11
-rw-r--r--tools/node_modules/eslint/lib/rules/no-unused-vars.js2
-rw-r--r--tools/node_modules/eslint/lib/rules/no-useless-escape.js4
-rw-r--r--tools/node_modules/eslint/lib/rules/no-useless-return.js19
-rw-r--r--tools/node_modules/eslint/lib/rules/no-var.js16
-rw-r--r--tools/node_modules/eslint/lib/rules/object-curly-newline.js87
-rw-r--r--tools/node_modules/eslint/lib/rules/object-property-newline.js10
-rw-r--r--tools/node_modules/eslint/lib/rules/object-shorthand.js16
-rw-r--r--tools/node_modules/eslint/lib/rules/one-var.js237
-rw-r--r--tools/node_modules/eslint/lib/rules/padding-line-between-statements.js16
-rw-r--r--tools/node_modules/eslint/lib/rules/prefer-arrow-callback.js9
-rw-r--r--tools/node_modules/eslint/lib/rules/prefer-destructuring.js6
-rw-r--r--tools/node_modules/eslint/lib/rules/prefer-template.js8
-rw-r--r--tools/node_modules/eslint/lib/rules/require-await.js5
-rw-r--r--tools/node_modules/eslint/lib/rules/rest-spread-spacing.js6
-rw-r--r--tools/node_modules/eslint/lib/rules/space-unary-ops.js15
-rw-r--r--tools/node_modules/eslint/lib/rules/spaced-comment.js10
-rw-r--r--[-rwxr-xr-x]tools/node_modules/eslint/lib/rules/template-tag-spacing.js0
-rw-r--r--tools/node_modules/eslint/lib/rules/valid-jsdoc.js129
-rw-r--r--tools/node_modules/eslint/lib/rules/vars-on-top.js24
-rw-r--r--tools/node_modules/eslint/lib/timing.js8
-rw-r--r--tools/node_modules/eslint/lib/util/glob-util.js43
-rw-r--r--tools/node_modules/eslint/lib/util/interpolate.js6
-rw-r--r--tools/node_modules/eslint/lib/util/naming.js21
-rw-r--r--tools/node_modules/eslint/lib/util/npm-util.js10
-rw-r--r--tools/node_modules/eslint/lib/util/path-util.js14
-rw-r--r--tools/node_modules/eslint/lib/util/source-code-util.js49
-rw-r--r--tools/node_modules/eslint/lib/util/source-code.js7
127 files changed, 2064 insertions, 1520 deletions
diff --git a/tools/node_modules/eslint/lib/ast-utils.js b/tools/node_modules/eslint/lib/ast-utils.js
index a186bdee54..a188c7fa1c 100644
--- a/tools/node_modules/eslint/lib/ast-utils.js
+++ b/tools/node_modules/eslint/lib/ast-utils.js
@@ -84,11 +84,10 @@ function isES5Constructor(node) {
* @returns {Node|null} A found function node.
*/
function getUpperFunction(node) {
- while (node) {
- if (anyFunctionPattern.test(node.type)) {
- return node;
+ for (let currentNode = node; currentNode; currentNode = currentNode.parent) {
+ if (anyFunctionPattern.test(currentNode.type)) {
+ return currentNode;
}
- node = node.parent;
}
return null;
}
@@ -132,12 +131,10 @@ function isLoop(node) {
* @returns {boolean} `true` if the node is in a loop.
*/
function isInLoop(node) {
- while (node && !isFunction(node)) {
- if (isLoop(node)) {
+ for (let currentNode = node; currentNode && !isFunction(currentNode); currentNode = currentNode.parent) {
+ if (isLoop(currentNode)) {
return true;
}
-
- node = node.parent;
}
return false;
@@ -204,16 +201,14 @@ function isArrayFromMethod(node) {
* @returns {boolean} Whether or not the node is a method which has `thisArg`.
*/
function isMethodWhichHasThisArg(node) {
- while (node) {
- if (node.type === "Identifier") {
- return arrayMethodPattern.test(node.name);
- }
- if (node.type === "MemberExpression" && !node.computed) {
- node = node.property;
- continue;
+ for (
+ let currentNode = node;
+ currentNode.type === "MemberExpression" && !currentNode.computed;
+ currentNode = currentNode.property
+ ) {
+ if (currentNode.property.type === "Identifier") {
+ return arrayMethodPattern.test(currentNode.property.name);
}
-
- break;
}
return false;
@@ -631,9 +626,10 @@ module.exports = {
return false;
}
const isAnonymous = node.id === null;
+ let currentNode = node;
- while (node) {
- const parent = node.parent;
+ while (currentNode) {
+ const parent = currentNode.parent;
switch (parent.type) {
@@ -643,7 +639,7 @@ module.exports = {
*/
case "LogicalExpression":
case "ConditionalExpression":
- node = parent;
+ currentNode = parent;
break;
/*
@@ -663,14 +659,14 @@ module.exports = {
if (func === null || !isCallee(func)) {
return true;
}
- node = func.parent;
+ currentNode = func.parent;
break;
}
case "ArrowFunctionExpression":
- if (node !== parent.body || !isCallee(parent)) {
+ if (currentNode !== parent.body || !isCallee(parent)) {
return true;
}
- node = parent.parent;
+ currentNode = parent.parent;
break;
/*
@@ -685,7 +681,7 @@ module.exports = {
*/
case "Property":
case "MethodDefinition":
- return parent.value !== node;
+ return parent.value !== currentNode;
/*
* e.g.
@@ -715,7 +711,7 @@ module.exports = {
case "VariableDeclarator":
return !(
isAnonymous &&
- parent.init === node &&
+ parent.init === currentNode &&
parent.id.type === "Identifier" &&
startsWithUpperCase(parent.id.name)
);
@@ -728,7 +724,7 @@ module.exports = {
*/
case "MemberExpression":
return (
- parent.object !== node ||
+ parent.object !== currentNode ||
parent.property.type !== "Identifier" ||
!bindOrCallOrApplyPattern.test(parent.property.name) ||
!isCallee(parent) ||
@@ -746,21 +742,21 @@ module.exports = {
if (isReflectApply(parent.callee)) {
return (
parent.arguments.length !== 3 ||
- parent.arguments[0] !== node ||
+ parent.arguments[0] !== currentNode ||
isNullOrUndefined(parent.arguments[1])
);
}
if (isArrayFromMethod(parent.callee)) {
return (
parent.arguments.length !== 3 ||
- parent.arguments[1] !== node ||
+ parent.arguments[1] !== currentNode ||
isNullOrUndefined(parent.arguments[2])
);
}
if (isMethodWhichHasThisArg(parent.callee)) {
return (
parent.arguments.length !== 2 ||
- parent.arguments[0] !== node ||
+ parent.arguments[0] !== currentNode ||
isNullOrUndefined(parent.arguments[1])
);
}
diff --git a/tools/node_modules/eslint/lib/cli-engine.js b/tools/node_modules/eslint/lib/cli-engine.js
index 0c1afcbceb..8531d1c1d4 100644
--- a/tools/node_modules/eslint/lib/cli-engine.js
+++ b/tools/node_modules/eslint/lib/cli-engine.js
@@ -157,8 +157,9 @@ function processText(text, configHelper, filename, fix, allowInlineConfig, repor
fileExtension = path.extname(filename);
}
- filename = filename || "<text>";
- debug(`Linting ${filename}`);
+ const effectiveFilename = filename || "<text>";
+
+ debug(`Linting ${effectiveFilename}`);
const config = configHelper.getConfig(filePath);
if (config.plugins) {
@@ -177,18 +178,18 @@ function processText(text, configHelper, filename, fix, allowInlineConfig, repor
const autofixingEnabled = typeof fix !== "undefined" && (!processor || processor.supportsAutofix);
const fixedResult = linter.verifyAndFix(text, config, {
- filename,
+ filename: effectiveFilename,
allowInlineConfig,
reportUnusedDisableDirectives,
fix: !!autofixingEnabled && fix,
- preprocess: processor && (rawText => processor.preprocess(rawText, filename)),
- postprocess: processor && (problemLists => processor.postprocess(problemLists, filename))
+ preprocess: processor && (rawText => processor.preprocess(rawText, effectiveFilename)),
+ postprocess: processor && (problemLists => processor.postprocess(problemLists, effectiveFilename))
});
const stats = calculateStatsPerFile(fixedResult.messages);
const result = {
- filePath: filename,
+ filePath: effectiveFilename,
messages: fixedResult.messages,
errorCount: stats.errorCount,
warningCount: stats.warningCount,
@@ -302,10 +303,10 @@ function getCacheFile(cacheFile, cwd) {
* make sure the path separators are normalized for the environment/os
* keeping the trailing path separator if present
*/
- cacheFile = path.normalize(cacheFile);
+ const normalizedCacheFile = path.normalize(cacheFile);
- const resolvedCacheFile = path.resolve(cwd, cacheFile);
- const looksLikeADirectory = cacheFile[cacheFile.length - 1] === path.sep;
+ const resolvedCacheFile = path.resolve(cwd, normalizedCacheFile);
+ const looksLikeADirectory = normalizedCacheFile.slice(-1) === path.sep;
/**
* return the name for the cache file in case the provided parameter is a directory
@@ -368,16 +369,16 @@ class CLIEngine {
/**
* Creates a new instance of the core CLI engine.
- * @param {CLIEngineOptions} options The options for this instance.
+ * @param {CLIEngineOptions} providedOptions The options for this instance.
* @constructor
*/
- constructor(options) {
+ constructor(providedOptions) {
- options = Object.assign(
+ const options = Object.assign(
Object.create(null),
defaultOptions,
{ cwd: process.cwd() },
- options
+ providedOptions
);
/**
@@ -605,20 +606,21 @@ class CLIEngine {
ignoredPaths = new IgnoredPaths(options);
// resolve filename based on options.cwd (for reporting, ignoredPaths also resolves)
- if (filename && !path.isAbsolute(filename)) {
- filename = path.resolve(options.cwd, filename);
- }
- if (filename && ignoredPaths.contains(filename)) {
+ const resolvedFilename = filename && !path.isAbsolute(filename)
+ ? path.resolve(options.cwd, filename)
+ : filename;
+
+ if (resolvedFilename && ignoredPaths.contains(resolvedFilename)) {
if (warnIgnored) {
- results.push(createIgnoreResult(filename, options.cwd));
+ results.push(createIgnoreResult(resolvedFilename, options.cwd));
}
} else {
results.push(
processText(
text,
configHelper,
- filename,
+ resolvedFilename,
options.fix,
options.allowInlineConfig,
options.reportUnusedDisableDirectives,
@@ -672,31 +674,30 @@ class CLIEngine {
*/
getFormatter(format) {
-
// default is stylish
- format = format || "stylish";
+ const resolvedFormatName = format || "stylish";
// only strings are valid formatters
- if (typeof format === "string") {
+ if (typeof resolvedFormatName === "string") {
// replace \ with / for Windows compatibility
- format = format.replace(/\\/g, "/");
+ const normalizedFormatName = resolvedFormatName.replace(/\\/g, "/");
const cwd = this.options ? this.options.cwd : process.cwd();
- const namespace = naming.getNamespaceFromTerm(format);
+ const namespace = naming.getNamespaceFromTerm(normalizedFormatName);
let formatterPath;
// if there's a slash, then it's a file
- if (!namespace && format.indexOf("/") > -1) {
- formatterPath = path.resolve(cwd, format);
+ if (!namespace && normalizedFormatName.indexOf("/") > -1) {
+ formatterPath = path.resolve(cwd, normalizedFormatName);
} else {
try {
- const npmFormat = naming.normalizePackageName(format, "eslint-formatter");
+ const npmFormat = naming.normalizePackageName(normalizedFormatName, "eslint-formatter");
formatterPath = resolver.resolve(npmFormat, `${cwd}/node_modules`);
} catch (e) {
- formatterPath = `./formatters/${format}`;
+ formatterPath = `./formatters/${normalizedFormatName}`;
}
}
diff --git a/tools/node_modules/eslint/lib/code-path-analysis/code-path-state.js b/tools/node_modules/eslint/lib/code-path-analysis/code-path-state.js
index 0c31e2072b..57da10fa91 100644
--- a/tools/node_modules/eslint/lib/code-path-analysis/code-path-state.js
+++ b/tools/node_modules/eslint/lib/code-path-analysis/code-path-state.js
@@ -164,13 +164,13 @@ function removeConnection(prevSegments, nextSegments) {
* Creates looping path.
*
* @param {CodePathState} state - The instance.
- * @param {CodePathSegment[]} fromSegments - Segments which are source.
- * @param {CodePathSegment[]} toSegments - Segments which are destination.
+ * @param {CodePathSegment[]} unflattenedFromSegments - Segments which are source.
+ * @param {CodePathSegment[]} unflattenedToSegments - Segments which are destination.
* @returns {void}
*/
-function makeLooped(state, fromSegments, toSegments) {
- fromSegments = CodePathSegment.flattenUnusedSegments(fromSegments);
- toSegments = CodePathSegment.flattenUnusedSegments(toSegments);
+function makeLooped(state, unflattenedFromSegments, unflattenedToSegments) {
+ const fromSegments = CodePathSegment.flattenUnusedSegments(unflattenedFromSegments);
+ const toSegments = CodePathSegment.flattenUnusedSegments(unflattenedToSegments);
const end = Math.min(fromSegments.length, toSegments.length);
diff --git a/tools/node_modules/eslint/lib/code-path-analysis/code-path.js b/tools/node_modules/eslint/lib/code-path-analysis/code-path.js
index 709a111189..cb26ea18a3 100644
--- a/tools/node_modules/eslint/lib/code-path-analysis/code-path.js
+++ b/tools/node_modules/eslint/lib/code-path-analysis/code-path.js
@@ -134,14 +134,19 @@ class CodePath {
* @returns {void}
*/
traverseSegments(options, callback) {
+ let resolvedOptions;
+ let resolvedCallback;
+
if (typeof options === "function") {
- callback = options;
- options = null;
+ resolvedCallback = options;
+ resolvedOptions = {};
+ } else {
+ resolvedOptions = options || {};
+ resolvedCallback = callback;
}
- options = options || {};
- const startSegment = options.first || this.internal.initialSegment;
- const lastSegment = options.last;
+ const startSegment = resolvedOptions.first || this.internal.initialSegment;
+ const lastSegment = resolvedOptions.last;
let item = null;
let index = 0;
@@ -206,7 +211,7 @@ class CodePath {
// Call the callback when the first time.
if (!skippedSegment) {
- callback.call(this, segment, controller);
+ resolvedCallback.call(this, segment, controller);
if (segment === lastSegment) {
controller.skip();
}
diff --git a/tools/node_modules/eslint/lib/code-path-analysis/fork-context.js b/tools/node_modules/eslint/lib/code-path-analysis/fork-context.js
index 4fae6bbb1e..939ed2d0d9 100644
--- a/tools/node_modules/eslint/lib/code-path-analysis/fork-context.js
+++ b/tools/node_modules/eslint/lib/code-path-analysis/fork-context.js
@@ -46,19 +46,15 @@ function isReachable(segment) {
function makeSegments(context, begin, end, create) {
const list = context.segmentsList;
- if (begin < 0) {
- begin = list.length + begin;
- }
- if (end < 0) {
- end = list.length + end;
- }
+ const normalizedBegin = begin >= 0 ? begin : list.length + begin;
+ const normalizedEnd = end >= 0 ? end : list.length + end;
const segments = [];
for (let i = 0; i < context.count; ++i) {
const allPrevSegments = [];
- for (let j = begin; j <= end; ++j) {
+ for (let j = normalizedBegin; j <= normalizedEnd; ++j) {
allPrevSegments.push(list[j][i]);
}
@@ -79,18 +75,20 @@ function makeSegments(context, begin, end, create) {
* @returns {CodePathSegment[]} The merged segments.
*/
function mergeExtraSegments(context, segments) {
- while (segments.length > context.count) {
+ let currentSegments = segments;
+
+ while (currentSegments.length > context.count) {
const merged = [];
- for (let i = 0, length = segments.length / 2 | 0; i < length; ++i) {
+ for (let i = 0, length = currentSegments.length / 2 | 0; i < length; ++i) {
merged.push(CodePathSegment.newNext(
context.idGenerator.next(),
- [segments[i], segments[i + length]]
+ [currentSegments[i], currentSegments[i + length]]
));
}
- segments = merged;
+ currentSegments = merged;
}
- return segments;
+ return currentSegments;
}
//------------------------------------------------------------------------------
diff --git a/tools/node_modules/eslint/lib/config.js b/tools/node_modules/eslint/lib/config.js
index b66b9f41e0..7ba5cd6e2d 100644
--- a/tools/node_modules/eslint/lib/config.js
+++ b/tools/node_modules/eslint/lib/config.js
@@ -51,11 +51,11 @@ function hasRules(options) {
class Config {
/**
- * @param {Object} options Options to be passed in
+ * @param {Object} providedOptions Options to be passed in
* @param {Linter} linterContext Linter instance object
*/
- constructor(options, linterContext) {
- options = options || {};
+ constructor(providedOptions, linterContext) {
+ const options = providedOptions || {};
this.linterContext = linterContext;
this.plugins = new Plugins(linterContext.environments, linterContext.rules);
@@ -132,11 +132,10 @@ class Config {
isResolvable(`eslint-config-${config}`) ||
config.charAt(0) === "@";
- if (!isNamedConfig) {
- config = path.resolve(this.options.cwd, config);
- }
-
- this.specificConfig = ConfigFile.load(config, this);
+ this.specificConfig = ConfigFile.load(
+ isNamedConfig ? config : path.resolve(this.options.cwd, config),
+ this
+ );
}
}
diff --git a/tools/node_modules/eslint/lib/config/config-file.js b/tools/node_modules/eslint/lib/config/config-file.js
index c5ff073cfc..37ac84831a 100644
--- a/tools/node_modules/eslint/lib/config/config-file.js
+++ b/tools/node_modules/eslint/lib/config/config-file.js
@@ -400,25 +400,29 @@ function applyExtends(config, configContext, filePath, relativeTo) {
}
// Make the last element in an array take the highest precedence
- config = configExtends.reduceRight((previousValue, parentPath) => {
+ return configExtends.reduceRight((previousValue, parentPath) => {
try {
+ let extensionPath;
+
if (parentPath.startsWith("eslint:")) {
- parentPath = getEslintCoreConfigPath(parentPath);
+ extensionPath = getEslintCoreConfigPath(parentPath);
} else if (isFilePath(parentPath)) {
/*
* If the `extends` path is relative, use the directory of the current configuration
* file as the reference point. Otherwise, use as-is.
*/
- parentPath = (path.isAbsolute(parentPath)
+ extensionPath = (path.isAbsolute(parentPath)
? parentPath
: path.join(relativeTo || path.dirname(filePath), parentPath)
);
+ } else {
+ extensionPath = parentPath;
}
- debug(`Loading ${parentPath}`);
+ debug(`Loading ${extensionPath}`);
// eslint-disable-next-line no-use-before-define
- return ConfigOps.merge(load(parentPath, configContext, relativeTo), previousValue);
+ return ConfigOps.merge(load(extensionPath, configContext, relativeTo), previousValue);
} catch (e) {
/*
@@ -432,8 +436,6 @@ function applyExtends(config, configContext, filePath, relativeTo) {
}
}, config);
-
- return config;
}
/**
@@ -463,13 +465,20 @@ function resolve(filePath, relativeTo) {
normalizedPackageName = naming.normalizePackageName(pluginName, "eslint-plugin");
debug(`Attempting to resolve ${normalizedPackageName}`);
- filePath = resolver.resolve(normalizedPackageName, getLookupPath(relativeTo));
- return { filePath, configName, configFullName };
+
+ return {
+ filePath: resolver.resolve(normalizedPackageName, getLookupPath(relativeTo)),
+ configName,
+ configFullName
+ };
}
normalizedPackageName = naming.normalizePackageName(filePath, "eslint-config");
debug(`Attempting to resolve ${normalizedPackageName}`);
- filePath = resolver.resolve(normalizedPackageName, getLookupPath(relativeTo));
- return { filePath, configFullName: filePath };
+
+ return {
+ filePath: resolver.resolve(normalizedPackageName, getLookupPath(relativeTo)),
+ configFullName: filePath
+ };
}
diff --git a/tools/node_modules/eslint/lib/config/config-ops.js b/tools/node_modules/eslint/lib/config/config-ops.js
index 2ce500a4f4..67c23a8a61 100644
--- a/tools/node_modules/eslint/lib/config/config-ops.js
+++ b/tools/node_modules/eslint/lib/config/config-ops.js
@@ -136,29 +136,27 @@ module.exports = {
const array = Array.isArray(src) || Array.isArray(target);
let dst = array && [] || {};
- combine = !!combine;
- isRule = !!isRule;
if (array) {
- target = target || [];
+ const resolvedTarget = target || [];
// src could be a string, so check for array
if (isRule && Array.isArray(src) && src.length > 1) {
dst = dst.concat(src);
} else {
- dst = dst.concat(target);
+ dst = dst.concat(resolvedTarget);
}
- if (typeof src !== "object" && !Array.isArray(src)) {
- src = [src];
- }
- Object.keys(src).forEach((e, i) => {
- e = src[i];
+ const resolvedSrc = typeof src === "object" ? src : [src];
+
+ Object.keys(resolvedSrc).forEach((_, i) => {
+ const e = resolvedSrc[i];
+
if (typeof dst[i] === "undefined") {
dst[i] = e;
} else if (typeof e === "object") {
if (isRule) {
dst[i] = e;
} else {
- dst[i] = deepmerge(target[i], e, combine, isRule);
+ dst[i] = deepmerge(resolvedTarget[i], e, combine, isRule);
}
} else {
if (!combine) {
diff --git a/tools/node_modules/eslint/lib/config/config-rule.js b/tools/node_modules/eslint/lib/config/config-rule.js
index 5fc38ac5d1..27d29446db 100644
--- a/tools/node_modules/eslint/lib/config/config-rule.js
+++ b/tools/node_modules/eslint/lib/config/config-rule.js
@@ -197,11 +197,10 @@ class RuleConfigSet {
* Add a severity level to the front of all configs in the instance.
* This should only be called after all configs have been added to the instance.
*
- * @param {number} [severity=2] The level of severity for the rule (0, 1, 2)
* @returns {void}
*/
- addErrorSeverity(severity) {
- severity = severity || 2;
+ addErrorSeverity() {
+ const severity = 2;
this.ruleConfigs = this.ruleConfigs.map(config => {
config.unshift(severity);
diff --git a/tools/node_modules/eslint/lib/config/config-validator.js b/tools/node_modules/eslint/lib/config/config-validator.js
index 3d98b51045..1a5b3ef13e 100644
--- a/tools/node_modules/eslint/lib/config/config-validator.js
+++ b/tools/node_modules/eslint/lib/config/config-validator.js
@@ -98,7 +98,8 @@ function validateRuleSchema(rule, localOptions) {
* @param {{create: Function}|null} rule The rule that the config is being validated for
* @param {string} ruleId The rule's unique name.
* @param {array|number} options The given options for the rule.
- * @param {string} source The name of the configuration source to report in any errors.
+ * @param {string|null} source The name of the configuration source to report in any errors. If null or undefined,
+ * no source is prepended to the message.
* @returns {void}
*/
function validateRuleOptions(rule, ruleId, options, source) {
@@ -112,7 +113,13 @@ function validateRuleOptions(rule, ruleId, options, source) {
validateRuleSchema(rule, Array.isArray(options) ? options.slice(1) : []);
}
} catch (err) {
- throw new Error(`${source}:\n\tConfiguration for rule "${ruleId}" is invalid:\n${err.message}`);
+ const enhancedMessage = `Configuration for rule "${ruleId}" is invalid:\n${err.message}`;
+
+ if (typeof source === "string") {
+ throw new Error(`${source}:\n\t${enhancedMessage}`);
+ } else {
+ throw new Error(enhancedMessage);
+ }
}
}
diff --git a/tools/node_modules/eslint/lib/config/plugins.js b/tools/node_modules/eslint/lib/config/plugins.js
index c509c48fe2..756f9ff21b 100644
--- a/tools/node_modules/eslint/lib/config/plugins.js
+++ b/tools/node_modules/eslint/lib/config/plugins.js
@@ -120,6 +120,26 @@ class Plugins {
throw pluginLoadErr;
}
+ // This step is costly, so skip if debug is disabled
+ if (debug.enabled) {
+ const resolvedPath = require.resolve(longName);
+
+ let version = null;
+
+ try {
+ version = require(`${longName}/package.json`).version;
+ } catch (e) {
+
+ // Do nothing
+ }
+
+ const loadedPluginAndVersion = version
+ ? `${longName}@${version}`
+ : `${longName}, version unknown`;
+
+ debug(`Loaded plugin ${pluginName} (${loadedPluginAndVersion}) (from ${resolvedPath})`);
+ }
+
this.define(pluginName, plugin);
}
}
diff --git a/tools/node_modules/eslint/lib/file-finder.js b/tools/node_modules/eslint/lib/file-finder.js
index 3458bbf52a..11091a99d5 100644
--- a/tools/node_modules/eslint/lib/file-finder.js
+++ b/tools/node_modules/eslint/lib/file-finder.js
@@ -79,26 +79,25 @@ class FileFinder {
* Does not check if a matching directory entry is a file.
* Searches for all the file names in this.fileNames.
* Is currently used by lib/config.js to find .eslintrc and package.json files.
- * @param {string} directory The directory to start the search from.
+ * @param {string} relativeDirectory The directory to start the search from.
* @returns {GeneratorFunction} to iterate the file paths found
*/
- *findAllInDirectoryAndParents(directory) {
+ *findAllInDirectoryAndParents(relativeDirectory) {
const cache = this.cache;
- if (directory) {
- directory = path.resolve(this.cwd, directory);
- } else {
- directory = this.cwd;
- }
+ const initialDirectory = relativeDirectory
+ ? path.resolve(this.cwd, relativeDirectory)
+ : this.cwd;
- if (cache.hasOwnProperty(directory)) {
- yield* cache[directory];
+ if (cache.hasOwnProperty(initialDirectory)) {
+ yield* cache[initialDirectory];
return; // to avoid doing the normal loop afterwards
}
const dirs = [];
const fileNames = this.fileNames;
let searched = 0;
+ let directory = initialDirectory;
do {
dirs[searched++] = directory;
@@ -135,7 +134,7 @@ class FileFinder {
// Add what has been cached previously to the cache of each directory searched.
for (let i = 0; i < searched; i++) {
- dirs.push.apply(cache[dirs[i]], cache[directory]);
+ [].push.apply(cache[dirs[i]], cache[directory]);
}
yield* cache[dirs[0]];
diff --git a/tools/node_modules/eslint/lib/ignored-paths.js b/tools/node_modules/eslint/lib/ignored-paths.js
index c02e83bc2a..8fff260d02 100644
--- a/tools/node_modules/eslint/lib/ignored-paths.js
+++ b/tools/node_modules/eslint/lib/ignored-paths.js
@@ -76,7 +76,6 @@ function findPackageJSONFile(cwd) {
* @returns {Object} Merged options
*/
function mergeDefaultOptions(options) {
- options = (options || {});
return Object.assign({}, DEFAULT_OPTIONS, options);
}
@@ -90,10 +89,11 @@ function mergeDefaultOptions(options) {
class IgnoredPaths {
/**
- * @param {Object} options object containing 'ignore', 'ignorePath' and 'patterns' properties
+ * @param {Object} providedOptions object containing 'ignore', 'ignorePath' and 'patterns' properties
*/
- constructor(options) {
- options = mergeDefaultOptions(options);
+ constructor(providedOptions) {
+ const options = mergeDefaultOptions(providedOptions);
+
this.cache = {};
/**
diff --git a/tools/node_modules/eslint/lib/linter.js b/tools/node_modules/eslint/lib/linter.js
index 2238c5be0e..8c631522f9 100755..100644
--- a/tools/node_modules/eslint/lib/linter.js
+++ b/tools/node_modules/eslint/lib/linter.js
@@ -14,7 +14,6 @@ const eslintScope = require("eslint-scope"),
levn = require("levn"),
lodash = require("lodash"),
blankScriptAST = require("../conf/blank-script.json"),
- defaultConfig = require("../conf/default-config-options.js"),
CodePathAnalyzer = require("./code-path-analysis/code-path-analyzer"),
ConfigOps = require("./config/config-ops"),
validator = require("./config/config-validator"),
@@ -33,6 +32,7 @@ const eslintScope = require("eslint-scope"),
const debug = require("debug")("eslint:linter");
const MAX_AUTOFIX_PASSES = 10;
+const DEFAULT_PARSER_NAME = "espree";
//------------------------------------------------------------------------------
// Typedefs
@@ -48,6 +48,14 @@ const MAX_AUTOFIX_PASSES = 10;
* @property {Object|null} visitorKeys The visitor keys to traverse this AST.
*/
+/**
+ * @typedef {Object} DisableDirective
+ * @property {("disable"|"enable"|"disable-line"|"disable-next-line")} type
+ * @property {number} line
+ * @property {number} column
+ * @property {(string|null)} ruleId
+ */
+
//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
@@ -63,25 +71,25 @@ function parseBooleanConfig(string, comment) {
const items = {};
// Collapse whitespace around `:` and `,` to make parsing easier
- string = string.replace(/\s*([:,])\s*/g, "$1");
+ const trimmedString = string.replace(/\s*([:,])\s*/g, "$1");
- string.split(/\s|,+/).forEach(name => {
+ trimmedString.split(/\s|,+/).forEach(name => {
if (!name) {
return;
}
const pos = name.indexOf(":");
- let value;
- if (pos !== -1) {
- value = name.slice(pos + 1);
- name = name.slice(0, pos);
+ if (pos === -1) {
+ items[name] = {
+ value: false,
+ comment
+ };
+ } else {
+ items[name.slice(0, pos)] = {
+ value: name.slice(pos + 1) === "true",
+ comment
+ };
}
-
- items[name] = {
- value: (value === "true"),
- comment
- };
-
});
return items;
}
@@ -119,9 +127,10 @@ function parseJsonConfig(string, location) {
* But we are supporting that. So this is a fallback for that.
*/
items = {};
- string = string.replace(/([a-zA-Z0-9\-/]+):/g, "\"$1\":").replace(/(]|[0-9])\s+(?=")/, "$1,");
+ const normalizedString = string.replace(/([a-zA-Z0-9\-/]+):/g, "\"$1\":").replace(/(]|[0-9])\s+(?=")/, "$1,");
+
try {
- items = JSON.parse(`{${string}}`);
+ items = JSON.parse(`{${normalizedString}}`);
} catch (ex) {
return {
success: false,
@@ -130,7 +139,7 @@ function parseJsonConfig(string, location) {
fatal: true,
severity: 2,
source: null,
- message: `Failed to parse JSON from '${string}': ${ex.message}`,
+ message: `Failed to parse JSON from '${normalizedString}': ${ex.message}`,
line: location.start.line,
column: location.start.column + 1
}
@@ -153,14 +162,12 @@ function parseListConfig(string) {
const items = {};
// Collapse whitespace around ,
- string = string.replace(/\s*,\s*/g, ",");
+ string.replace(/\s*,\s*/g, ",").split(/,+/).forEach(name => {
+ const trimmedName = name.trim();
- string.split(/,+/).forEach(name => {
- name = name.trim();
- if (!name) {
- return;
+ if (trimmedName) {
+ items[trimmedName] = true;
}
- items[name] = true;
});
return items;
}
@@ -170,32 +177,12 @@ function parseListConfig(string) {
* and any globals declared by special block comments, are present in the global
* scope.
* @param {Scope} globalScope The global scope.
- * @param {Object} config The existing configuration data.
- * @param {Environments} envContext Env context
+ * @param {Object} configGlobals The globals declared in configuration
+ * @param {{exportedVariables: Object, enabledGlobals: Object}} commentDirectives Directives from comment configuration
* @returns {void}
*/
-function addDeclaredGlobals(globalScope, config, envContext) {
- const declaredGlobals = {},
- exportedGlobals = {},
- explicitGlobals = {},
- builtin = envContext.get("builtin");
-
- Object.assign(declaredGlobals, builtin);
-
- Object.keys(config.env).filter(name => config.env[name]).forEach(name => {
- const env = envContext.get(name),
- environmentGlobals = env && env.globals;
-
- if (environmentGlobals) {
- Object.assign(declaredGlobals, environmentGlobals);
- }
- });
-
- Object.assign(exportedGlobals, config.exported);
- Object.assign(declaredGlobals, config.globals);
- Object.assign(explicitGlobals, config.astGlobals);
-
- Object.keys(declaredGlobals).forEach(name => {
+function addDeclaredGlobals(globalScope, configGlobals, commentDirectives) {
+ Object.keys(configGlobals).forEach(name => {
let variable = globalScope.set.get(name);
if (!variable) {
@@ -204,24 +191,24 @@ function addDeclaredGlobals(globalScope, config, envContext) {
globalScope.variables.push(variable);
globalScope.set.set(name, variable);
}
- variable.writeable = declaredGlobals[name];
+ variable.writeable = configGlobals[name];
});
- Object.keys(explicitGlobals).forEach(name => {
+ Object.keys(commentDirectives.enabledGlobals).forEach(name => {
let variable = globalScope.set.get(name);
if (!variable) {
variable = new eslintScope.Variable(name, globalScope);
variable.eslintExplicitGlobal = true;
- variable.eslintExplicitGlobalComment = explicitGlobals[name].comment;
+ variable.eslintExplicitGlobalComment = commentDirectives.enabledGlobals[name].comment;
globalScope.variables.push(variable);
globalScope.set.set(name, variable);
}
- variable.writeable = explicitGlobals[name].value;
+ variable.writeable = commentDirectives.enabledGlobals[name].value;
});
// mark all exported variables as such
- Object.keys(exportedGlobals).forEach(name => {
+ Object.keys(commentDirectives.exportedVariables).forEach(name => {
const variable = globalScope.set.get(name);
if (variable) {
@@ -260,12 +247,7 @@ function addDeclaredGlobals(globalScope, config, envContext) {
* @param {{line: number, column: number}} loc The 0-based location of the comment token
* @param {string} value The value after the directive in the comment
* comment specified no specific rules, so it applies to all rules (e.g. `eslint-disable`)
- * @returns {{
- * type: ("disable"|"enable"|"disable-line"|"disable-next-line"),
- * line: number,
- * column: number,
- * ruleId: (string|null)
- * }[]} Directives from the comment
+ * @returns {DisableDirective[]} Directives from the comment
*/
function createDisableDirectives(type, loc, value) {
const ruleIds = Object.keys(parseListConfig(value));
@@ -280,92 +262,90 @@ function createDisableDirectives(type, loc, value) {
* where reporting is disabled or enabled and merges them with reporting config.
* @param {string} filename The file being checked.
* @param {ASTNode} ast The top node of the AST.
- * @param {Object} config The existing configuration data.
* @param {function(string): {create: Function}} ruleMapper A map from rule IDs to defined rules
- * @returns {{
- * config: Object,
- * problems: Problem[],
- * disableDirectives: {
- * type: ("disable"|"enable"|"disable-line"|"disable-next-line"),
- * line: number,
- * column: number,
- * ruleId: (string|null)
- * }[]
- * }} Modified config object, along with any problems encountered
- * while parsing config comments
+ * @returns {{configuredRules: Object, enabledGlobals: Object, exportedVariables: Object, problems: Problem[], disableDirectives: DisableDirective[]}}
+ * A collection of the directive comments that were found, along with any problems that occurred when parsing
*/
-function modifyConfigsFromComments(filename, ast, config, ruleMapper) {
-
- const commentConfig = {
- exported: {},
- astGlobals: {},
- rules: {},
- env: {}
- };
- const commentRules = {};
+function getDirectiveComments(filename, ast, ruleMapper) {
+ const configuredRules = {};
+ const enabledGlobals = {};
+ const exportedVariables = {};
const problems = [];
const disableDirectives = [];
ast.comments.filter(token => token.type !== "Shebang").forEach(comment => {
+ const trimmedCommentText = comment.value.trim();
+ const match = /^(eslint(-\w+){0,3}|exported|globals?)(\s|$)/.exec(trimmedCommentText);
- let value = comment.value.trim();
- const match = /^(eslint(-\w+){0,3}|exported|globals?)(\s|$)/.exec(value);
-
- if (match) {
- value = value.slice(match.index + match[1].length);
-
- if (comment.type === "Block") {
- switch (match[1]) {
- case "exported":
- Object.assign(commentConfig.exported, parseBooleanConfig(value, comment));
- break;
-
- case "globals":
- case "global":
- Object.assign(commentConfig.astGlobals, parseBooleanConfig(value, comment));
- break;
-
- case "eslint-disable":
- [].push.apply(disableDirectives, createDisableDirectives("disable", comment.loc.start, value));
- break;
-
- case "eslint-enable":
- [].push.apply(disableDirectives, createDisableDirectives("enable", comment.loc.start, value));
- break;
-
- case "eslint": {
- const parseResult = parseJsonConfig(value, comment.loc);
-
- if (parseResult.success) {
- Object.keys(parseResult.config).forEach(name => {
- const ruleValue = parseResult.config[name];
-
- validator.validateRuleOptions(ruleMapper(name), name, ruleValue, `${filename} line ${comment.loc.start.line}`);
- commentRules[name] = ruleValue;
- });
- } else {
- problems.push(parseResult.error);
- }
+ if (!match) {
+ return;
+ }
- break;
+ const directiveValue = trimmedCommentText.slice(match.index + match[1].length);
+
+ if (/^eslint-disable-(next-)?line$/.test(match[1]) && comment.loc.start.line === comment.loc.end.line) {
+ const directiveType = match[1].slice("eslint-".length);
+
+ [].push.apply(disableDirectives, createDisableDirectives(directiveType, comment.loc.start, directiveValue));
+ } else if (comment.type === "Block") {
+ switch (match[1]) {
+ case "exported":
+ Object.assign(exportedVariables, parseBooleanConfig(directiveValue, comment));
+ break;
+
+ case "globals":
+ case "global":
+ Object.assign(enabledGlobals, parseBooleanConfig(directiveValue, comment));
+ break;
+
+ case "eslint-disable":
+ [].push.apply(disableDirectives, createDisableDirectives("disable", comment.loc.start, directiveValue));
+ break;
+
+ case "eslint-enable":
+ [].push.apply(disableDirectives, createDisableDirectives("enable", comment.loc.start, directiveValue));
+ break;
+
+ case "eslint": {
+ const parseResult = parseJsonConfig(directiveValue, comment.loc);
+
+ if (parseResult.success) {
+ Object.keys(parseResult.config).forEach(name => {
+ const ruleValue = parseResult.config[name];
+
+ try {
+ validator.validateRuleOptions(ruleMapper(name), name, ruleValue);
+ } catch (err) {
+ problems.push({
+ ruleId: name,
+ severity: 2,
+ source: null,
+ message: err.message,
+ line: comment.loc.start.line,
+ column: comment.loc.start.column + 1,
+ endLine: comment.loc.end.line,
+ endColumn: comment.loc.end.column + 1,
+ nodeType: null
+ });
+ }
+ configuredRules[name] = ruleValue;
+ });
+ } else {
+ problems.push(parseResult.error);
}
- // no default
- }
- } else { // comment.type === "Line"
- if (match[1] === "eslint-disable-line") {
- [].push.apply(disableDirectives, createDisableDirectives("disable-line", comment.loc.start, value));
- } else if (match[1] === "eslint-disable-next-line") {
- [].push.apply(disableDirectives, createDisableDirectives("disable-next-line", comment.loc.start, value));
+ break;
}
+
+ // no default
}
}
});
- Object.assign(commentConfig.rules, commentRules);
-
return {
- config: ConfigOps.merge(config, commentConfig),
+ configuredRules,
+ enabledGlobals,
+ exportedVariables,
problems,
disableDirectives
};
@@ -381,7 +361,7 @@ function normalizeEcmaVersion(ecmaVersion, isModule) {
// Need at least ES6 for modules
if (isModule && (!ecmaVersion || ecmaVersion < 6)) {
- ecmaVersion = 6;
+ return 6;
}
/*
@@ -389,87 +369,87 @@ function normalizeEcmaVersion(ecmaVersion, isModule) {
* ES2015, which corresponds with ES6 (or a difference of 2009).
*/
if (ecmaVersion >= 2015) {
- ecmaVersion -= 2009;
+ return ecmaVersion - 2009;
}
return ecmaVersion;
}
+const eslintEnvPattern = /\/\*\s*eslint-env\s(.+?)\*\//g;
+
/**
- * Process initial config to make it safe to extend by file comment config
- * @param {Object} config Initial config
- * @param {Environments} envContext Env context
- * @returns {Object} Processed config
+ * Checks whether or not there is a comment which has "eslint-env *" in a given text.
+ * @param {string} text - A source code text to check.
+ * @returns {Object|null} A result of parseListConfig() with "eslint-env *" comment.
*/
-function prepareConfig(config, envContext) {
- config.globals = config.globals || {};
- const copiedRules = {};
- let parserOptions = {};
+function findEslintEnv(text) {
+ let match, retv;
- if (typeof config.rules === "object") {
- Object.keys(config.rules).forEach(k => {
- const rule = config.rules[k];
+ eslintEnvPattern.lastIndex = 0;
- if (rule === null) {
- throw new Error(`Invalid config for rule '${k}'.`);
- }
- if (Array.isArray(rule)) {
- copiedRules[k] = rule.slice();
- } else {
- copiedRules[k] = rule;
- }
- });
+ while ((match = eslintEnvPattern.exec(text))) {
+ retv = Object.assign(retv || {}, parseListConfig(match[1]));
}
- // merge in environment parserOptions
- if (typeof config.env === "object") {
- Object.keys(config.env).forEach(envName => {
- const env = envContext.get(envName);
+ return retv;
+}
- if (config.env[envName] && env && env.parserOptions) {
- parserOptions = ConfigOps.merge(parserOptions, env.parserOptions);
- }
- });
- }
+/**
+ * Normalizes the possible options for `linter.verify` and `linter.verifyAndFix` to a
+ * consistent shape.
+ * @param {(string|{reportUnusedDisableDirectives: boolean, filename: string, allowInlineConfig: boolean})} providedOptions Options
+ * @returns {{reportUnusedDisableDirectives: boolean, filename: string, allowInlineConfig: boolean}} Normalized options
+ */
+function normalizeVerifyOptions(providedOptions) {
+ const isObjectOptions = typeof providedOptions === "object";
+ const providedFilename = isObjectOptions ? providedOptions.filename : providedOptions;
- const preparedConfig = {
- rules: copiedRules,
- parser: config.parser || defaultConfig.parser,
- globals: ConfigOps.merge(defaultConfig.globals, config.globals),
- env: ConfigOps.merge(defaultConfig.env, config.env || {}),
- settings: ConfigOps.merge(defaultConfig.settings, config.settings || {}),
- parserOptions: ConfigOps.merge(parserOptions, config.parserOptions || {})
+ return {
+ filename: typeof providedFilename === "string" ? providedFilename : "<input>",
+ allowInlineConfig: !isObjectOptions || providedOptions.allowInlineConfig !== false,
+ reportUnusedDisableDirectives: isObjectOptions && !!providedOptions.reportUnusedDisableDirectives
};
- const isModule = preparedConfig.parserOptions.sourceType === "module";
+}
+
+/**
+ * Combines the provided parserOptions with the options from environments
+ * @param {Object} providedOptions The provided 'parserOptions' key in a config
+ * @param {Environment[]} enabledEnvironments The environments enabled in configuration and with inline comments
+ * @returns {Object} Resulting parser options after merge
+ */
+function resolveParserOptions(providedOptions, enabledEnvironments) {
+ const parserOptionsFromEnv = enabledEnvironments
+ .filter(env => env.parserOptions)
+ .reduce((parserOptions, env) => ConfigOps.merge(parserOptions, env.parserOptions), {});
+
+ const mergedParserOptions = ConfigOps.merge(parserOptionsFromEnv, providedOptions || {});
+
+ const isModule = mergedParserOptions.sourceType === "module";
if (isModule) {
// can't have global return inside of modules
- preparedConfig.parserOptions.ecmaFeatures = Object.assign({}, preparedConfig.parserOptions.ecmaFeatures, { globalReturn: false });
+ mergedParserOptions.ecmaFeatures = Object.assign({}, mergedParserOptions.ecmaFeatures, { globalReturn: false });
}
- preparedConfig.parserOptions.ecmaVersion = normalizeEcmaVersion(preparedConfig.parserOptions.ecmaVersion, isModule);
+ mergedParserOptions.ecmaVersion = normalizeEcmaVersion(mergedParserOptions.ecmaVersion, isModule);
- return preparedConfig;
+ return mergedParserOptions;
}
-const eslintEnvPattern = /\/\*\s*eslint-env\s(.+?)\*\//g;
-
/**
- * Checks whether or not there is a comment which has "eslint-env *" in a given text.
- * @param {string} text - A source code text to check.
- * @returns {Object|null} A result of parseListConfig() with "eslint-env *" comment.
+ * Combines the provided globals object with the globals from environments
+ * @param {Object} providedGlobals The 'globals' key in a config
+ * @param {Environments[]} enabledEnvironments The environments enabled in configuration and with inline comments
+ * @returns {Object} The resolved globals object
*/
-function findEslintEnv(text) {
- let match, retv;
-
- eslintEnvPattern.lastIndex = 0;
-
- while ((match = eslintEnvPattern.exec(text))) {
- retv = Object.assign(retv || {}, parseListConfig(match[1]));
- }
-
- return retv;
+function resolveGlobals(providedGlobals, enabledEnvironments) {
+ return Object.assign.apply(
+ null,
+ [{}]
+ .concat(enabledEnvironments.filter(env => env.globals).map(env => env.globals))
+ .concat(providedGlobals)
+ );
}
/**
@@ -532,13 +512,16 @@ function analyzeScope(ast, parserOptions, visitorKeys) {
* as possible
* @param {string} text The text to parse.
* @param {Object} providedParserOptions Options to pass to the parser
- * @param {Object} parser The parser module
+ * @param {string} parserName The name of the parser
+ * @param {Map<string, Object>} parserMap A map from names to loaded parsers
* @param {string} filePath The path to the file being parsed.
* @returns {{success: false, error: Problem}|{success: true, sourceCode: SourceCode}}
* An object containing the AST and parser services if parsing was successful, or the error if parsing failed
* @private
*/
-function parse(text, providedParserOptions, parser, filePath) {
+function parse(text, providedParserOptions, parserName, parserMap, filePath) {
+
+
const textToParse = stripUnicodeBOM(text).replace(astUtils.SHEBANG_MATCHER, (match, captured) => `//${captured}`);
const parserOptions = Object.assign({}, providedParserOptions, {
loc: true,
@@ -551,6 +534,25 @@ function parse(text, providedParserOptions, parser, filePath) {
filePath
});
+ let parser;
+
+ try {
+ parser = parserMap.get(parserName) || require(parserName);
+ } catch (ex) {
+ return {
+ success: false,
+ error: {
+ ruleId: null,
+ fatal: true,
+ severity: 2,
+ source: null,
+ message: ex.message,
+ line: 0,
+ column: 0
+ }
+ };
+ }
+
/*
* Check for parsing errors first. If there's a parsing error, nothing
* else can happen. However, a parsing error does not throw an error
@@ -669,6 +671,21 @@ function markVariableAsUsed(scopeManager, currentNode, parserOptions, name) {
return false;
}
+/**
+ * Runs a rule, and gets its listeners
+ * @param {Rule} rule A normalized rule with a `create` method
+ * @param {Context} ruleContext The context that should be passed to the rule
+ * @returns {Object} A map of selector listeners provided by the rule
+ */
+function createRuleListeners(rule, ruleContext) {
+ try {
+ return rule.create(ruleContext);
+ } catch (ex) {
+ ex.message = `Error while loading rule '${ruleContext.id}': ${ex.message}`;
+ throw ex;
+ }
+}
+
// methods that exist on SourceCode object
const DEPRECATED_SOURCECODE_PASSTHROUGHS = {
getSource: "getText",
@@ -707,7 +724,157 @@ const BASE_TRAVERSAL_CONTEXT = Object.freeze(
)
);
+/**
+ * Runs the given rules on the given SourceCode object
+ * @param {SourceCode} sourceCode A SourceCode object for the given text
+ * @param {Object} configuredRules The rules configuration
+ * @param {function(string): Rule} ruleMapper A mapper function from rule names to rules
+ * @param {Object} parserOptions The options that were passed to the parser
+ * @param {string} parserName The name of the parser in the config
+ * @param {Object} settings The settings that were enabled in the config
+ * @param {string} filename The reported filename of the code
+ * @returns {Problem[]} An array of reported problems
+ */
+function runRules(sourceCode, configuredRules, ruleMapper, parserOptions, parserName, settings, filename) {
+ const emitter = createEmitter();
+ const traverser = new Traverser();
+
+ /*
+ * Create a frozen object with the ruleContext properties and methods that are shared by all rules.
+ * All rule contexts will inherit from this object. This avoids the performance penalty of copying all the
+ * properties once for each rule.
+ */
+ const sharedTraversalContext = Object.freeze(
+ Object.assign(
+ Object.create(BASE_TRAVERSAL_CONTEXT),
+ {
+ getAncestors: () => traverser.parents(),
+ getDeclaredVariables: sourceCode.scopeManager.getDeclaredVariables.bind(sourceCode.scopeManager),
+ getFilename: () => filename,
+ getScope: () => getScope(sourceCode.scopeManager, traverser.current(), parserOptions.ecmaVersion),
+ getSourceCode: () => sourceCode,
+ markVariableAsUsed: name => markVariableAsUsed(sourceCode.scopeManager, traverser.current(), parserOptions, name),
+ parserOptions,
+ parserPath: parserName,
+ parserServices: sourceCode.parserServices,
+ settings,
+
+ /**
+ * This is used to avoid breaking rules that used to monkeypatch the `Linter#report` method
+ * by using the `_linter` property on rule contexts.
+ *
+ * This should be removed in a major release after we create a better way to
+ * lint for unused disable comments.
+ * https://github.com/eslint/eslint/issues/9193
+ */
+ _linter: {
+ report() {},
+ on: emitter.on
+ }
+ }
+ )
+ );
+
+
+ const lintingProblems = [];
+
+ Object.keys(configuredRules).forEach(ruleId => {
+ const severity = ConfigOps.getRuleSeverity(configuredRules[ruleId]);
+
+ if (severity === 0) {
+ return;
+ }
+
+ const rule = ruleMapper(ruleId);
+ const messageIds = rule.meta && rule.meta.messages;
+ let reportTranslator = null;
+ const ruleContext = Object.freeze(
+ Object.assign(
+ Object.create(sharedTraversalContext),
+ {
+ id: ruleId,
+ options: getRuleOptions(configuredRules[ruleId]),
+ report() {
+
+ /*
+ * Create a report translator lazily.
+ * In a vast majority of cases, any given rule reports zero errors on a given
+ * piece of code. Creating a translator lazily avoids the performance cost of
+ * creating a new translator function for each rule that usually doesn't get
+ * called.
+ *
+ * Using lazy report translators improves end-to-end performance by about 3%
+ * with Node 8.4.0.
+ */
+ if (reportTranslator === null) {
+ reportTranslator = createReportTranslator({ ruleId, severity, sourceCode, messageIds });
+ }
+ const problem = reportTranslator.apply(null, arguments);
+
+ if (problem.fix && rule.meta && !rule.meta.fixable) {
+ throw new Error("Fixable rules should export a `meta.fixable` property.");
+ }
+ lintingProblems.push(problem);
+
+ /*
+ * This is used to avoid breaking rules that used monkeypatch Linter, and relied on
+ * `linter.report` getting called with report info every time a rule reports a problem.
+ * To continue to support this, make sure that `context._linter.report` is called every
+ * time a problem is reported by a rule, even though `context._linter` is no longer a
+ * `Linter` instance.
+ *
+ * This should be removed in a major release after we create a better way to
+ * lint for unused disable comments.
+ * https://github.com/eslint/eslint/issues/9193
+ */
+ sharedTraversalContext._linter.report( // eslint-disable-line no-underscore-dangle
+ problem.ruleId,
+ problem.severity,
+ { loc: { start: { line: problem.line, column: problem.column - 1 } } },
+ problem.message
+ );
+ }
+ }
+ )
+ );
+
+ const ruleListeners = createRuleListeners(rule, ruleContext);
+
+ // add all the selectors from the rule as listeners
+ Object.keys(ruleListeners).forEach(selector => {
+ emitter.on(
+ selector,
+ timing.enabled
+ ? timing.time(ruleId, ruleListeners[selector])
+ : ruleListeners[selector]
+ );
+ });
+ });
+
+ const eventGenerator = new CodePathAnalyzer(new NodeEventGenerator(emitter));
+
+ /*
+ * Each node has a type property. Whenever a particular type of
+ * node is found, an event is fired. This allows any listeners to
+ * automatically be informed that this type of node has been found
+ * and react accordingly.
+ */
+ traverser.traverse(sourceCode.ast, {
+ enter(node, parent) {
+ node.parent = parent;
+ eventGenerator.enterNode(node);
+ },
+ leave(node) {
+ eventGenerator.leaveNode(node);
+ },
+ visitorKeys: sourceCode.visitorKeys
+ });
+
+ return lintingProblems;
+}
+
const lastSourceCodes = new WeakMap();
+const loadedParserMaps = new WeakMap();
//------------------------------------------------------------------------------
// Public Interface
@@ -721,10 +888,10 @@ module.exports = class Linter {
constructor() {
lastSourceCodes.set(this, null);
+ loadedParserMaps.set(this, new Map());
this.version = pkg.version;
this.rules = new Rules();
- this._parsers = new Map();
this.environments = new Environments();
}
@@ -742,7 +909,7 @@ module.exports = class Linter {
/**
* Same as linter.verify, except without support for processors.
* @param {string|SourceCode} textOrSourceCode The text to parse or a SourceCode object.
- * @param {ESLintConfig} config An ESLintConfig instance to configure everything.
+ * @param {ESLintConfig} providedConfig An ESLintConfig instance to configure everything.
* @param {(string|Object)} [filenameOrOptions] The optional filename of the file being checked.
* If this is not set, the filename will default to '<input>' in the rule context. If
* an object, then it has "filename", "saveState", and "allowInlineConfig" properties.
@@ -750,23 +917,14 @@ module.exports = class Linter {
* Useful if you want to validate JS without comments overriding rules.
* @param {boolean} [filenameOrOptions.reportUnusedDisableDirectives=false] Adds reported errors for unused
* eslint-disable directives
- * @returns {Object[]} The results as an array of messages or null if no messages.
+ * @returns {Object[]} The results as an array of messages or an empty array if no messages.
*/
- _verifyWithoutProcessors(textOrSourceCode, config, filenameOrOptions) {
- let text,
- allowInlineConfig,
- providedFilename,
- reportUnusedDisableDirectives;
+ _verifyWithoutProcessors(textOrSourceCode, providedConfig, filenameOrOptions) {
+ const config = providedConfig || {};
+ const options = normalizeVerifyOptions(filenameOrOptions);
+ let text;
// evaluate arguments
- if (typeof filenameOrOptions === "object") {
- providedFilename = filenameOrOptions.filename;
- allowInlineConfig = filenameOrOptions.allowInlineConfig;
- reportUnusedDisableDirectives = filenameOrOptions.reportUnusedDisableDirectives;
- } else {
- providedFilename = filenameOrOptions;
- }
-
if (typeof textOrSourceCode === "string") {
lastSourceCodes.set(this, null);
text = textOrSourceCode;
@@ -775,23 +933,18 @@ module.exports = class Linter {
text = textOrSourceCode.text;
}
- const filename = typeof providedFilename === "string" ? providedFilename : "<input>";
-
// search and apply "eslint-env *".
const envInFile = findEslintEnv(text);
+ const resolvedEnvConfig = Object.assign({ builtin: true }, config.env, envInFile);
+ const enabledEnvs = Object.keys(resolvedEnvConfig)
+ .filter(envName => resolvedEnvConfig[envName])
+ .map(envName => this.environments.get(envName))
+ .filter(env => env);
- config = Object.assign({}, config);
-
- if (envInFile) {
- if (config.env) {
- config.env = Object.assign({}, config.env, envInFile);
- } else {
- config.env = envInFile;
- }
- }
-
- // process initial config to make it safe to extend
- config = prepareConfig(config, this.environments);
+ const parserOptions = resolveParserOptions(config.parserOptions || {}, enabledEnvs);
+ const configuredGlobals = resolveGlobals(config.globals || {}, enabledEnvs);
+ const parserName = config.parser || DEFAULT_PARSER_NAME;
+ const settings = config.settings || {};
if (!lastSourceCodes.get(this)) {
@@ -801,26 +954,12 @@ module.exports = class Linter {
return [];
}
- let parser;
-
- try {
- parser = this._parsers.get(config.parser) || require(config.parser);
- } catch (ex) {
- return [{
- ruleId: null,
- fatal: true,
- severity: 2,
- source: null,
- message: ex.message,
- line: 0,
- column: 0
- }];
- }
const parseResult = parse(
text,
- config.parserOptions,
- parser,
- filename
+ parserOptions,
+ parserName,
+ loadedParserMaps.get(this),
+ options.filename
);
if (!parseResult.success) {
@@ -842,171 +981,41 @@ module.exports = class Linter {
ast: lastSourceCode.ast,
parserServices: lastSourceCode.parserServices,
visitorKeys: lastSourceCode.visitorKeys,
- scopeManager: analyzeScope(lastSourceCode.ast, config.parserOptions)
+ scopeManager: analyzeScope(lastSourceCode.ast, parserOptions)
}));
}
}
- const problems = [];
const sourceCode = lastSourceCodes.get(this);
- let disableDirectives;
-
- // parse global comments and modify config
- if (allowInlineConfig !== false) {
- const modifyConfigResult = modifyConfigsFromComments(filename, sourceCode.ast, config, ruleId => this.rules.get(ruleId));
-
- config = modifyConfigResult.config;
- modifyConfigResult.problems.forEach(problem => problems.push(problem));
- disableDirectives = modifyConfigResult.disableDirectives;
- } else {
- disableDirectives = [];
- }
-
- const emitter = createEmitter();
- const traverser = new Traverser();
- const scopeManager = sourceCode.scopeManager;
-
- /*
- * Create a frozen object with the ruleContext properties and methods that are shared by all rules.
- * All rule contexts will inherit from this object. This avoids the performance penalty of copying all the
- * properties once for each rule.
- */
- const sharedTraversalContext = Object.freeze(
- Object.assign(
- Object.create(BASE_TRAVERSAL_CONTEXT),
- {
- getAncestors: () => traverser.parents(),
- getDeclaredVariables: scopeManager.getDeclaredVariables.bind(scopeManager),
- getFilename: () => filename,
- getScope: () => getScope(scopeManager, traverser.current(), config.parserOptions.ecmaVersion),
- getSourceCode: () => sourceCode,
- markVariableAsUsed: name => markVariableAsUsed(scopeManager, traverser.current(), config.parserOptions, name),
- parserOptions: config.parserOptions,
- parserPath: config.parser,
- parserServices: sourceCode.parserServices,
- settings: config.settings,
-
- /**
- * This is used to avoid breaking rules that used to monkeypatch the `Linter#report` method
- * by using the `_linter` property on rule contexts.
- *
- * This should be removed in a major release after we create a better way to
- * lint for unused disable comments.
- * https://github.com/eslint/eslint/issues/9193
- */
- _linter: {
- report() {},
- on: emitter.on
- }
- }
- )
- );
-
- // enable appropriate rules
- Object.keys(config.rules).forEach(ruleId => {
- const severity = ConfigOps.getRuleSeverity(config.rules[ruleId]);
-
- if (severity === 0) {
- return;
- }
-
- const rule = this.rules.get(ruleId);
- const messageIds = rule && rule.meta && rule.meta.messages;
- let reportTranslator = null;
- const ruleContext = Object.freeze(
- Object.assign(
- Object.create(sharedTraversalContext),
- {
- id: ruleId,
- options: getRuleOptions(config.rules[ruleId]),
- report() {
-
- /*
- * Create a report translator lazily.
- * In a vast majority of cases, any given rule reports zero errors on a given
- * piece of code. Creating a translator lazily avoids the performance cost of
- * creating a new translator function for each rule that usually doesn't get
- * called.
- *
- * Using lazy report translators improves end-to-end performance by about 3%
- * with Node 8.4.0.
- */
- if (reportTranslator === null) {
- reportTranslator = createReportTranslator({ ruleId, severity, sourceCode, messageIds });
- }
- const problem = reportTranslator.apply(null, arguments);
-
- if (problem.fix && rule.meta && !rule.meta.fixable) {
- throw new Error("Fixable rules should export a `meta.fixable` property.");
- }
- problems.push(problem);
-
- /*
- * This is used to avoid breaking rules that used monkeypatch Linter, and relied on
- * `linter.report` getting called with report info every time a rule reports a problem.
- * To continue to support this, make sure that `context._linter.report` is called every
- * time a problem is reported by a rule, even though `context._linter` is no longer a
- * `Linter` instance.
- *
- * This should be removed in a major release after we create a better way to
- * lint for unused disable comments.
- * https://github.com/eslint/eslint/issues/9193
- */
- sharedTraversalContext._linter.report( // eslint-disable-line no-underscore-dangle
- problem.ruleId,
- problem.severity,
- { loc: { start: { line: problem.line, column: problem.column - 1 } } },
- problem.message
- );
- }
- }
- )
- );
-
- try {
- const ruleListeners = rule.create(ruleContext);
-
- // add all the selectors from the rule as listeners
- Object.keys(ruleListeners).forEach(selector => {
- emitter.on(
- selector,
- timing.enabled
- ? timing.time(ruleId, ruleListeners[selector])
- : ruleListeners[selector]
- );
- });
- } catch (ex) {
- ex.message = `Error while loading rule '${ruleId}': ${ex.message}`;
- throw ex;
- }
- });
+ const commentDirectives = options.allowInlineConfig
+ ? getDirectiveComments(options.filename, sourceCode.ast, ruleId => this.rules.get(ruleId))
+ : { configuredRules: {}, enabledGlobals: {}, exportedVariables: {}, problems: [], disableDirectives: [] };
// augment global scope with declared global variables
- addDeclaredGlobals(scopeManager.scopes[0], config, this.environments);
+ addDeclaredGlobals(
+ sourceCode.scopeManager.scopes[0],
+ configuredGlobals,
+ { exportedVariables: commentDirectives.exportedVariables, enabledGlobals: commentDirectives.enabledGlobals }
+ );
- const eventGenerator = new CodePathAnalyzer(new NodeEventGenerator(emitter));
+ const configuredRules = Object.assign({}, config.rules, commentDirectives.configuredRules);
- /*
- * Each node has a type property. Whenever a particular type of
- * node is found, an event is fired. This allows any listeners to
- * automatically be informed that this type of node has been found
- * and react accordingly.
- */
- traverser.traverse(sourceCode.ast, {
- enter(node, parent) {
- node.parent = parent;
- eventGenerator.enterNode(node);
- },
- leave(node) {
- eventGenerator.leaveNode(node);
- },
- visitorKeys: sourceCode.visitorKeys
- });
+ const lintingProblems = runRules(
+ sourceCode,
+ configuredRules,
+ ruleId => this.rules.get(ruleId),
+ parserOptions,
+ parserName,
+ settings,
+ options.filename
+ );
return applyDisableDirectives({
- directives: disableDirectives,
- problems: problems.sort((problemA, problemB) => problemA.line - problemB.line || problemA.column - problemB.column),
- reportUnusedDisableDirectives
+ directives: commentDirectives.disableDirectives,
+ problems: lintingProblems
+ .concat(commentDirectives.problems)
+ .sort((problemA, problemB) => problemA.line - problemB.line || problemA.column - problemB.column),
+ reportUnusedDisableDirectives: options.reportUnusedDisableDirectives
});
}
@@ -1026,7 +1035,7 @@ module.exports = class Linter {
* @param {function(Array<Object[]>): Object[]} [filenameOrOptions.postprocess] postprocessor for report messages. If provided,
* this should accept an array of the message lists for each code block returned from the preprocessor,
* apply a mapping to the messages as appropriate, and return a one-dimensional array of messages
- * @returns {Object[]} The results as an array of messages or null if no messages.
+ * @returns {Object[]} The results as an array of messages or an empty array if no messages.
*/
verify(textOrSourceCode, config, filenameOrOptions) {
const preprocess = filenameOrOptions && filenameOrOptions.preprocess || (rawText => [rawText]);
@@ -1083,7 +1092,7 @@ module.exports = class Linter {
* @returns {void}
*/
defineParser(parserId, parserModule) {
- this._parsers.set(parserId, parserModule);
+ loadedParserMaps.get(this).set(parserId, parserModule);
}
/**
@@ -1108,7 +1117,8 @@ module.exports = class Linter {
let messages = [],
fixedResult,
fixed = false,
- passNumber = 0;
+ passNumber = 0,
+ currentText = text;
const debugTextDescription = options && options.filename || `${text.slice(0, 10)}...`;
const shouldFix = options && typeof options.fix !== "undefined" ? options.fix : true;
@@ -1125,10 +1135,10 @@ module.exports = class Linter {
passNumber++;
debug(`Linting code for ${debugTextDescription} (pass ${passNumber})`);
- messages = this.verify(text, config, options);
+ messages = this.verify(currentText, config, options);
debug(`Generating fixed text for ${debugTextDescription} (pass ${passNumber})`);
- fixedResult = SourceCodeFixer.applyFixes(text, messages, shouldFix);
+ fixedResult = SourceCodeFixer.applyFixes(currentText, messages, shouldFix);
/*
* stop if there are any syntax errors.
@@ -1142,7 +1152,7 @@ module.exports = class Linter {
fixed = fixed || fixedResult.fixed;
// update to use the fixed output instead of the original text
- text = fixedResult.output;
+ currentText = fixedResult.output;
} while (
fixedResult.fixed &&
@@ -1154,12 +1164,12 @@ module.exports = class Linter {
* the most up-to-date information.
*/
if (fixedResult.fixed) {
- fixedResult.messages = this.verify(text, config, options);
+ fixedResult.messages = this.verify(currentText, config, options);
}
// ensure the last result properly reflects if fixes were done
fixedResult.fixed = fixed;
- fixedResult.output = text;
+ fixedResult.output = currentText;
return fixedResult;
}
diff --git a/tools/node_modules/eslint/lib/load-rules.js b/tools/node_modules/eslint/lib/load-rules.js
index b74905d65a..a9da956bdd 100644
--- a/tools/node_modules/eslint/lib/load-rules.js
+++ b/tools/node_modules/eslint/lib/load-rules.js
@@ -20,16 +20,15 @@ const rulesDirCache = {};
/**
* Load all rule modules from specified directory.
- * @param {string} [rulesDir] Path to rules directory, may be relative. Defaults to `lib/rules`.
+ * @param {string} [relativeRulesDir] Path to rules directory, may be relative. Defaults to `lib/rules`.
* @param {string} cwd Current working directory
* @returns {Object} Loaded rule modules by rule ids (file names).
*/
-module.exports = function(rulesDir, cwd) {
- if (!rulesDir) {
- rulesDir = path.join(__dirname, "rules");
- } else {
- rulesDir = path.resolve(cwd, rulesDir);
- }
+module.exports = function(relativeRulesDir, cwd) {
+
+ const rulesDir = relativeRulesDir
+ ? path.resolve(cwd, relativeRulesDir)
+ : path.join(__dirname, "rules");
// cache will help performance as IO operation are expensive
if (rulesDirCache[rulesDir]) {
diff --git a/tools/node_modules/eslint/lib/options.js b/tools/node_modules/eslint/lib/options.js
index c8005d4445..9265d151d5 100644
--- a/tools/node_modules/eslint/lib/options.js
+++ b/tools/node_modules/eslint/lib/options.js
@@ -27,16 +27,16 @@ module.exports = optionator({
heading: "Basic configuration"
},
{
- option: "config",
- alias: "c",
- type: "path::String",
- description: "Use configuration from this file or shareable config"
- },
- {
option: "eslintrc",
type: "Boolean",
default: "true",
- description: "Disable use of configuration from .eslintrc"
+ description: "Disable use of configuration from .eslintrc.*"
+ },
+ {
+ option: "config",
+ alias: "c",
+ type: "path::String",
+ description: "Use this configuration, overriding .eslintrc.* config options if present"
},
{
option: "env",
diff --git a/tools/node_modules/eslint/lib/report-translator.js b/tools/node_modules/eslint/lib/report-translator.js
index 8e5b587f96..7893a1f7ad 100644
--- a/tools/node_modules/eslint/lib/report-translator.js
+++ b/tools/node_modules/eslint/lib/report-translator.js
@@ -28,6 +28,22 @@ const interpolate = require("./util/interpolate");
* @property {Function} [fix] The function to call that creates a fix command.
*/
+/**
+ * Information about the report
+ * @typedef {Object} ReportInfo
+ * @property {string} ruleId
+ * @property {(0|1|2)} severity
+ * @property {(string|undefined)} message
+ * @property {(string|undefined)} messageId
+ * @property {number} line
+ * @property {number} column
+ * @property {(number|undefined)} endLine
+ * @property {(number|undefined)} endColumn
+ * @property {(string|null)} nodeType
+ * @property {string} source
+ * @property {({text: string, range: (number[]|null)}|null)} fix
+ */
+
//------------------------------------------------------------------------------
// Module Definition
//------------------------------------------------------------------------------
@@ -121,7 +137,7 @@ function compareFixesByRange(a, b) {
* Merges the given fixes array into one.
* @param {Fix[]} fixes The fixes to merge.
* @param {SourceCode} sourceCode The source code object to get the text between fixes.
- * @returns {{text: string, range: [number, number]}} The merged fixes
+ * @returns {{text: string, range: number[]}} The merged fixes
*/
function mergeFixes(fixes, sourceCode) {
if (fixes.length === 0) {
@@ -158,7 +174,7 @@ function mergeFixes(fixes, sourceCode) {
* If the descriptor retrieves multiple fixes, this merges those to one.
* @param {MessageDescriptor} descriptor The report descriptor.
* @param {SourceCode} sourceCode The source code object to get text between fixes.
- * @returns {({text: string, range: [number, number]}|null)} The fix for the descriptor
+ * @returns {({text: string, range: number[]}|null)} The fix for the descriptor
*/
function normalizeFixes(descriptor, sourceCode) {
if (typeof descriptor.fix !== "function") {
@@ -177,27 +193,15 @@ function normalizeFixes(descriptor, sourceCode) {
/**
* Creates information about the report from a descriptor
- * @param {{
- * ruleId: string,
- * severity: (0|1|2),
- * node: (ASTNode|null),
- * message: string,
- * loc: {start: SourceLocation, end: (SourceLocation|null)},
- * fix: ({text: string, range: [number, number]}|null),
- * sourceLines: string[]
- * }} options Information about the problem
- * @returns {function(...args): {
- * ruleId: string,
- * severity: (0|1|2),
- * message: string,
- * line: number,
- * column: number,
- * endLine: (number|undefined),
- * endColumn: (number|undefined),
- * nodeType: (string|null),
- * source: string,
- * fix: ({text: string, range: [number, number]}|null)
- * }} Information about the report
+ * @param {Object} options Information about the problem
+ * @param {string} options.ruleId Rule ID
+ * @param {(0|1|2)} options.severity Rule severity
+ * @param {(ASTNode|null)} options.node Node
+ * @param {string} options.message Error message
+ * @param {{start: SourceLocation, end: (SourceLocation|null)}} options.loc Start and end location
+ * @param {{text: string, range: (number[]|null)}} options.fix The fix object
+ * @param {string[]} options.sourceLines Source lines
+ * @returns {function(...args): ReportInfo} Function that returns information about the report
*/
function createProblem(options) {
const problem = {
@@ -235,20 +239,7 @@ function createProblem(options) {
* problem for the Node.js API.
* @param {{ruleId: string, severity: number, sourceCode: SourceCode, messageIds: Object}} metadata Metadata for the reported problem
* @param {SourceCode} sourceCode The `SourceCode` instance for the text being linted
- * @returns {function(...args): {
- * ruleId: string,
- * severity: (0|1|2),
- * message: (string|undefined),
- * messageId: (string|undefined),
- * line: number,
- * column: number,
- * endLine: (number|undefined),
- * endColumn: (number|undefined),
- * nodeType: (string|null),
- * source: string,
- * fix: ({text: string, range: [number, number]}|null)
- * }}
- * Information about the report
+ * @returns {function(...args): ReportInfo} Function that returns information about the report
*/
module.exports = function createReportTranslator(metadata) {
diff --git a/tools/node_modules/eslint/lib/rules/accessor-pairs.js b/tools/node_modules/eslint/lib/rules/accessor-pairs.js
index b01b29b176..6860729543 100644
--- a/tools/node_modules/eslint/lib/rules/accessor-pairs.js
+++ b/tools/node_modules/eslint/lib/rules/accessor-pairs.js
@@ -58,11 +58,11 @@ function isPropertyDescriptor(node) {
* Object.defineProperties(obj, {foo: {set: ...}})
* Object.create(proto, {foo: {set: ...}})
*/
- node = node.parent.parent;
+ const grandparent = node.parent.parent;
- return node.type === "ObjectExpression" && (
- isArgumentOfMethodCall(node, 1, "Object", "create") ||
- isArgumentOfMethodCall(node, 1, "Object", "defineProperties")
+ return grandparent.type === "ObjectExpression" && (
+ isArgumentOfMethodCall(grandparent, 1, "Object", "create") ||
+ isArgumentOfMethodCall(grandparent, 1, "Object", "defineProperties")
);
}
@@ -89,7 +89,11 @@ module.exports = {
}
},
additionalProperties: false
- }]
+ }],
+ messages: {
+ getter: "Getter is not present.",
+ setter: "Setter is not present."
+ }
},
create(context) {
const config = context.options[0] || {};
@@ -140,9 +144,9 @@ module.exports = {
}
if (checkSetWithoutGet && isSetPresent && !isGetPresent) {
- context.report({ node, message: "Getter is not present." });
+ context.report({ node, messageId: "getter" });
} else if (checkGetWithoutSet && isGetPresent && !isSetPresent) {
- context.report({ node, message: "Setter is not present." });
+ context.report({ node, messageId: "setter" });
}
}
diff --git a/tools/node_modules/eslint/lib/rules/array-bracket-newline.js b/tools/node_modules/eslint/lib/rules/array-bracket-newline.js
index b939d65b3f..e190405726 100644
--- a/tools/node_modules/eslint/lib/rules/array-bracket-newline.js
+++ b/tools/node_modules/eslint/lib/rules/array-bracket-newline.js
@@ -41,7 +41,13 @@ module.exports = {
}
]
}
- ]
+ ],
+ messages: {
+ unexpectedOpeningLinebreak: "There should be no linebreak after '['.",
+ unexpectedClosingLinebreak: "There should be no linebreak before ']'.",
+ missingOpeningLinebreak: "A linebreak is required after '['.",
+ missingClosingLinebreak: "A linebreak is required before ']'."
+ }
},
create(context) {
@@ -106,7 +112,7 @@ module.exports = {
context.report({
node,
loc: token.loc,
- message: "There should be no linebreak after '['.",
+ messageId: "unexpectedOpeningLinebreak",
fix(fixer) {
const nextToken = sourceCode.getTokenAfter(token, { includeComments: true });
@@ -129,7 +135,7 @@ module.exports = {
context.report({
node,
loc: token.loc,
- message: "There should be no linebreak before ']'.",
+ messageId: "unexpectedClosingLinebreak",
fix(fixer) {
const previousToken = sourceCode.getTokenBefore(token, { includeComments: true });
@@ -152,7 +158,7 @@ module.exports = {
context.report({
node,
loc: token.loc,
- message: "A linebreak is required after '['.",
+ messageId: "missingOpeningLinebreak",
fix(fixer) {
return fixer.insertTextAfter(token, "\n");
}
@@ -169,7 +175,7 @@ module.exports = {
context.report({
node,
loc: token.loc,
- message: "A linebreak is required before ']'.",
+ messageId: "missingClosingLinebreak",
fix(fixer) {
return fixer.insertTextBefore(token, "\n");
}
diff --git a/tools/node_modules/eslint/lib/rules/array-bracket-spacing.js b/tools/node_modules/eslint/lib/rules/array-bracket-spacing.js
index 933458a42a..c64ff3dc27 100644
--- a/tools/node_modules/eslint/lib/rules/array-bracket-spacing.js
+++ b/tools/node_modules/eslint/lib/rules/array-bracket-spacing.js
@@ -38,7 +38,13 @@ module.exports = {
},
additionalProperties: false
}
- ]
+ ],
+ messages: {
+ unexpectedSpaceAfter: "There should be no space after '{{tokenValue}}'.",
+ unexpectedSpaceBefore: "There should be no space before '{{tokenValue}}'.",
+ missingSpaceAfter: "A space is required after '{{tokenValue}}'.",
+ missingSpaceBefore: "A space is required before '{{tokenValue}}'."
+ }
},
create(context) {
const spaced = context.options[0] === "always",
@@ -76,7 +82,7 @@ module.exports = {
context.report({
node,
loc: token.loc.start,
- message: "There should be no space after '{{tokenValue}}'.",
+ messageId: "unexpectedSpaceAfter",
data: {
tokenValue: token.value
},
@@ -98,7 +104,7 @@ module.exports = {
context.report({
node,
loc: token.loc.start,
- message: "There should be no space before '{{tokenValue}}'.",
+ messageId: "unexpectedSpaceBefore",
data: {
tokenValue: token.value
},
@@ -120,7 +126,7 @@ module.exports = {
context.report({
node,
loc: token.loc.start,
- message: "A space is required after '{{tokenValue}}'.",
+ messageId: "missingSpaceAfter",
data: {
tokenValue: token.value
},
@@ -140,7 +146,7 @@ module.exports = {
context.report({
node,
loc: token.loc.start,
- message: "A space is required before '{{tokenValue}}'.",
+ messageId: "missingSpaceBefore",
data: {
tokenValue: token.value
},
diff --git a/tools/node_modules/eslint/lib/rules/array-callback-return.js b/tools/node_modules/eslint/lib/rules/array-callback-return.js
index 69655481d8..2375dcba9b 100644
--- a/tools/node_modules/eslint/lib/rules/array-callback-return.js
+++ b/tools/node_modules/eslint/lib/rules/array-callback-return.js
@@ -71,8 +71,10 @@ function isTargetMethod(node) {
* @returns {boolean} `true` if the node is the callback of an array method.
*/
function isCallbackOfArrayMethod(node) {
- while (node) {
- const parent = node.parent;
+ let currentNode = node;
+
+ while (currentNode) {
+ const parent = currentNode.parent;
switch (parent.type) {
@@ -82,7 +84,7 @@ function isCallbackOfArrayMethod(node) {
*/
case "LogicalExpression":
case "ConditionalExpression":
- node = parent;
+ currentNode = parent;
break;
/*
@@ -99,7 +101,7 @@ function isCallbackOfArrayMethod(node) {
if (func === null || !astUtils.isCallee(func)) {
return false;
}
- node = func.parent;
+ currentNode = func.parent;
break;
}
@@ -112,13 +114,13 @@ function isCallbackOfArrayMethod(node) {
if (astUtils.isArrayFromMethod(parent.callee)) {
return (
parent.arguments.length >= 2 &&
- parent.arguments[1] === node
+ parent.arguments[1] === currentNode
);
}
if (isTargetMethod(parent.callee)) {
return (
parent.arguments.length >= 1 &&
- parent.arguments[0] === node
+ parent.arguments[0] === currentNode
);
}
return false;
@@ -156,7 +158,13 @@ module.exports = {
},
additionalProperties: false
}
- ]
+ ],
+
+ messages: {
+ expectedAtEnd: "Expected to return a value at the end of {{name}}.",
+ expectedInside: "Expected to return a value in {{name}}.",
+ expectedReturnValue: "{{name}} expected a return value."
+ }
},
create(context) {
@@ -188,9 +196,9 @@ module.exports = {
context.report({
node,
loc: getLocation(node, context.getSourceCode()).loc.start,
- message: funcInfo.hasReturn
- ? "Expected to return a value at the end of {{name}}."
- : "Expected to return a value in {{name}}.",
+ messageId: funcInfo.hasReturn
+ ? "expectedAtEnd"
+ : "expectedInside",
data: {
name: astUtils.getFunctionNameWithKind(funcInfo.node)
}
@@ -230,7 +238,7 @@ module.exports = {
if (!options.allowImplicit && !node.argument) {
context.report({
node,
- message: "{{name}} expected a return value.",
+ messageId: "expectedReturnValue",
data: {
name: lodash.upperFirst(astUtils.getFunctionNameWithKind(funcInfo.node))
}
diff --git a/tools/node_modules/eslint/lib/rules/array-element-newline.js b/tools/node_modules/eslint/lib/rules/array-element-newline.js
index 22352c7e33..359b8d436e 100644
--- a/tools/node_modules/eslint/lib/rules/array-element-newline.js
+++ b/tools/node_modules/eslint/lib/rules/array-element-newline.js
@@ -41,7 +41,12 @@ module.exports = {
}
]
}
- ]
+ ],
+
+ messages: {
+ unexpectedLineBreak: "There should be no linebreak here.",
+ missingLineBreak: "There should be a linebreak after this element."
+ }
},
create(context) {
@@ -54,16 +59,16 @@ module.exports = {
/**
* Normalizes a given option value.
*
- * @param {string|Object|undefined} option - An option value to parse.
+ * @param {string|Object|undefined} providedOption - An option value to parse.
* @returns {{multiline: boolean, minItems: number}} Normalized option object.
*/
- function normalizeOptionValue(option) {
+ function normalizeOptionValue(providedOption) {
let multiline = false;
let minItems;
- option = option || "always";
+ const option = providedOption || "always";
- if (option === "always" || option.minItems === 0) {
+ if (!option || option === "always" || option.minItems === 0) {
minItems = 0;
} else if (option === "never") {
minItems = Number.POSITIVE_INFINITY;
@@ -100,7 +105,7 @@ module.exports = {
start: tokenBefore.loc.end,
end: token.loc.start
},
- message: "There should be no linebreak here.",
+ messageId: "unexpectedLineBreak",
fix(fixer) {
if (astUtils.isCommentToken(tokenBefore)) {
return null;
@@ -149,7 +154,7 @@ module.exports = {
start: tokenBefore.loc.end,
end: token.loc.start
},
- message: "There should be a linebreak after this element.",
+ messageId: "missingLineBreak",
fix(fixer) {
return fixer.replaceTextRange([tokenBefore.range[1], token.range[0]], "\n");
}
diff --git a/tools/node_modules/eslint/lib/rules/arrow-body-style.js b/tools/node_modules/eslint/lib/rules/arrow-body-style.js
index afbf46fd54..1f0d1377b5 100644
--- a/tools/node_modules/eslint/lib/rules/arrow-body-style.js
+++ b/tools/node_modules/eslint/lib/rules/arrow-body-style.js
@@ -55,7 +55,15 @@ module.exports = {
]
},
- fixable: "code"
+ fixable: "code",
+
+ messages: {
+ unexpectedOtherBlock: "Unexpected block statement surrounding arrow body.",
+ unexpectedEmptyBlock: "Unexpected block statement surrounding arrow body; put a value of `undefined` immediately after the `=>`.",
+ unexpectedObjectBlock: "Unexpected block statement surrounding arrow body; parenthesize the returned value and move it immediately after the `=>`.",
+ unexpectedSingleBlock: "Unexpected block statement surrounding arrow body; move the returned value immediately after the `=>`.",
+ expectedBlock: "Expected block statement surrounding arrow body."
+ }
},
create(context) {
@@ -110,22 +118,22 @@ module.exports = {
}
if (never || asNeeded && blockBody[0].type === "ReturnStatement") {
- let message;
+ let messageId;
if (blockBody.length === 0) {
- message = "Unexpected block statement surrounding arrow body; put a value of `undefined` immediately after the `=>`.";
+ messageId = "unexpectedEmptyBlock";
} else if (blockBody.length > 1) {
- message = "Unexpected block statement surrounding arrow body.";
+ messageId = "unexpectedOtherBlock";
} else if (astUtils.isOpeningBraceToken(sourceCode.getFirstToken(blockBody[0], { skip: 1 }))) {
- message = "Unexpected block statement surrounding arrow body; parenthesize the returned value and move it immediately after the `=>`.";
+ messageId = "unexpectedObjectBlock";
} else {
- message = "Unexpected block statement surrounding arrow body; move the returned value immediately after the `=>`.";
+ messageId = "unexpectedSingleBlock";
}
context.report({
node,
loc: arrowBody.loc.start,
- message,
+ messageId,
fix(fixer) {
const fixes = [];
@@ -190,7 +198,7 @@ module.exports = {
context.report({
node,
loc: arrowBody.loc.start,
- message: "Expected block statement surrounding arrow body.",
+ messageId: "expectedBlock",
fix(fixer) {
const fixes = [];
const arrowToken = sourceCode.getTokenBefore(arrowBody, astUtils.isArrowToken);
diff --git a/tools/node_modules/eslint/lib/rules/arrow-parens.js b/tools/node_modules/eslint/lib/rules/arrow-parens.js
index 5a0fd61b34..8cabb7f90f 100644
--- a/tools/node_modules/eslint/lib/rules/arrow-parens.js
+++ b/tools/node_modules/eslint/lib/rules/arrow-parens.js
@@ -38,15 +38,19 @@ module.exports = {
},
additionalProperties: false
}
- ]
+ ],
+
+ messages: {
+ unexpectedParens: "Unexpected parentheses around single function argument.",
+ expectedParens: "Expected parentheses around arrow function argument.",
+
+ unexpectedParensInline: "Unexpected parentheses around single function argument having a body with no curly braces.",
+ expectedParensBlock: "Expected parentheses around arrow function argument having a body with curly braces."
+ }
},
create(context) {
- const message = "Expected parentheses around arrow function argument.";
- const asNeededMessage = "Unexpected parentheses around single function argument.";
const asNeeded = context.options[0] === "as-needed";
- const requireForBlockBodyMessage = "Unexpected parentheses around single function argument having a body with no curly braces";
- const requireForBlockBodyNoParensMessage = "Expected parentheses around arrow function argument having a body with curly braces.";
const requireForBlockBody = asNeeded && context.options[1] && context.options[1].requireForBlockBody === true;
const sourceCode = context.getSourceCode();
@@ -94,7 +98,7 @@ module.exports = {
if (astUtils.isOpeningParenToken(firstTokenOfParam)) {
context.report({
node,
- message: requireForBlockBodyMessage,
+ messageId: "unexpectedParensInline",
fix: fixParamsWithParenthesis
});
}
@@ -108,7 +112,7 @@ module.exports = {
if (!astUtils.isOpeningParenToken(firstTokenOfParam)) {
context.report({
node,
- message: requireForBlockBodyNoParensMessage,
+ messageId: "expectedParensBlock",
fix(fixer) {
return fixer.replaceText(firstTokenOfParam, `(${firstTokenOfParam.value})`);
}
@@ -127,7 +131,7 @@ module.exports = {
if (astUtils.isOpeningParenToken(firstTokenOfParam)) {
context.report({
node,
- message: asNeededMessage,
+ messageId: "unexpectedParens",
fix: fixParamsWithParenthesis
});
}
@@ -141,7 +145,7 @@ module.exports = {
if (after.value !== ")") {
context.report({
node,
- message,
+ messageId: "expectedParens",
fix(fixer) {
return fixer.replaceText(firstTokenOfParam, `(${firstTokenOfParam.value})`);
}
diff --git a/tools/node_modules/eslint/lib/rules/arrow-spacing.js b/tools/node_modules/eslint/lib/rules/arrow-spacing.js
index d2c5b9b77b..52f8fcab97 100644
--- a/tools/node_modules/eslint/lib/rules/arrow-spacing.js
+++ b/tools/node_modules/eslint/lib/rules/arrow-spacing.js
@@ -38,7 +38,15 @@ module.exports = {
},
additionalProperties: false
}
- ]
+ ],
+
+ messages: {
+ expectedBefore: "Missing space before =>.",
+ unexpectedBefore: "Unexpected space before =>.",
+
+ expectedAfter: "Missing space after =>.",
+ unexpectedAfter: "Unexpected space after =>."
+ }
},
create(context) {
@@ -96,7 +104,7 @@ module.exports = {
if (countSpace.before === 0) {
context.report({
node: tokens.before,
- message: "Missing space before =>.",
+ messageId: "expectedBefore",
fix(fixer) {
return fixer.insertTextBefore(tokens.arrow, " ");
}
@@ -108,7 +116,7 @@ module.exports = {
if (countSpace.before > 0) {
context.report({
node: tokens.before,
- message: "Unexpected space before =>.",
+ messageId: "unexpectedBefore",
fix(fixer) {
return fixer.removeRange([tokens.before.range[1], tokens.arrow.range[0]]);
}
@@ -122,7 +130,7 @@ module.exports = {
if (countSpace.after === 0) {
context.report({
node: tokens.after,
- message: "Missing space after =>.",
+ messageId: "expectedAfter",
fix(fixer) {
return fixer.insertTextAfter(tokens.arrow, " ");
}
@@ -134,7 +142,7 @@ module.exports = {
if (countSpace.after > 0) {
context.report({
node: tokens.after,
- message: "Unexpected space after =>.",
+ messageId: "unexpectedAfter",
fix(fixer) {
return fixer.removeRange([tokens.arrow.range[1], tokens.after.range[0]]);
}
diff --git a/tools/node_modules/eslint/lib/rules/block-scoped-var.js b/tools/node_modules/eslint/lib/rules/block-scoped-var.js
index 58cef1741a..1000fbc83c 100644
--- a/tools/node_modules/eslint/lib/rules/block-scoped-var.js
+++ b/tools/node_modules/eslint/lib/rules/block-scoped-var.js
@@ -17,7 +17,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/block-scoped-var"
},
- schema: []
+ schema: [],
+
+ messages: {
+ outOfScope: "'{{name}}' used outside of binding context."
+ }
},
create(context) {
@@ -48,7 +52,7 @@ module.exports = {
function report(reference) {
const identifier = reference.identifier;
- context.report({ node: identifier, message: "'{{name}}' used outside of binding context.", data: { name: identifier.name } });
+ context.report({ node: identifier, messageId: "outOfScope", data: { name: identifier.name } });
}
/**
diff --git a/tools/node_modules/eslint/lib/rules/block-spacing.js b/tools/node_modules/eslint/lib/rules/block-spacing.js
index 4fbf6d4c0b..536381362a 100644
--- a/tools/node_modules/eslint/lib/rules/block-spacing.js
+++ b/tools/node_modules/eslint/lib/rules/block-spacing.js
@@ -24,12 +24,17 @@ module.exports = {
schema: [
{ enum: ["always", "never"] }
- ]
+ ],
+
+ messages: {
+ missing: "Requires a space {{location}} '{{token}}'",
+ extra: "Unexpected space(s) {{location}} '{{token}}'"
+ }
},
create(context) {
const always = (context.options[0] !== "never"),
- message = always ? "Requires a space" : "Unexpected space(s)",
+ messageId = always ? "missing" : "extra",
sourceCode = context.getSourceCode();
/**
@@ -98,9 +103,10 @@ module.exports = {
context.report({
node,
loc: openBrace.loc.start,
- message: "{{message}} after '{'.",
+ messageId,
data: {
- message
+ location: "after",
+ token: openBrace.value
},
fix(fixer) {
if (always) {
@@ -115,9 +121,10 @@ module.exports = {
context.report({
node,
loc: closeBrace.loc.start,
- message: "{{message}} before '}'.",
+ messageId,
data: {
- message
+ location: "before",
+ token: closeBrace.value
},
fix(fixer) {
if (always) {
diff --git a/tools/node_modules/eslint/lib/rules/brace-style.js b/tools/node_modules/eslint/lib/rules/brace-style.js
index bc0ddbd78f..e2cbafe219 100644
--- a/tools/node_modules/eslint/lib/rules/brace-style.js
+++ b/tools/node_modules/eslint/lib/rules/brace-style.js
@@ -35,7 +35,16 @@ module.exports = {
}
],
- fixable: "whitespace"
+ fixable: "whitespace",
+
+ messages: {
+ nextLineOpen: "Opening curly brace does not appear on the same line as controlling statement.",
+ sameLineOpen: "Opening curly brace appears on the same line as controlling statement.",
+ blockSameLine: "Statement inside of curly braces should be on next line.",
+ nextLineClose: "Closing curly brace does not appear on the same line as the subsequent block.",
+ singleLineClose: "Closing curly brace should be on the same line as opening curly brace or on the line after the previous block.",
+ sameLineClose: "Closing curly brace appears on the same line as the subsequent block."
+ }
},
create(context) {
@@ -43,13 +52,6 @@ module.exports = {
params = context.options[1] || {},
sourceCode = context.getSourceCode();
- const OPEN_MESSAGE = "Opening curly brace does not appear on the same line as controlling statement.",
- OPEN_MESSAGE_ALLMAN = "Opening curly brace appears on the same line as controlling statement.",
- BODY_MESSAGE = "Statement inside of curly braces should be on next line.",
- CLOSE_MESSAGE = "Closing curly brace does not appear on the same line as the subsequent block.",
- CLOSE_MESSAGE_SINGLE = "Closing curly brace should be on the same line as opening curly brace or on the line after the previous block.",
- CLOSE_MESSAGE_STROUSTRUP_ALLMAN = "Closing curly brace appears on the same line as the subsequent block.";
-
//--------------------------------------------------------------------------
// Helpers
//--------------------------------------------------------------------------
@@ -86,7 +88,7 @@ module.exports = {
if (style !== "allman" && !astUtils.isTokenOnSameLine(tokenBeforeOpeningCurly, openingCurly)) {
context.report({
node: openingCurly,
- message: OPEN_MESSAGE,
+ messageId: "nextLineOpen",
fix: removeNewlineBetween(tokenBeforeOpeningCurly, openingCurly)
});
}
@@ -94,7 +96,7 @@ module.exports = {
if (style === "allman" && astUtils.isTokenOnSameLine(tokenBeforeOpeningCurly, openingCurly) && !singleLineException) {
context.report({
node: openingCurly,
- message: OPEN_MESSAGE_ALLMAN,
+ messageId: "sameLineOpen",
fix: fixer => fixer.insertTextBefore(openingCurly, "\n")
});
}
@@ -102,7 +104,7 @@ module.exports = {
if (astUtils.isTokenOnSameLine(openingCurly, tokenAfterOpeningCurly) && tokenAfterOpeningCurly !== closingCurly && !singleLineException) {
context.report({
node: openingCurly,
- message: BODY_MESSAGE,
+ messageId: "blockSameLine",
fix: fixer => fixer.insertTextAfter(openingCurly, "\n")
});
}
@@ -110,7 +112,7 @@ module.exports = {
if (tokenBeforeClosingCurly !== openingCurly && !singleLineException && astUtils.isTokenOnSameLine(tokenBeforeClosingCurly, closingCurly)) {
context.report({
node: closingCurly,
- message: CLOSE_MESSAGE_SINGLE,
+ messageId: "singleLineClose",
fix: fixer => fixer.insertTextBefore(closingCurly, "\n")
});
}
@@ -127,7 +129,7 @@ module.exports = {
if (style === "1tbs" && !astUtils.isTokenOnSameLine(curlyToken, keywordToken)) {
context.report({
node: curlyToken,
- message: CLOSE_MESSAGE,
+ messageId: "nextLineClose",
fix: removeNewlineBetween(curlyToken, keywordToken)
});
}
@@ -135,7 +137,7 @@ module.exports = {
if (style !== "1tbs" && astUtils.isTokenOnSameLine(curlyToken, keywordToken)) {
context.report({
node: curlyToken,
- message: CLOSE_MESSAGE_STROUSTRUP_ALLMAN,
+ messageId: "sameLineClose",
fix: fixer => fixer.insertTextAfter(curlyToken, "\n")
});
}
diff --git a/tools/node_modules/eslint/lib/rules/callback-return.js b/tools/node_modules/eslint/lib/rules/callback-return.js
index ed85c7181a..f55fed87db 100644
--- a/tools/node_modules/eslint/lib/rules/callback-return.js
+++ b/tools/node_modules/eslint/lib/rules/callback-return.js
@@ -20,7 +20,11 @@ module.exports = {
schema: [{
type: "array",
items: { type: "string" }
- }]
+ }],
+
+ messages: {
+ missingReturn: "Expected return with your callback function."
+ }
},
create(context) {
@@ -166,7 +170,7 @@ module.exports = {
// as long as you're the child of a function at this point you should be asked to return
if (findClosestParentOfType(node, ["FunctionDeclaration", "FunctionExpression", "ArrowFunctionExpression"])) {
- context.report({ node, message: "Expected return with your callback function." });
+ context.report({ node, messageId: "missingReturn" });
}
}
diff --git a/tools/node_modules/eslint/lib/rules/camelcase.js b/tools/node_modules/eslint/lib/rules/camelcase.js
index 86822f9752..84db54ff28 100644
--- a/tools/node_modules/eslint/lib/rules/camelcase.js
+++ b/tools/node_modules/eslint/lib/rules/camelcase.js
@@ -28,7 +28,11 @@ module.exports = {
},
additionalProperties: false
}
- ]
+ ],
+
+ messages: {
+ notCamelCase: "Identifier '{{name}}' is not in camel case."
+ }
},
create(context) {
@@ -62,7 +66,7 @@ module.exports = {
function report(node) {
if (reported.indexOf(node) < 0) {
reported.push(node);
- context.report({ node, message: "Identifier '{{name}}' is not in camel case.", data: { name: node.name } });
+ context.report({ node, messageId: "notCamelCase", data: { name: node.name } });
}
}
diff --git a/tools/node_modules/eslint/lib/rules/capitalized-comments.js b/tools/node_modules/eslint/lib/rules/capitalized-comments.js
index 19b5f6a717..c98a4464ac 100644
--- a/tools/node_modules/eslint/lib/rules/capitalized-comments.js
+++ b/tools/node_modules/eslint/lib/rules/capitalized-comments.js
@@ -15,9 +15,7 @@ const astUtils = require("../ast-utils");
// Helpers
//------------------------------------------------------------------------------
-const ALWAYS_MESSAGE = "Comments should not begin with a lowercase character",
- NEVER_MESSAGE = "Comments should not begin with an uppercase character",
- DEFAULT_IGNORE_PATTERN = astUtils.COMMENTS_IGNORE_PATTERN,
+const DEFAULT_IGNORE_PATTERN = astUtils.COMMENTS_IGNORE_PATTERN,
WHITESPACE = /\s/g,
MAYBE_URL = /^\s*[^:/?#\s]+:\/\/[^?#]/, // TODO: Combine w/ max-len pattern?
DEFAULTS = {
@@ -132,7 +130,12 @@ module.exports = {
}
]
}
- ]
+ ],
+
+ messages: {
+ unexpectedLowercaseComment: "Comments should not begin with a lowercase character",
+ unexpectedUppercaseComment: "Comments should not begin with an uppercase character"
+ }
},
create(context) {
@@ -267,14 +270,14 @@ module.exports = {
commentValid = isCommentValid(comment, options);
if (!commentValid) {
- const message = capitalize === "always"
- ? ALWAYS_MESSAGE
- : NEVER_MESSAGE;
+ const messageId = capitalize === "always"
+ ? "unexpectedLowercaseComment"
+ : "unexpectedUppercaseComment";
context.report({
node: null, // Intentionally using loc instead
loc: comment.loc,
- message,
+ messageId,
fix(fixer) {
const match = comment.value.match(LETTER_PATTERN);
diff --git a/tools/node_modules/eslint/lib/rules/class-methods-use-this.js b/tools/node_modules/eslint/lib/rules/class-methods-use-this.js
index 774086780a..b7d94135bb 100644
--- a/tools/node_modules/eslint/lib/rules/class-methods-use-this.js
+++ b/tools/node_modules/eslint/lib/rules/class-methods-use-this.js
@@ -28,7 +28,11 @@ module.exports = {
}
},
additionalProperties: false
- }]
+ }],
+
+ messages: {
+ missingThis: "Expected 'this' to be used by class method '{{name}}'."
+ }
},
create(context) {
const config = context.options[0] ? Object.assign({}, context.options[0]) : {};
@@ -80,9 +84,9 @@ module.exports = {
if (isIncludedInstanceMethod(node.parent) && !methodUsesThis) {
context.report({
node,
- message: "Expected 'this' to be used by class method '{{classMethod}}'.",
+ messageId: "missingThis",
data: {
- classMethod: node.parent.key.name
+ name: node.parent.key.name
}
});
}
diff --git a/tools/node_modules/eslint/lib/rules/comma-dangle.js b/tools/node_modules/eslint/lib/rules/comma-dangle.js
index 180979d403..50de7b59b2 100644
--- a/tools/node_modules/eslint/lib/rules/comma-dangle.js
+++ b/tools/node_modules/eslint/lib/rules/comma-dangle.js
@@ -124,14 +124,17 @@ module.exports = {
]
}
]
+ },
+
+ messages: {
+ unexpected: "Unexpected trailing comma.",
+ missing: "Missing trailing comma."
}
},
create(context) {
const options = normalizeOptions(context.options[0]);
const sourceCode = context.getSourceCode();
- const UNEXPECTED_MESSAGE = "Unexpected trailing comma.";
- const MISSING_MESSAGE = "Missing trailing comma.";
/**
* Gets the last item of the given node.
@@ -230,7 +233,7 @@ module.exports = {
context.report({
node: lastItem,
loc: trailingToken.loc.start,
- message: UNEXPECTED_MESSAGE,
+ messageId: "unexpected",
fix(fixer) {
return fixer.remove(trailingToken);
}
@@ -267,7 +270,7 @@ module.exports = {
context.report({
node: lastItem,
loc: trailingToken.loc.end,
- message: MISSING_MESSAGE,
+ messageId: "missing",
fix(fixer) {
return fixer.insertTextAfter(trailingToken, ",");
}
diff --git a/tools/node_modules/eslint/lib/rules/comma-spacing.js b/tools/node_modules/eslint/lib/rules/comma-spacing.js
index dd3de7f354..2a48e54d51 100644
--- a/tools/node_modules/eslint/lib/rules/comma-spacing.js
+++ b/tools/node_modules/eslint/lib/rules/comma-spacing.js
@@ -34,7 +34,12 @@ module.exports = {
},
additionalProperties: false
}
- ]
+ ],
+
+ messages: {
+ missing: "A space is required {{loc}} ','.",
+ unexpected: "There should be no space {{loc}} ','."
+ }
},
create(context) {
@@ -57,17 +62,17 @@ module.exports = {
/**
* Reports a spacing error with an appropriate message.
* @param {ASTNode} node The binary expression node to report.
- * @param {string} dir Is the error "before" or "after" the comma?
+ * @param {string} loc Is the error "before" or "after" the comma?
* @param {ASTNode} otherNode The node at the left or right of `node`
* @returns {void}
* @private
*/
- function report(node, dir, otherNode) {
+ function report(node, loc, otherNode) {
context.report({
node,
fix(fixer) {
- if (options[dir]) {
- if (dir === "before") {
+ if (options[loc]) {
+ if (loc === "before") {
return fixer.insertTextBefore(node, " ");
}
return fixer.insertTextAfter(node, " ");
@@ -76,7 +81,7 @@ module.exports = {
let start, end;
const newText = "";
- if (dir === "before") {
+ if (loc === "before") {
start = otherNode.range[1];
end = node.range[0];
} else {
@@ -87,11 +92,9 @@ module.exports = {
return fixer.replaceTextRange([start, end], newText);
},
- message: options[dir]
- ? "A space is required {{dir}} ','."
- : "There should be no space {{dir}} ','.",
+ messageId: options[loc] ? "missing" : "unexpected",
data: {
- dir
+ loc
}
});
}
diff --git a/tools/node_modules/eslint/lib/rules/comma-style.js b/tools/node_modules/eslint/lib/rules/comma-style.js
index 8b96e5e25a..5ba2dbb28b 100644
--- a/tools/node_modules/eslint/lib/rules/comma-style.js
+++ b/tools/node_modules/eslint/lib/rules/comma-style.js
@@ -36,7 +36,12 @@ module.exports = {
},
additionalProperties: false
}
- ]
+ ],
+ messages: {
+ unexpectedLineBeforeAndAfterComma: "Bad line breaking before and after ','.",
+ expectedCommaFirst: "',' should be placed first.",
+ expectedCommaLast: "',' should be placed last."
+ }
},
create(context) {
@@ -49,7 +54,8 @@ module.exports = {
FunctionDeclaration: true,
FunctionExpression: true,
ImportDeclaration: true,
- ObjectPattern: true
+ ObjectPattern: true,
+ NewExpression: true
};
if (context.options.length === 2 && context.options[1].hasOwnProperty("exceptions")) {
@@ -134,7 +140,7 @@ module.exports = {
line: commaToken.loc.end.line,
column: commaToken.loc.start.column
},
- message: "Bad line breaking before and after ','.",
+ messageId: "unexpectedLineBeforeAndAfterComma",
fix: getFixerFunction("between", previousItemToken, commaToken, currentItemToken)
});
@@ -142,7 +148,7 @@ module.exports = {
context.report({
node: reportItem,
- message: "',' should be placed first.",
+ messageId: "expectedCommaFirst",
fix: getFixerFunction(style, previousItemToken, commaToken, currentItemToken)
});
@@ -154,7 +160,7 @@ module.exports = {
line: commaToken.loc.end.line,
column: commaToken.loc.end.column
},
- message: "',' should be placed last.",
+ messageId: "expectedCommaLast",
fix: getFixerFunction(style, previousItemToken, commaToken, currentItemToken)
});
}
@@ -294,6 +300,11 @@ module.exports = {
validateComma(node, "specifiers");
};
}
+ if (!exceptions.NewExpression) {
+ nodes.NewExpression = function(node) {
+ validateComma(node, "arguments");
+ };
+ }
return nodes;
}
diff --git a/tools/node_modules/eslint/lib/rules/complexity.js b/tools/node_modules/eslint/lib/rules/complexity.js
index 1838d4bf8e..0b86441365 100644
--- a/tools/node_modules/eslint/lib/rules/complexity.js
+++ b/tools/node_modules/eslint/lib/rules/complexity.js
@@ -50,7 +50,11 @@ module.exports = {
}
]
}
- ]
+ ],
+
+ messages: {
+ complex: "{{name}} has a complexity of {{complexity}}."
+ }
},
create(context) {
@@ -96,7 +100,7 @@ module.exports = {
if (complexity > THRESHOLD) {
context.report({
node,
- message: "{{name}} has a complexity of {{complexity}}.",
+ messageId: "complex",
data: { name, complexity }
});
}
diff --git a/tools/node_modules/eslint/lib/rules/computed-property-spacing.js b/tools/node_modules/eslint/lib/rules/computed-property-spacing.js
index 57408afb45..51334a2ab4 100644
--- a/tools/node_modules/eslint/lib/rules/computed-property-spacing.js
+++ b/tools/node_modules/eslint/lib/rules/computed-property-spacing.js
@@ -25,7 +25,15 @@ module.exports = {
{
enum: ["always", "never"]
}
- ]
+ ],
+
+ messages: {
+ unexpectedSpaceBefore: "There should be no space before '{{tokenValue}}'.",
+ unexpectedSpaceAfter: "There should be no space after '{{tokenValue}}'.",
+
+ missingSpaceBefore: "A space is required before '{{tokenValue}}'.",
+ missingSpaceAfter: "A space is required after '{{tokenValue}}'."
+ }
},
create(context) {
@@ -47,7 +55,7 @@ module.exports = {
context.report({
node,
loc: token.loc.start,
- message: "There should be no space after '{{tokenValue}}'.",
+ messageId: "unexpectedSpaceAfter",
data: {
tokenValue: token.value
},
@@ -68,7 +76,7 @@ module.exports = {
context.report({
node,
loc: token.loc.start,
- message: "There should be no space before '{{tokenValue}}'.",
+ messageId: "unexpectedSpaceBefore",
data: {
tokenValue: token.value
},
@@ -88,7 +96,7 @@ module.exports = {
context.report({
node,
loc: token.loc.start,
- message: "A space is required after '{{tokenValue}}'.",
+ messageId: "missingSpaceAfter",
data: {
tokenValue: token.value
},
@@ -108,7 +116,7 @@ module.exports = {
context.report({
node,
loc: token.loc.start,
- message: "A space is required before '{{tokenValue}}'.",
+ messageId: "missingSpaceBefore",
data: {
tokenValue: token.value
},
diff --git a/tools/node_modules/eslint/lib/rules/consistent-return.js b/tools/node_modules/eslint/lib/rules/consistent-return.js
index a436dd1fc0..c86b1717ef 100644
--- a/tools/node_modules/eslint/lib/rules/consistent-return.js
+++ b/tools/node_modules/eslint/lib/rules/consistent-return.js
@@ -68,7 +68,13 @@ module.exports = {
}
},
additionalProperties: false
- }]
+ }],
+
+ messages: {
+ missingReturn: "Expected to return a value at the end of {{name}}.",
+ missingReturnValue: "{{name}} expected a return value.",
+ unexpectedReturnValue: "{{name}} expected no return value."
+ }
},
create(context) {
@@ -129,7 +135,7 @@ module.exports = {
context.report({
node,
loc,
- message: "Expected to return a value at the end of {{name}}.",
+ messageId: "missingReturn",
data: { name }
});
}
@@ -143,7 +149,7 @@ module.exports = {
codePath,
hasReturn: false,
hasReturnValue: false,
- message: "",
+ messageId: "",
node
};
},
@@ -163,17 +169,16 @@ module.exports = {
if (!funcInfo.hasReturn) {
funcInfo.hasReturn = true;
funcInfo.hasReturnValue = hasReturnValue;
- funcInfo.message = "{{name}} expected {{which}} return value.";
+ funcInfo.messageId = hasReturnValue ? "missingReturnValue" : "unexpectedReturnValue";
funcInfo.data = {
name: funcInfo.node.type === "Program"
? "Program"
- : lodash.upperFirst(astUtils.getFunctionNameWithKind(funcInfo.node)),
- which: hasReturnValue ? "a" : "no"
+ : lodash.upperFirst(astUtils.getFunctionNameWithKind(funcInfo.node))
};
} else if (funcInfo.hasReturnValue !== hasReturnValue) {
context.report({
node,
- message: funcInfo.message,
+ messageId: funcInfo.messageId,
data: funcInfo.data
});
}
diff --git a/tools/node_modules/eslint/lib/rules/consistent-this.js b/tools/node_modules/eslint/lib/rules/consistent-this.js
index 60690007f2..5cc3a647da 100644
--- a/tools/node_modules/eslint/lib/rules/consistent-this.js
+++ b/tools/node_modules/eslint/lib/rules/consistent-this.js
@@ -24,6 +24,11 @@ module.exports = {
minLength: 1
},
uniqueItems: true
+ },
+
+ messages: {
+ aliasNotAssignedToThis: "Designated alias '{{name}}' is not assigned to 'this'.",
+ unexpectedAlias: "Unexpected alias '{{name}}' for 'this'."
}
},
@@ -40,11 +45,11 @@ module.exports = {
* Reports that a variable declarator or assignment expression is assigning
* a non-'this' value to the specified alias.
* @param {ASTNode} node - The assigning node.
- * @param {string} alias - the name of the alias that was incorrectly used.
+ * @param {string} name - the name of the alias that was incorrectly used.
* @returns {void}
*/
- function reportBadAssignment(node, alias) {
- context.report({ node, message: "Designated alias '{{alias}}' is not assigned to 'this'.", data: { alias } });
+ function reportBadAssignment(node, name) {
+ context.report({ node, messageId: "aliasNotAssignedToThis", data: { name } });
}
/**
@@ -63,7 +68,7 @@ module.exports = {
reportBadAssignment(node, name);
}
} else if (isThis) {
- context.report({ node, message: "Unexpected alias '{{name}}' for 'this'.", data: { name } });
+ context.report({ node, messageId: "unexpectedAlias", data: { name } });
}
}
diff --git a/tools/node_modules/eslint/lib/rules/constructor-super.js b/tools/node_modules/eslint/lib/rules/constructor-super.js
index 30637472f1..3cbc2f59f8 100644
--- a/tools/node_modules/eslint/lib/rules/constructor-super.js
+++ b/tools/node_modules/eslint/lib/rules/constructor-super.js
@@ -99,7 +99,16 @@ module.exports = {
url: "https://eslint.org/docs/rules/constructor-super"
},
- schema: []
+ schema: [],
+
+ messages: {
+ missingSome: "Lacked a call of 'super()' in some code paths.",
+ missingAll: "Expected to call 'super()'.",
+
+ duplicate: "Unexpected duplicate 'super()'.",
+ badSuper: "Unexpected 'super()' because 'super' is not a constructor.",
+ unexpected: "Unexpected 'super()'."
+ }
},
create(context) {
@@ -210,9 +219,9 @@ module.exports = {
if (!calledInEveryPaths) {
context.report({
- message: calledInSomePaths
- ? "Lacked a call of 'super()' in some code paths."
- : "Expected to call 'super()'.",
+ messageId: calledInSomePaths
+ ? "missingSome"
+ : "missingAll",
node: node.parent
});
}
@@ -281,7 +290,7 @@ module.exports = {
const node = nodes[i];
context.report({
- message: "Unexpected duplicate 'super()'.",
+ messageId: "duplicate",
node
});
}
@@ -325,12 +334,12 @@ module.exports = {
if (info) {
if (duplicate) {
context.report({
- message: "Unexpected duplicate 'super()'.",
+ messageId: "duplicate",
node
});
} else if (!funcInfo.superIsConstructor) {
context.report({
- message: "Unexpected 'super()' because 'super' is not a constructor.",
+ messageId: "badSuper",
node
});
} else {
@@ -339,7 +348,7 @@ module.exports = {
}
} else if (funcInfo.codePath.currentSegments.some(isReachable)) {
context.report({
- message: "Unexpected 'super()'.",
+ messageId: "unexpected",
node
});
}
diff --git a/tools/node_modules/eslint/lib/rules/curly.js b/tools/node_modules/eslint/lib/rules/curly.js
index 7fdf57eda1..07d991b31a 100644
--- a/tools/node_modules/eslint/lib/rules/curly.js
+++ b/tools/node_modules/eslint/lib/rules/curly.js
@@ -51,7 +51,14 @@ module.exports = {
]
},
- fixable: "code"
+ fixable: "code",
+
+ messages: {
+ missingCurlyAfter: "Expected { after '{{name}}'.",
+ missingCurlyAfterCondition: "Expected { after '{{name}}' condition.",
+ unexpectedCurlyAfter: "Unnecessary { after '{{name}}'.",
+ unexpectedCurlyAfterCondition: "Unnecessary { after '{{name}}' condition."
+ }
},
create(context) {
@@ -130,12 +137,14 @@ module.exports = {
return true;
}
- node = node.consequent.body[0];
- while (node) {
- if (node.type === "IfStatement" && !node.alternate) {
+ for (
+ let currentNode = node.consequent.body[0];
+ currentNode;
+ currentNode = astUtils.getTrailingStatement(currentNode)
+ ) {
+ if (currentNode.type === "IfStatement" && !currentNode.alternate) {
return true;
}
- node = astUtils.getTrailingStatement(node);
}
}
@@ -143,28 +152,6 @@ module.exports = {
}
/**
- * Reports "Expected { after ..." error
- * @param {ASTNode} node The node to report.
- * @param {ASTNode} bodyNode The body node that is incorrectly missing curly brackets
- * @param {string} name The name to report.
- * @param {string} suffix Additional string to add to the end of a report.
- * @returns {void}
- * @private
- */
- function reportExpectedBraceError(node, bodyNode, name, suffix) {
- context.report({
- node,
- loc: (name !== "else" ? node : getElseKeyword(node)).loc.start,
- message: "Expected { after '{{name}}'{{suffix}}.",
- data: {
- name,
- suffix: (suffix ? ` ${suffix}` : "")
- },
- fix: fixer => fixer.replaceText(bodyNode, `{${sourceCode.getText(bodyNode)}}`)
- });
- }
-
- /**
* Determines if a semicolon needs to be inserted after removing a set of curly brackets, in order to avoid a SyntaxError.
* @param {Token} closingBracket The } token
* @returns {boolean} `true` if a semicolon needs to be inserted after the last statement in the block.
@@ -219,61 +206,11 @@ module.exports = {
}
/**
- * Reports "Unnecessary { after ..." error
- * @param {ASTNode} node The node to report.
- * @param {ASTNode} bodyNode The block statement that is incorrectly surrounded by parens
- * @param {string} name The name to report.
- * @param {string} suffix Additional string to add to the end of a report.
- * @returns {void}
- * @private
- */
- function reportUnnecessaryBraceError(node, bodyNode, name, suffix) {
- context.report({
- node,
- loc: (name !== "else" ? node : getElseKeyword(node)).loc.start,
- message: "Unnecessary { after '{{name}}'{{suffix}}.",
- data: {
- name,
- suffix: (suffix ? ` ${suffix}` : "")
- },
- fix(fixer) {
-
- /*
- * `do while` expressions sometimes need a space to be inserted after `do`.
- * e.g. `do{foo()} while (bar)` should be corrected to `do foo() while (bar)`
- */
- const needsPrecedingSpace = node.type === "DoWhileStatement" &&
- sourceCode.getTokenBefore(bodyNode).range[1] === bodyNode.range[0] &&
- !astUtils.canTokensBeAdjacent("do", sourceCode.getFirstToken(bodyNode, { skip: 1 }));
-
- const openingBracket = sourceCode.getFirstToken(bodyNode);
- const closingBracket = sourceCode.getLastToken(bodyNode);
- const lastTokenInBlock = sourceCode.getTokenBefore(closingBracket);
-
- if (needsSemicolon(closingBracket)) {
-
- /*
- * If removing braces would cause a SyntaxError due to multiple statements on the same line (or
- * change the semantics of the code due to ASI), don't perform a fix.
- */
- return null;
- }
-
- const resultingBodyText = sourceCode.getText().slice(openingBracket.range[1], lastTokenInBlock.range[0]) +
- sourceCode.getText(lastTokenInBlock) +
- sourceCode.getText().slice(lastTokenInBlock.range[1], closingBracket.range[0]);
-
- return fixer.replaceText(bodyNode, (needsPrecedingSpace ? " " : "") + resultingBodyText);
- }
- });
- }
-
- /**
* Prepares to check the body of a node to see if it's a block statement.
* @param {ASTNode} node The node to report if there's a problem.
* @param {ASTNode} body The body node to check for blocks.
* @param {string} name The name to report if there's a problem.
- * @param {string} suffix Additional string to add to the end of a report.
+ * @param {{ condition: boolean }} opts Options to pass to the report functions
* @returns {Object} a prepared check object, with "actual", "expected", "check" properties.
* "actual" will be `true` or `false` whether the body is already a block statement.
* "expected" will be `true` or `false` if the body should be a block statement or not, or
@@ -282,7 +219,7 @@ module.exports = {
* "check" will be a function reporting appropriate problems depending on the other
* properties.
*/
- function prepareCheck(node, body, name, suffix) {
+ function prepareCheck(node, body, name, opts) {
const hasBlock = (body.type === "BlockStatement");
let expected = null;
@@ -314,9 +251,53 @@ module.exports = {
check() {
if (this.expected !== null && this.expected !== this.actual) {
if (this.expected) {
- reportExpectedBraceError(node, body, name, suffix);
+ context.report({
+ node,
+ loc: (name !== "else" ? node : getElseKeyword(node)).loc.start,
+ messageId: opts && opts.condition ? "missingCurlyAfterCondition" : "missingCurlyAfter",
+ data: {
+ name
+ },
+ fix: fixer => fixer.replaceText(body, `{${sourceCode.getText(body)}}`)
+ });
} else {
- reportUnnecessaryBraceError(node, body, name, suffix);
+ context.report({
+ node,
+ loc: (name !== "else" ? node : getElseKeyword(node)).loc.start,
+ messageId: opts && opts.condition ? "unexpectedCurlyAfterCondition" : "unexpectedCurlyAfter",
+ data: {
+ name
+ },
+ fix(fixer) {
+
+ /*
+ * `do while` expressions sometimes need a space to be inserted after `do`.
+ * e.g. `do{foo()} while (bar)` should be corrected to `do foo() while (bar)`
+ */
+ const needsPrecedingSpace = node.type === "DoWhileStatement" &&
+ sourceCode.getTokenBefore(body).range[1] === body.range[0] &&
+ !astUtils.canTokensBeAdjacent("do", sourceCode.getFirstToken(body, { skip: 1 }));
+
+ const openingBracket = sourceCode.getFirstToken(body);
+ const closingBracket = sourceCode.getLastToken(body);
+ const lastTokenInBlock = sourceCode.getTokenBefore(closingBracket);
+
+ if (needsSemicolon(closingBracket)) {
+
+ /*
+ * If removing braces would cause a SyntaxError due to multiple statements on the same line (or
+ * change the semantics of the code due to ASI), don't perform a fix.
+ */
+ return null;
+ }
+
+ const resultingBodyText = sourceCode.getText().slice(openingBracket.range[1], lastTokenInBlock.range[0]) +
+ sourceCode.getText(lastTokenInBlock) +
+ sourceCode.getText().slice(lastTokenInBlock.range[1], closingBracket.range[0]);
+
+ return fixer.replaceText(body, (needsPrecedingSpace ? " " : "") + resultingBodyText);
+ }
+ });
}
}
}
@@ -332,14 +313,13 @@ module.exports = {
function prepareIfChecks(node) {
const preparedChecks = [];
- do {
- preparedChecks.push(prepareCheck(node, node.consequent, "if", "condition"));
- if (node.alternate && node.alternate.type !== "IfStatement") {
- preparedChecks.push(prepareCheck(node, node.alternate, "else"));
+ for (let currentNode = node; currentNode; currentNode = currentNode.alternate) {
+ preparedChecks.push(prepareCheck(currentNode, currentNode.consequent, "if", { condition: true }));
+ if (currentNode.alternate && currentNode.alternate.type !== "IfStatement") {
+ preparedChecks.push(prepareCheck(currentNode, currentNode.alternate, "else"));
break;
}
- node = node.alternate;
- } while (node);
+ }
if (consistent) {
@@ -377,7 +357,7 @@ module.exports = {
},
WhileStatement(node) {
- prepareCheck(node, node.body, "while", "condition").check();
+ prepareCheck(node, node.body, "while", { condition: true }).check();
},
DoWhileStatement(node) {
@@ -385,7 +365,7 @@ module.exports = {
},
ForStatement(node) {
- prepareCheck(node, node.body, "for", "condition").check();
+ prepareCheck(node, node.body, "for", { condition: true }).check();
},
ForInStatement(node) {
diff --git a/tools/node_modules/eslint/lib/rules/default-case.js b/tools/node_modules/eslint/lib/rules/default-case.js
index a66300a99b..cf123198f4 100644
--- a/tools/node_modules/eslint/lib/rules/default-case.js
+++ b/tools/node_modules/eslint/lib/rules/default-case.js
@@ -27,7 +27,11 @@ module.exports = {
}
},
additionalProperties: false
- }]
+ }],
+
+ messages: {
+ missingDefaultCase: "Expected a default case."
+ }
},
create(context) {
@@ -82,7 +86,7 @@ module.exports = {
}
if (!comment || !commentPattern.test(comment.value.trim())) {
- context.report({ node, message: "Expected a default case." });
+ context.report({ node, messageId: "missingDefaultCase" });
}
}
}
diff --git a/tools/node_modules/eslint/lib/rules/dot-location.js b/tools/node_modules/eslint/lib/rules/dot-location.js
index c02476e035..7ff8ca65ae 100644
--- a/tools/node_modules/eslint/lib/rules/dot-location.js
+++ b/tools/node_modules/eslint/lib/rules/dot-location.js
@@ -26,7 +26,12 @@ module.exports = {
}
],
- fixable: "code"
+ fixable: "code",
+
+ messages: {
+ expectedDotAfterObject: "Expected dot to be on same line as object.",
+ expectedDotBeforeProperty: "Expected dot to be on same line as property."
+ }
},
create(context) {
@@ -58,7 +63,7 @@ module.exports = {
context.report({
node,
loc: dot.loc.start,
- message: "Expected dot to be on same line as object.",
+ messageId: "expectedDotAfterObject",
fix: fixer => fixer.replaceTextRange([obj.range[1], prop.range[0]], `${neededTextAfterObj}.${textBeforeDot}${textAfterDot}`)
});
}
@@ -66,7 +71,7 @@ module.exports = {
context.report({
node,
loc: dot.loc.start,
- message: "Expected dot to be on same line as property.",
+ messageId: "expectedDotBeforeProperty",
fix: fixer => fixer.replaceTextRange([obj.range[1], prop.range[0]], `${textBeforeDot}${textAfterDot}.`)
});
}
diff --git a/tools/node_modules/eslint/lib/rules/dot-notation.js b/tools/node_modules/eslint/lib/rules/dot-notation.js
index 10c73b41f0..c381661d41 100644
--- a/tools/node_modules/eslint/lib/rules/dot-notation.js
+++ b/tools/node_modules/eslint/lib/rules/dot-notation.js
@@ -41,7 +41,12 @@ module.exports = {
}
],
- fixable: "code"
+ fixable: "code",
+
+ messages: {
+ useDot: "[{{key}}] is better written in dot notation.",
+ useBrackets: ".{{key}} is a syntax error."
+ }
},
create(context) {
@@ -71,9 +76,9 @@ module.exports = {
context.report({
node: node.property,
- message: "[{{propertyValue}}] is better written in dot notation.",
+ messageId: "useDot",
data: {
- propertyValue: formattedValue
+ key: formattedValue
},
fix(fixer) {
const leftBracket = sourceCode.getTokenAfter(node.object, astUtils.isOpeningBracketToken);
@@ -124,9 +129,9 @@ module.exports = {
) {
context.report({
node: node.property,
- message: ".{{propertyName}} is a syntax error.",
+ messageId: "useBrackets",
data: {
- propertyName: node.property.name
+ key: node.property.name
},
fix(fixer) {
const dot = sourceCode.getTokenBefore(node.property);
diff --git a/tools/node_modules/eslint/lib/rules/eol-last.js b/tools/node_modules/eslint/lib/rules/eol-last.js
index f96352676c..3ecf422739 100644
--- a/tools/node_modules/eslint/lib/rules/eol-last.js
+++ b/tools/node_modules/eslint/lib/rules/eol-last.js
@@ -27,7 +27,11 @@ module.exports = {
{
enum: ["always", "never", "unix", "windows"]
}
- ]
+ ],
+ messages: {
+ missing: "Newline required at end of file but not found.",
+ unexpected: "Newline not allowed at end of file."
+ }
},
create(context) {
@@ -75,7 +79,7 @@ module.exports = {
context.report({
node,
loc: location,
- message: "Newline required at end of file but not found.",
+ messageId: "missing",
fix(fixer) {
return fixer.insertTextAfterRange([0, src.length], appendCRLF ? CRLF : LF);
}
@@ -86,7 +90,7 @@ module.exports = {
context.report({
node,
loc: location,
- message: "Newline not allowed at end of file.",
+ messageId: "unexpected",
fix(fixer) {
const finalEOLs = /(?:\r?\n)+$/,
match = finalEOLs.exec(sourceCode.text),
diff --git a/tools/node_modules/eslint/lib/rules/eqeqeq.js b/tools/node_modules/eslint/lib/rules/eqeqeq.js
index fc65450af4..ec9d0a7821 100644
--- a/tools/node_modules/eslint/lib/rules/eqeqeq.js
+++ b/tools/node_modules/eslint/lib/rules/eqeqeq.js
@@ -56,7 +56,11 @@ module.exports = {
]
},
- fixable: "code"
+ fixable: "code",
+
+ messages: {
+ unexpected: "Expected '{{expectedOperator}}' and instead saw '{{actualOperator}}'."
+ }
},
create(context) {
@@ -134,7 +138,7 @@ module.exports = {
context.report({
node,
loc: getOperatorLocation(node),
- message: "Expected '{{expectedOperator}}' and instead saw '{{actualOperator}}'.",
+ messageId: "unexpected",
data: { expectedOperator, actualOperator: node.operator },
fix(fixer) {
diff --git a/tools/node_modules/eslint/lib/rules/generator-star-spacing.js b/tools/node_modules/eslint/lib/rules/generator-star-spacing.js
index 282b37510b..68f2863626 100644
--- a/tools/node_modules/eslint/lib/rules/generator-star-spacing.js
+++ b/tools/node_modules/eslint/lib/rules/generator-star-spacing.js
@@ -85,7 +85,6 @@ module.exports = {
}
const modes = (function(option) {
- option = option || {};
const defaults = optionToDefinition(option, optionDefinitions.before);
return {
@@ -93,7 +92,7 @@ module.exports = {
anonymous: optionToDefinition(option.anonymous, defaults),
method: optionToDefinition(option.method, defaults)
};
- }(context.options[0]));
+ }(context.options[0] || {}));
const sourceCode = context.getSourceCode();
diff --git a/tools/node_modules/eslint/lib/rules/guard-for-in.js b/tools/node_modules/eslint/lib/rules/guard-for-in.js
index 88a9106b3f..0f85e4984a 100644
--- a/tools/node_modules/eslint/lib/rules/guard-for-in.js
+++ b/tools/node_modules/eslint/lib/rules/guard-for-in.js
@@ -26,16 +26,44 @@ module.exports = {
return {
ForInStatement(node) {
+ const body = node.body;
- /*
- * If the for-in statement has {}, then the real body is the body
- * of the BlockStatement. Otherwise, just use body as provided.
- */
- const body = node.body.type === "BlockStatement" ? node.body.body[0] : node.body;
+ // empty statement
+ if (body.type === "EmptyStatement") {
+ return;
+ }
+
+ // if statement
+ if (body.type === "IfStatement") {
+ return;
+ }
+
+ // empty block
+ if (body.type === "BlockStatement" && body.body.length === 0) {
+ return;
+ }
- if (body && body.type !== "IfStatement") {
- context.report({ node, message: "The body of a for-in should be wrapped in an if statement to filter unwanted properties from the prototype." });
+ // block with just if statement
+ if (body.type === "BlockStatement" && body.body.length === 1 && body.body[0].type === "IfStatement") {
+ return;
}
+
+ // block that starts with if statement
+ if (body.type === "BlockStatement" && body.body.length >= 1 && body.body[0].type === "IfStatement") {
+ const i = body.body[0];
+
+ // ... whose consequent is a continue
+ if (i.consequent.type === "ContinueStatement") {
+ return;
+ }
+
+ // ... whose consequent is a block that contains only a continue
+ if (i.consequent.type === "BlockStatement" && i.consequent.body.length === 1 && i.consequent.body[0].type === "ContinueStatement") {
+ return;
+ }
+ }
+
+ context.report({ node, message: "The body of a for-in should be wrapped in an if statement to filter unwanted properties from the prototype." });
}
};
diff --git a/tools/node_modules/eslint/lib/rules/indent-legacy.js b/tools/node_modules/eslint/lib/rules/indent-legacy.js
index 701cf01632..dc6d1689e4 100644
--- a/tools/node_modules/eslint/lib/rules/indent-legacy.js
+++ b/tools/node_modules/eslint/lib/rules/indent-legacy.js
@@ -505,12 +505,9 @@ module.exports = {
*/
function getParentNodeByType(node, type, stopAtList) {
let parent = node.parent;
+ const stopAtSet = new Set(stopAtList || ["Program"]);
- if (!stopAtList) {
- stopAtList = ["Program"];
- }
-
- while (parent.type !== type && stopAtList.indexOf(parent.type) === -1 && parent.type !== "Program") {
+ while (parent.type !== type && !stopAtSet.has(parent.type) && parent.type !== "Program") {
parent = parent.parent;
}
@@ -941,19 +938,19 @@ module.exports = {
/**
* Returns the expected indentation for the case statement
* @param {ASTNode} node node to examine
- * @param {int} [switchIndent] indent for switch statement
+ * @param {int} [providedSwitchIndent] indent for switch statement
* @returns {int} indent size
*/
- function expectedCaseIndent(node, switchIndent) {
+ function expectedCaseIndent(node, providedSwitchIndent) {
const switchNode = (node.type === "SwitchStatement") ? node : node.parent;
+ const switchIndent = typeof providedSwitchIndent === "undefined"
+ ? getNodeIndent(switchNode).goodChar
+ : providedSwitchIndent;
let caseIndent;
if (caseIndentStore[switchNode.loc.start.line]) {
return caseIndentStore[switchNode.loc.start.line];
}
- if (typeof switchIndent === "undefined") {
- switchIndent = getNodeIndent(switchNode).goodChar;
- }
if (switchNode.cases.length > 0 && options.SwitchCase === 0) {
caseIndent = switchIndent;
diff --git a/tools/node_modules/eslint/lib/rules/indent.js b/tools/node_modules/eslint/lib/rules/indent.js
index 2159880f88..a08b4d7e5f 100644
--- a/tools/node_modules/eslint/lib/rules/indent.js
+++ b/tools/node_modules/eslint/lib/rules/indent.js
@@ -442,6 +442,7 @@ class OffsetStorage {
const offset = (
offsetInfo.from &&
offsetInfo.from.loc.start.line === token.loc.start.line &&
+ !/^\s*?\n/.test(token.value) &&
!offsetInfo.force
) ? 0 : offsetInfo.offset * this._indentSize;
@@ -779,6 +780,19 @@ module.exports = {
}
/**
+ * Counts the number of linebreaks that follow the last non-whitespace character in a string
+ * @param {string} string The string to check
+ * @returns {number} The number of JavaScript linebreaks that follow the last non-whitespace character,
+ * or the total number of linebreaks if the string is all whitespace.
+ */
+ function countTrailingLinebreaks(string) {
+ const trailingWhitespace = string.match(/\s*$/)[0];
+ const linebreakMatches = trailingWhitespace.match(astUtils.createGlobalLinebreakMatcher());
+
+ return linebreakMatches === null ? 0 : linebreakMatches.length;
+ }
+
+ /**
* Check indentation for lists of elements (arrays, objects, function params)
* @param {ASTNode[]} elements List of elements that should be offset
* @param {Token} startToken The start token of the list that element should be aligned against, e.g. '['
@@ -835,8 +849,12 @@ module.exports = {
} else {
const previousElement = elements[index - 1];
const firstTokenOfPreviousElement = previousElement && getFirstToken(previousElement);
+ const previousElementLastToken = previousElement && sourceCode.getLastToken(previousElement);
- if (previousElement && sourceCode.getLastToken(previousElement).loc.start.line > startToken.loc.end.line) {
+ if (
+ previousElement &&
+ previousElementLastToken.loc.end.line - countTrailingLinebreaks(previousElementLastToken.value) > startToken.loc.end.line
+ ) {
offsets.setDesiredOffsets(element.range, firstTokenOfPreviousElement, 0);
}
}
@@ -979,6 +997,8 @@ module.exports = {
return !node || node.loc.start.line === token.loc.start.line;
}
+ const ignoredNodeFirstTokens = new Set();
+
const baseOffsetListeners = {
"ArrayExpression, ArrayPattern"(node) {
const openingBracket = sourceCode.getFirstToken(node);
@@ -1009,15 +1029,6 @@ module.exports = {
addElementListIndent(node.params, openingParen, closingParen, options.FunctionExpression.parameters);
}
addBlocklessNodeIndent(node.body);
-
- let arrowToken;
-
- if (node.params.length) {
- arrowToken = sourceCode.getTokenAfter(node.params[node.params.length - 1], astUtils.isArrowToken);
- } else {
- arrowToken = sourceCode.getFirstToken(node, astUtils.isArrowToken);
- }
- offsets.setDesiredOffset(arrowToken, sourceCode.getFirstToken(node), 0);
},
AssignmentExpression(node) {
@@ -1042,7 +1053,6 @@ module.exports = {
offsets.ignoreToken(operator);
offsets.ignoreToken(tokenAfterOperator);
offsets.setDesiredOffset(tokenAfterOperator, operator, 0);
- offsets.setDesiredOffsets([tokenAfterOperator.range[1], node.range[1]], tokenAfterOperator, 1);
},
"BlockStatement, ClassBody"(node) {
@@ -1094,8 +1104,8 @@ module.exports = {
const questionMarkToken = sourceCode.getFirstTokenBetween(node.test, node.consequent, token => token.type === "Punctuator" && token.value === "?");
const colonToken = sourceCode.getFirstTokenBetween(node.consequent, node.alternate, token => token.type === "Punctuator" && token.value === ":");
- const firstConsequentToken = sourceCode.getTokenAfter(questionMarkToken, { includeComments: true });
- const lastConsequentToken = sourceCode.getTokenBefore(colonToken, { includeComments: true });
+ const firstConsequentToken = sourceCode.getTokenAfter(questionMarkToken);
+ const lastConsequentToken = sourceCode.getTokenBefore(colonToken);
const firstAlternateToken = sourceCode.getTokenAfter(colonToken);
offsets.setDesiredOffset(questionMarkToken, firstToken, 1);
@@ -1128,9 +1138,6 @@ module.exports = {
*/
offsets.setDesiredOffset(firstAlternateToken, firstToken, 1);
}
-
- offsets.setDesiredOffsets([questionMarkToken.range[1], colonToken.range[0]], firstConsequentToken, 0);
- offsets.setDesiredOffsets([colonToken.range[1], node.range[1]], firstAlternateToken, 0);
}
},
@@ -1272,20 +1279,9 @@ module.exports = {
SwitchStatement(node) {
const openingCurly = sourceCode.getTokenAfter(node.discriminant, astUtils.isOpeningBraceToken);
const closingCurly = sourceCode.getLastToken(node);
- const caseKeywords = node.cases.map(switchCase => sourceCode.getFirstToken(switchCase));
offsets.setDesiredOffsets([openingCurly.range[1], closingCurly.range[0]], openingCurly, options.SwitchCase);
- node.cases.forEach((switchCase, index) => {
- const caseKeyword = caseKeywords[index];
-
- if (!(switchCase.consequent.length === 1 && switchCase.consequent[0].type === "BlockStatement")) {
- const tokenAfterCurrentCase = index === node.cases.length - 1 ? closingCurly : caseKeywords[index + 1];
-
- offsets.setDesiredOffsets([caseKeyword.range[1], tokenAfterCurrentCase.range[0]], caseKeyword, 1);
- }
- });
-
if (node.cases.length) {
sourceCode.getTokensBetween(
node.cases[node.cases.length - 1],
@@ -1295,6 +1291,15 @@ module.exports = {
}
},
+ SwitchCase(node) {
+ if (!(node.consequent.length === 1 && node.consequent[0].type === "BlockStatement")) {
+ const caseKeyword = sourceCode.getFirstToken(node);
+ const tokenAfterCurrentCase = sourceCode.getTokenAfter(node);
+
+ offsets.setDesiredOffsets([caseKeyword.range[1], tokenAfterCurrentCase.range[0]], caseKeyword, 1);
+ }
+ },
+
TemplateLiteral(node) {
node.expressions.forEach((expression, index) => {
const previousQuasi = node.quasis[index];
@@ -1385,7 +1390,6 @@ module.exports = {
const firstToken = sourceCode.getFirstToken(node);
offsets.setDesiredOffsets(node.name.range, firstToken, 1);
- offsets.setDesiredOffset(sourceCode.getLastToken(node), firstToken, 0);
},
JSXExpressionContainer(node) {
@@ -1397,7 +1401,15 @@ module.exports = {
openingCurly,
1
);
- offsets.setDesiredOffset(closingCurly, openingCurly, 0);
+ },
+
+ "*"(node) {
+ const firstToken = sourceCode.getFirstToken(node);
+
+ // Ensure that the children of every node are indented at least as much as the first token.
+ if (firstToken && !ignoredNodeFirstTokens.has(firstToken)) {
+ offsets.setDesiredOffsets(node.range, firstToken, 0);
+ }
}
};
@@ -1406,7 +1418,8 @@ module.exports = {
/*
* To ignore the indentation of a node:
* 1. Don't call the node's listener when entering it (if it has a listener)
- * 2. Call `ignoreNode` on the node sometime after exiting it and before validating offsets.
+ * 2. Don't set any offsets against the first token of the node.
+ * 3. Call `ignoreNode` on the node sometime after exiting it and before validating offsets.
*/
const offsetListeners = lodash.mapValues(
baseOffsetListeners,
@@ -1434,7 +1447,16 @@ module.exports = {
// For each ignored node selector, set up a listener to collect it into the `ignoredNodes` set.
const ignoredNodes = new Set();
- const addToIgnoredNodes = ignoredNodes.add.bind(ignoredNodes);
+
+ /**
+ * Ignores a node
+ * @param {ASTNode} node The node to ignore
+ * @returns {void}
+ */
+ function addToIgnoredNodes(node) {
+ ignoredNodes.add(node);
+ ignoredNodeFirstTokens.add(sourceCode.getFirstToken(node));
+ }
const ignoredNodeListeners = options.ignoredNodes.reduce(
(listeners, ignoredSelector) => Object.assign(listeners, { [ignoredSelector]: addToIgnoredNodes }),
@@ -1457,7 +1479,7 @@ module.exports = {
// If a node's type is nonstandard, we can't tell how its children should be offset, so ignore it.
if (!KNOWN_NODES.has(node.type)) {
- ignoredNodes.add(node);
+ addToIgnoredNodes(node);
}
},
"Program:exit"() {
diff --git a/tools/node_modules/eslint/lib/rules/key-spacing.js b/tools/node_modules/eslint/lib/rules/key-spacing.js
index 1ae4990a59..b1208e19e9 100644
--- a/tools/node_modules/eslint/lib/rules/key-spacing.js
+++ b/tools/node_modules/eslint/lib/rules/key-spacing.js
@@ -360,9 +360,10 @@ module.exports = {
*/
function isKeyValueProperty(property) {
return !(
- (property.method ||
+ property.method ||
property.shorthand ||
- property.kind !== "init" || property.type !== "Property") // Could be "ExperimentalSpreadProperty" or "SpreadProperty"
+ property.kind !== "init" ||
+ property.type !== "Property" // Could be "ExperimentalSpreadProperty" or "SpreadElement"
);
}
diff --git a/tools/node_modules/eslint/lib/rules/keyword-spacing.js b/tools/node_modules/eslint/lib/rules/keyword-spacing.js
index d0dd640255..a2ce79ab5a 100644
--- a/tools/node_modules/eslint/lib/rules/keyword-spacing.js
+++ b/tools/node_modules/eslint/lib/rules/keyword-spacing.js
@@ -108,13 +108,10 @@ module.exports = {
* Reports a given token if there are not space(s) before the token.
*
* @param {Token} token - A token to report.
- * @param {RegExp|undefined} pattern - Optional. A pattern of the previous
- * token to check.
+ * @param {RegExp} pattern - A pattern of the previous token to check.
* @returns {void}
*/
function expectSpaceBefore(token, pattern) {
- pattern = pattern || PREV_TOKEN;
-
const prevToken = sourceCode.getTokenBefore(token);
if (prevToken &&
@@ -138,13 +135,10 @@ module.exports = {
* Reports a given token if there are space(s) before the token.
*
* @param {Token} token - A token to report.
- * @param {RegExp|undefined} pattern - Optional. A pattern of the previous
- * token to check.
+ * @param {RegExp} pattern - A pattern of the previous token to check.
* @returns {void}
*/
function unexpectSpaceBefore(token, pattern) {
- pattern = pattern || PREV_TOKEN;
-
const prevToken = sourceCode.getTokenBefore(token);
if (prevToken &&
@@ -168,13 +162,10 @@ module.exports = {
* Reports a given token if there are not space(s) after the token.
*
* @param {Token} token - A token to report.
- * @param {RegExp|undefined} pattern - Optional. A pattern of the next
- * token to check.
+ * @param {RegExp} pattern - A pattern of the next token to check.
* @returns {void}
*/
function expectSpaceAfter(token, pattern) {
- pattern = pattern || NEXT_TOKEN;
-
const nextToken = sourceCode.getTokenAfter(token);
if (nextToken &&
@@ -198,13 +189,10 @@ module.exports = {
* Reports a given token if there are space(s) after the token.
*
* @param {Token} token - A token to report.
- * @param {RegExp|undefined} pattern - Optional. A pattern of the next
- * token to check.
+ * @param {RegExp} pattern - A pattern of the next token to check.
* @returns {void}
*/
function unexpectSpaceAfter(token, pattern) {
- pattern = pattern || NEXT_TOKEN;
-
const nextToken = sourceCode.getTokenAfter(token);
if (nextToken &&
@@ -274,7 +262,7 @@ module.exports = {
* @returns {void}
*/
function checkSpacingBefore(token, pattern) {
- checkMethodMap[token.value].before(token, pattern);
+ checkMethodMap[token.value].before(token, pattern || PREV_TOKEN);
}
/**
@@ -287,7 +275,7 @@ module.exports = {
* @returns {void}
*/
function checkSpacingAfter(token, pattern) {
- checkMethodMap[token.value].after(token, pattern);
+ checkMethodMap[token.value].after(token, pattern || NEXT_TOKEN);
}
/**
@@ -436,7 +424,12 @@ module.exports = {
* @returns {void}
*/
function checkSpacingForForOfStatement(node) {
- checkSpacingAroundFirstToken(node);
+ if (node.await) {
+ checkSpacingBefore(sourceCode.getFirstToken(node, 0));
+ checkSpacingAfter(sourceCode.getFirstToken(node, 1));
+ } else {
+ checkSpacingAroundFirstToken(node);
+ }
checkSpacingAround(sourceCode.getTokenBefore(node.right, astUtils.isNotOpeningParenToken));
}
diff --git a/tools/node_modules/eslint/lib/rules/max-len.js b/tools/node_modules/eslint/lib/rules/max-len.js
index 35ac803b65..273eb84907 100644
--- a/tools/node_modules/eslint/lib/rules/max-len.js
+++ b/tools/node_modules/eslint/lib/rules/max-len.js
@@ -213,7 +213,8 @@ module.exports = {
* @returns {ASTNode[]} An array of string nodes.
*/
function getAllStrings() {
- return sourceCode.ast.tokens.filter(token => token.type === "String");
+ return sourceCode.ast.tokens.filter(token => (token.type === "String" ||
+ (token.type === "JSXText" && sourceCode.getNodeByRangeIndex(token.range[0] - 1).type === "JSXAttribute")));
}
/**
@@ -287,6 +288,7 @@ module.exports = {
* line is a comment
*/
let lineIsComment = false;
+ let textToMeasure;
/*
* We can short-circuit the comment checks if we're already out of
@@ -305,12 +307,17 @@ module.exports = {
if (isFullLineComment(line, lineNumber, comment)) {
lineIsComment = true;
+ textToMeasure = line;
} else if (ignoreTrailingComments && isTrailingComment(line, lineNumber, comment)) {
- line = stripTrailingComment(line, comment);
+ textToMeasure = stripTrailingComment(line, comment);
+ } else {
+ textToMeasure = line;
}
+ } else {
+ textToMeasure = line;
}
- if (ignorePattern && ignorePattern.test(line) ||
- ignoreUrls && URL_REGEXP.test(line) ||
+ if (ignorePattern && ignorePattern.test(textToMeasure) ||
+ ignoreUrls && URL_REGEXP.test(textToMeasure) ||
ignoreStrings && stringsByLine[lineNumber] ||
ignoreTemplateLiterals && templateLiteralsByLine[lineNumber] ||
ignoreRegExpLiterals && regExpLiteralsByLine[lineNumber]
@@ -320,7 +327,7 @@ module.exports = {
return;
}
- const lineLength = computeLineLength(line, tabWidth);
+ const lineLength = computeLineLength(textToMeasure, tabWidth);
const commentLengthApplies = lineIsComment && maxCommentLength;
if (lineIsComment && ignoreComments) {
diff --git a/tools/node_modules/eslint/lib/rules/no-alert.js b/tools/node_modules/eslint/lib/rules/no-alert.js
index b4fd231215..69d419da1c 100644
--- a/tools/node_modules/eslint/lib/rules/no-alert.js
+++ b/tools/node_modules/eslint/lib/rules/no-alert.js
@@ -24,17 +24,6 @@ function isProhibitedIdentifier(name) {
}
/**
- * Reports the given node and identifier name.
- * @param {RuleContext} context The ESLint rule context.
- * @param {ASTNode} node The node to report on.
- * @param {string} identifierName The name of the identifier.
- * @returns {void}
- */
-function report(context, node, identifierName) {
- context.report(node, "Unexpected {{name}}.", { name: identifierName });
-}
-
-/**
* Finds the eslint-scope reference in the given scope.
* @param {Object} scope The scope to search.
* @param {ASTNode} node The identifier node.
@@ -92,7 +81,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-alert"
},
- schema: []
+ schema: [],
+
+ messages: {
+ unexpected: "Unexpected {{name}}."
+ }
},
create(context) {
@@ -103,17 +96,25 @@ module.exports = {
// without window.
if (callee.type === "Identifier") {
- const identifierName = callee.name;
+ const name = callee.name;
if (!isShadowed(currentScope, callee) && isProhibitedIdentifier(callee.name)) {
- report(context, node, identifierName);
+ context.report({
+ node,
+ messageId: "unexpected",
+ data: { name }
+ });
}
} else if (callee.type === "MemberExpression" && isGlobalThisReferenceOrGlobalWindow(currentScope, callee.object)) {
- const identifierName = getPropertyName(callee);
-
- if (isProhibitedIdentifier(identifierName)) {
- report(context, node, identifierName);
+ const name = getPropertyName(callee);
+
+ if (isProhibitedIdentifier(name)) {
+ context.report({
+ node,
+ messageId: "unexpected",
+ data: { name }
+ });
}
}
diff --git a/tools/node_modules/eslint/lib/rules/no-array-constructor.js b/tools/node_modules/eslint/lib/rules/no-array-constructor.js
index 187389fdff..51676f7821 100644
--- a/tools/node_modules/eslint/lib/rules/no-array-constructor.js
+++ b/tools/node_modules/eslint/lib/rules/no-array-constructor.js
@@ -18,7 +18,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-array-constructor"
},
- schema: []
+ schema: [],
+
+ messages: {
+ preferLiteral: "The array literal notation [] is preferable."
+ }
},
create(context) {
@@ -35,7 +39,7 @@ module.exports = {
node.callee.type === "Identifier" &&
node.callee.name === "Array"
) {
- context.report({ node, message: "The array literal notation [] is preferrable." });
+ context.report({ node, messageId: "preferLiteral" });
}
}
diff --git a/tools/node_modules/eslint/lib/rules/no-await-in-loop.js b/tools/node_modules/eslint/lib/rules/no-await-in-loop.js
index 7d4f8a0a6b..ef0bda90bf 100644
--- a/tools/node_modules/eslint/lib/rules/no-await-in-loop.js
+++ b/tools/node_modules/eslint/lib/rules/no-await-in-loop.js
@@ -4,24 +4,54 @@
*/
"use strict";
-// Node types which are considered loops.
-const loopTypes = new Set([
- "ForStatement",
- "ForOfStatement",
- "ForInStatement",
- "WhileStatement",
- "DoWhileStatement"
-]);
+/**
+ * Check whether it should stop traversing ancestors at the given node.
+ * @param {ASTNode} node A node to check.
+ * @returns {boolean} `true` if it should stop traversing.
+ */
+function isBoundary(node) {
+ const t = node.type;
+
+ return (
+ t === "FunctionDeclaration" ||
+ t === "FunctionExpression" ||
+ t === "ArrowFunctionExpression" ||
+
+ /*
+ * Don't report the await expressions on for-await-of loop since it's
+ * asynchronous iteration intentionally.
+ */
+ (t === "ForOfStatement" && node.await === true)
+ );
+}
-/*
- * Node types at which we should stop looking for loops. For example, it is fine to declare an async
- * function within a loop, and use await inside of that.
+/**
+ * Check whether the given node is in loop.
+ * @param {ASTNode} node A node to check.
+ * @param {ASTNode} parent A parent node to check.
+ * @returns {boolean} `true` if the node is in loop.
*/
-const boundaryTypes = new Set([
- "FunctionDeclaration",
- "FunctionExpression",
- "ArrowFunctionExpression"
-]);
+function isLooped(node, parent) {
+ switch (parent.type) {
+ case "ForStatement":
+ return (
+ node === parent.test ||
+ node === parent.update ||
+ node === parent.body
+ );
+
+ case "ForOfStatement":
+ case "ForInStatement":
+ return node === parent.body;
+
+ case "WhileStatement":
+ case "DoWhileStatement":
+ return node === parent.test || node === parent.body;
+
+ default:
+ return false;
+ }
+}
module.exports = {
meta: {
@@ -31,54 +61,42 @@ module.exports = {
recommended: false,
url: "https://eslint.org/docs/rules/no-await-in-loop"
},
- schema: []
+ schema: [],
+ messages: {
+ unexpectedAwait: "Unexpected `await` inside a loop."
+ }
},
create(context) {
- return {
- AwaitExpression(node) {
- const ancestors = context.getAncestors();
-
- // Reverse so that we can traverse from the deepest node upwards.
- ancestors.reverse();
-
- /*
- * Create a set of all the ancestors plus this node so that we can check
- * if this use of await appears in the body of the loop as opposed to
- * the right-hand side of a for...of, for example.
- */
- const ancestorSet = new Set(ancestors).add(node);
- for (let i = 0; i < ancestors.length; i++) {
- const ancestor = ancestors[i];
-
- if (boundaryTypes.has(ancestor.type)) {
+ /**
+ * Validate an await expression.
+ * @param {ASTNode} awaitNode An AwaitExpression or ForOfStatement node to validate.
+ * @returns {void}
+ */
+ function validate(awaitNode) {
+ if (awaitNode.type === "ForOfStatement" && !awaitNode.await) {
+ return;
+ }
- /*
- * Short-circuit out if we encounter a boundary type. Loops above
- * this do not matter.
- */
- return;
- }
- if (loopTypes.has(ancestor.type)) {
+ let node = awaitNode;
+ let parent = node.parent;
- /*
- * Only report if we are actually in the body or another part that gets executed on
- * every iteration.
- */
- if (
- ancestorSet.has(ancestor.body) ||
- ancestorSet.has(ancestor.test) ||
- ancestorSet.has(ancestor.update)
- ) {
- context.report({
- node,
- message: "Unexpected `await` inside a loop."
- });
- return;
- }
- }
+ while (parent && !isBoundary(parent)) {
+ if (isLooped(node, parent)) {
+ context.report({
+ node: awaitNode,
+ messageId: "unexpectedAwait"
+ });
+ return;
}
+ node = parent;
+ parent = parent.parent;
}
+ }
+
+ return {
+ AwaitExpression: validate,
+ ForOfStatement: validate
};
}
};
diff --git a/tools/node_modules/eslint/lib/rules/no-bitwise.js b/tools/node_modules/eslint/lib/rules/no-bitwise.js
index 8376674f65..36bbdaf349 100644
--- a/tools/node_modules/eslint/lib/rules/no-bitwise.js
+++ b/tools/node_modules/eslint/lib/rules/no-bitwise.js
@@ -46,7 +46,11 @@ module.exports = {
},
additionalProperties: false
}
- ]
+ ],
+
+ messages: {
+ unexpected: "Unexpected use of '{{operator}}'."
+ }
},
create(context) {
@@ -60,7 +64,7 @@ module.exports = {
* @returns {void}
*/
function report(node) {
- context.report({ node, message: "Unexpected use of '{{operator}}'.", data: { operator: node.operator } });
+ context.report({ node, messageId: "unexpected", data: { operator: node.operator } });
}
/**
diff --git a/tools/node_modules/eslint/lib/rules/no-buffer-constructor.js b/tools/node_modules/eslint/lib/rules/no-buffer-constructor.js
index 55f181ee69..51f78edb1f 100644
--- a/tools/node_modules/eslint/lib/rules/no-buffer-constructor.js
+++ b/tools/node_modules/eslint/lib/rules/no-buffer-constructor.js
@@ -11,12 +11,15 @@
module.exports = {
meta: {
docs: {
- description: "disallow use of the Buffer() constructor",
+ description: "disallow use of the `Buffer()` constructor",
category: "Node.js and CommonJS",
recommended: false,
url: "https://eslint.org/docs/rules/no-buffer-constructor"
},
- schema: []
+ schema: [],
+ messages: {
+ deprecated: "{{expr}} is deprecated. Use Buffer.from(), Buffer.alloc(), or Buffer.allocUnsafe() instead."
+ }
},
create(context) {
@@ -29,8 +32,8 @@ module.exports = {
"CallExpression[callee.name='Buffer'], NewExpression[callee.name='Buffer']"(node) {
context.report({
node,
- message: "{{example}} is deprecated. Use Buffer.from(), Buffer.alloc(), or Buffer.allocUnsafe() instead.",
- data: { example: node.type === "CallExpression" ? "Buffer()" : "new Buffer()" }
+ messageId: "deprecated",
+ data: { expr: node.type === "CallExpression" ? "Buffer()" : "new Buffer()" }
});
}
};
diff --git a/tools/node_modules/eslint/lib/rules/no-caller.js b/tools/node_modules/eslint/lib/rules/no-caller.js
index df10bf3736..9756b212ff 100644
--- a/tools/node_modules/eslint/lib/rules/no-caller.js
+++ b/tools/node_modules/eslint/lib/rules/no-caller.js
@@ -18,7 +18,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-caller"
},
- schema: []
+ schema: [],
+
+ messages: {
+ unexpected: "Avoid arguments.{{prop}}."
+ }
},
create(context) {
@@ -30,7 +34,7 @@ module.exports = {
propertyName = node.property.name;
if (objectName === "arguments" && !node.computed && propertyName && propertyName.match(/^calle[er]$/)) {
- context.report({ node, message: "Avoid arguments.{{property}}.", data: { property: propertyName } });
+ context.report({ node, messageId: "unexpected", data: { prop: propertyName } });
}
}
diff --git a/tools/node_modules/eslint/lib/rules/no-case-declarations.js b/tools/node_modules/eslint/lib/rules/no-case-declarations.js
index 03c730ddbd..862be4c57d 100644
--- a/tools/node_modules/eslint/lib/rules/no-case-declarations.js
+++ b/tools/node_modules/eslint/lib/rules/no-case-declarations.js
@@ -17,7 +17,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-case-declarations"
},
- schema: []
+ schema: [],
+
+ messages: {
+ unexpected: "Unexpected lexical declaration in case block."
+ }
},
create(context) {
@@ -47,7 +51,7 @@ module.exports = {
if (isLexicalDeclaration(statement)) {
context.report({
node,
- message: "Unexpected lexical declaration in case block."
+ messageId: "unexpected"
});
}
}
diff --git a/tools/node_modules/eslint/lib/rules/no-catch-shadow.js b/tools/node_modules/eslint/lib/rules/no-catch-shadow.js
index 69a4e6aff8..907792278f 100644
--- a/tools/node_modules/eslint/lib/rules/no-catch-shadow.js
+++ b/tools/node_modules/eslint/lib/rules/no-catch-shadow.js
@@ -24,7 +24,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-catch-shadow"
},
- schema: []
+ schema: [],
+
+ messages: {
+ mutable: "Value of '{{name}}' may be overwritten in IE 8 and earlier."
+ }
},
create(context) {
@@ -61,7 +65,7 @@ module.exports = {
}
if (paramIsShadowing(scope, node.param.name)) {
- context.report({ node, message: "Value of '{{name}}' may be overwritten in IE 8 and earlier.", data: { name: node.param.name } });
+ context.report({ node, messageId: "mutable", data: { name: node.param.name } });
}
}
};
diff --git a/tools/node_modules/eslint/lib/rules/no-class-assign.js b/tools/node_modules/eslint/lib/rules/no-class-assign.js
index 56e75122a2..58dddd6a68 100644
--- a/tools/node_modules/eslint/lib/rules/no-class-assign.js
+++ b/tools/node_modules/eslint/lib/rules/no-class-assign.js
@@ -20,7 +20,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-class-assign"
},
- schema: []
+ schema: [],
+
+ messages: {
+ class: "'{{name}}' is a class."
+ }
},
create(context) {
@@ -32,7 +36,7 @@ module.exports = {
*/
function checkVariable(variable) {
astUtils.getModifyingReferences(variable.references).forEach(reference => {
- context.report({ node: reference.identifier, message: "'{{name}}' is a class.", data: { name: reference.identifier.name } });
+ context.report({ node: reference.identifier, messageId: "class", data: { name: reference.identifier.name } });
});
}
diff --git a/tools/node_modules/eslint/lib/rules/no-compare-neg-zero.js b/tools/node_modules/eslint/lib/rules/no-compare-neg-zero.js
index 09cf295063..6903bd0654 100644
--- a/tools/node_modules/eslint/lib/rules/no-compare-neg-zero.js
+++ b/tools/node_modules/eslint/lib/rules/no-compare-neg-zero.js
@@ -17,7 +17,10 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-compare-neg-zero"
},
fixable: null,
- schema: []
+ schema: [],
+ messages: {
+ unexpected: "Do not use the '{{operator}}' operator to compare against -0."
+ }
},
create(context) {
@@ -43,7 +46,7 @@ module.exports = {
if (isNegZero(node.left) || isNegZero(node.right)) {
context.report({
node,
- message: "Do not use the '{{operator}}' operator to compare against -0.",
+ messageId: "unexpected",
data: { operator: node.operator }
});
}
diff --git a/tools/node_modules/eslint/lib/rules/no-cond-assign.js b/tools/node_modules/eslint/lib/rules/no-cond-assign.js
index e761be14ec..f949bcc884 100644
--- a/tools/node_modules/eslint/lib/rules/no-cond-assign.js
+++ b/tools/node_modules/eslint/lib/rules/no-cond-assign.js
@@ -30,7 +30,14 @@ module.exports = {
{
enum: ["except-parens", "always"]
}
- ]
+ ],
+
+ messages: {
+ unexpected: "Unexpected assignment within {{type}}.",
+
+ // must match JSHint's error message
+ missing: "Expected a conditional expression and instead saw an assignment."
+ }
},
create(context) {
@@ -95,11 +102,10 @@ module.exports = {
)
) {
- // must match JSHint's error message
context.report({
node,
loc: node.test.loc.start,
- message: "Expected a conditional expression and instead saw an assignment."
+ messageId: "missing"
});
}
}
@@ -115,7 +121,7 @@ module.exports = {
if (ancestor) {
context.report({
node: ancestor,
- message: "Unexpected assignment within {{type}}.",
+ messageId: "unexpected",
data: {
type: NODE_DESCRIPTIONS[ancestor.type] || ancestor.type
}
diff --git a/tools/node_modules/eslint/lib/rules/no-confusing-arrow.js b/tools/node_modules/eslint/lib/rules/no-confusing-arrow.js
index 542a4060e2..297e3b1480 100644
--- a/tools/node_modules/eslint/lib/rules/no-confusing-arrow.js
+++ b/tools/node_modules/eslint/lib/rules/no-confusing-arrow.js
@@ -42,7 +42,11 @@ module.exports = {
allowParens: { type: "boolean" }
},
additionalProperties: false
- }]
+ }],
+
+ messages: {
+ confusing: "Arrow function used ambiguously with a conditional expression."
+ }
},
create(context) {
@@ -60,7 +64,7 @@ module.exports = {
if (isConditional(body) && !(config.allowParens && astUtils.isParenthesised(sourceCode, body))) {
context.report({
node,
- message: "Arrow function used ambiguously with a conditional expression.",
+ messageId: "confusing",
fix(fixer) {
// if `allowParens` is not set to true dont bother wrapping in parens
diff --git a/tools/node_modules/eslint/lib/rules/no-console.js b/tools/node_modules/eslint/lib/rules/no-console.js
index b00582ebad..fd5c33a8e7 100644
--- a/tools/node_modules/eslint/lib/rules/no-console.js
+++ b/tools/node_modules/eslint/lib/rules/no-console.js
@@ -39,7 +39,11 @@ module.exports = {
},
additionalProperties: false
}
- ]
+ ],
+
+ messages: {
+ unexpected: "Unexpected console statement."
+ }
},
create(context) {
@@ -102,7 +106,7 @@ module.exports = {
context.report({
node,
loc: node.loc,
- message: "Unexpected console statement."
+ messageId: "unexpected"
});
}
diff --git a/tools/node_modules/eslint/lib/rules/no-const-assign.js b/tools/node_modules/eslint/lib/rules/no-const-assign.js
index 8a08a52df4..043fe05df7 100644
--- a/tools/node_modules/eslint/lib/rules/no-const-assign.js
+++ b/tools/node_modules/eslint/lib/rules/no-const-assign.js
@@ -20,7 +20,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-const-assign"
},
- schema: []
+ schema: [],
+
+ messages: {
+ const: "'{{name}}' is constant."
+ }
},
create(context) {
@@ -32,7 +36,7 @@ module.exports = {
*/
function checkVariable(variable) {
astUtils.getModifyingReferences(variable.references).forEach(reference => {
- context.report({ node: reference.identifier, message: "'{{name}}' is constant.", data: { name: reference.identifier.name } });
+ context.report({ node: reference.identifier, messageId: "const", data: { name: reference.identifier.name } });
});
}
diff --git a/tools/node_modules/eslint/lib/rules/no-constant-condition.js b/tools/node_modules/eslint/lib/rules/no-constant-condition.js
index 5611d617ec..724da97412 100644
--- a/tools/node_modules/eslint/lib/rules/no-constant-condition.js
+++ b/tools/node_modules/eslint/lib/rules/no-constant-condition.js
@@ -28,8 +28,11 @@ module.exports = {
},
additionalProperties: false
}
+ ],
- ]
+ messages: {
+ unexpected: "Unexpected constant condition."
+ }
},
create(context) {
@@ -139,7 +142,7 @@ module.exports = {
function checkConstantConditionLoopInSet(node) {
if (loopsInCurrentScope.has(node)) {
loopsInCurrentScope.delete(node);
- context.report({ node: node.test, message: "Unexpected constant condition." });
+ context.report({ node: node.test, messageId: "unexpected" });
}
}
@@ -151,7 +154,7 @@ module.exports = {
*/
function reportIfConstant(node) {
if (node.test && isConstant(node.test, true)) {
- context.report({ node: node.test, message: "Unexpected constant condition." });
+ context.report({ node: node.test, messageId: "unexpected" });
}
}
diff --git a/tools/node_modules/eslint/lib/rules/no-continue.js b/tools/node_modules/eslint/lib/rules/no-continue.js
index 52061ef532..3075b77f9f 100644
--- a/tools/node_modules/eslint/lib/rules/no-continue.js
+++ b/tools/node_modules/eslint/lib/rules/no-continue.js
@@ -18,14 +18,18 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-continue"
},
- schema: []
+ schema: [],
+
+ messages: {
+ unexpected: "Unexpected use of continue statement."
+ }
},
create(context) {
return {
ContinueStatement(node) {
- context.report({ node, message: "Unexpected use of continue statement." });
+ context.report({ node, messageId: "unexpected" });
}
};
diff --git a/tools/node_modules/eslint/lib/rules/no-control-regex.js b/tools/node_modules/eslint/lib/rules/no-control-regex.js
index 676c666128..24bb6be667 100644
--- a/tools/node_modules/eslint/lib/rules/no-control-regex.js
+++ b/tools/node_modules/eslint/lib/rules/no-control-regex.js
@@ -5,6 +5,44 @@
"use strict";
+const RegExpValidator = require("regexpp").RegExpValidator;
+const collector = new class {
+ constructor() {
+ this.ecmaVersion = 2018;
+ this._source = "";
+ this._controlChars = [];
+ this._validator = new RegExpValidator(this);
+ }
+
+ onPatternEnter() {
+ this._controlChars = [];
+ }
+
+ onCharacter(start, end, cp) {
+ if (cp >= 0x00 &&
+ cp <= 0x1F &&
+ (
+ this._source.codePointAt(start) === cp ||
+ this._source.slice(start, end).startsWith("\\x") ||
+ this._source.slice(start, end).startsWith("\\u")
+ )
+ ) {
+ this._controlChars.push(`\\x${`0${cp.toString(16)}`.slice(-2)}`);
+ }
+ }
+
+ collectControlChars(regexpStr) {
+ try {
+ this._source = regexpStr;
+ this._validator.validatePattern(regexpStr); // Call onCharacter hook
+ } catch (err) {
+
+ // Ignore syntax errors in RegExp.
+ }
+ return this._controlChars;
+ }
+}();
+
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
@@ -18,7 +56,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-control-regex"
},
- schema: []
+ schema: [],
+
+ messages: {
+ unexpected: "Unexpected control character(s) in regular expression: {{controlChars}}."
+ }
},
create(context) {
@@ -26,95 +68,36 @@ module.exports = {
/**
* Get the regex expression
* @param {ASTNode} node node to evaluate
- * @returns {*} Regex if found else null
+ * @returns {RegExp|null} Regex if found else null
* @private
*/
- function getRegExp(node) {
- if (node.value instanceof RegExp) {
- return node.value;
+ function getRegExpPattern(node) {
+ if (node.regex) {
+ return node.regex.pattern;
}
- if (typeof node.value === "string") {
-
- const parent = context.getAncestors().pop();
-
- if ((parent.type === "NewExpression" || parent.type === "CallExpression") &&
- parent.callee.type === "Identifier" && parent.callee.name === "RegExp"
- ) {
-
- // there could be an invalid regular expression string
- try {
- return new RegExp(node.value);
- } catch (ex) {
- return null;
- }
- }
+ if (typeof node.value === "string" &&
+ (node.parent.type === "NewExpression" || node.parent.type === "CallExpression") &&
+ node.parent.callee.type === "Identifier" &&
+ node.parent.callee.name === "RegExp" &&
+ node.parent.arguments[0] === node
+ ) {
+ return node.value;
}
return null;
}
-
- const controlChar = /[\x00-\x1f]/g; // eslint-disable-line no-control-regex
- const consecutiveSlashes = /\\+/g;
- const consecutiveSlashesAtEnd = /\\+$/g;
- const stringControlChar = /\\x[01][0-9a-f]/ig;
- const stringControlCharWithoutSlash = /x[01][0-9a-f]/ig;
-
- /**
- * Return a list of the control characters in the given regex string
- * @param {string} regexStr regex as string to check
- * @returns {array} returns a list of found control characters on given string
- * @private
- */
- function getControlCharacters(regexStr) {
-
- // check control characters, if RegExp object used
- const controlChars = regexStr.match(controlChar) || [];
-
- let stringControlChars = [];
-
- // check substr, if regex literal used
- const subStrIndex = regexStr.search(stringControlChar);
-
- if (subStrIndex > -1) {
-
- // is it escaped, check backslash count
- const possibleEscapeCharacters = regexStr.slice(0, subStrIndex).match(consecutiveSlashesAtEnd);
-
- const hasControlChars = possibleEscapeCharacters === null || !(possibleEscapeCharacters[0].length % 2);
-
- if (hasControlChars) {
- stringControlChars = regexStr.slice(subStrIndex, -1)
- .split(consecutiveSlashes)
- .filter(Boolean)
- .map(x => {
- const match = x.match(stringControlCharWithoutSlash) || [x];
-
- return `\\${match[0]}`;
- });
- }
- }
-
- return controlChars.map(x => {
- const hexCode = `0${x.charCodeAt(0).toString(16)}`.slice(-2);
-
- return `\\x${hexCode}`;
- }).concat(stringControlChars);
- }
-
return {
Literal(node) {
- const regex = getRegExp(node);
-
- if (regex) {
- const computedValue = regex.toString();
+ const pattern = getRegExpPattern(node);
- const controlCharacters = getControlCharacters(computedValue);
+ if (pattern) {
+ const controlCharacters = collector.collectControlChars(pattern);
if (controlCharacters.length > 0) {
context.report({
node,
- message: "Unexpected control character(s) in regular expression: {{controlChars}}.",
+ messageId: "unexpected",
data: {
controlChars: controlCharacters.join(", ")
}
diff --git a/tools/node_modules/eslint/lib/rules/no-debugger.js b/tools/node_modules/eslint/lib/rules/no-debugger.js
index 7d816e3a00..f00e819df0 100644
--- a/tools/node_modules/eslint/lib/rules/no-debugger.js
+++ b/tools/node_modules/eslint/lib/rules/no-debugger.js
@@ -20,7 +20,10 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-debugger"
},
fixable: "code",
- schema: []
+ schema: [],
+ messages: {
+ unexpected: "Unexpected 'debugger' statement."
+ }
},
create(context) {
@@ -29,7 +32,7 @@ module.exports = {
DebuggerStatement(node) {
context.report({
node,
- message: "Unexpected 'debugger' statement.",
+ messageId: "unexpected",
fix(fixer) {
if (astUtils.STATEMENT_LIST_PARENTS.has(node.parent.type)) {
return fixer.remove(node);
diff --git a/tools/node_modules/eslint/lib/rules/no-delete-var.js b/tools/node_modules/eslint/lib/rules/no-delete-var.js
index 9ca09f1dea..f54a396ec2 100644
--- a/tools/node_modules/eslint/lib/rules/no-delete-var.js
+++ b/tools/node_modules/eslint/lib/rules/no-delete-var.js
@@ -18,7 +18,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-delete-var"
},
- schema: []
+ schema: [],
+
+ messages: {
+ unexpected: "Variables should not be deleted."
+ }
},
create(context) {
@@ -27,7 +31,7 @@ module.exports = {
UnaryExpression(node) {
if (node.operator === "delete" && node.argument.type === "Identifier") {
- context.report({ node, message: "Variables should not be deleted." });
+ context.report({ node, messageId: "unexpected" });
}
}
};
diff --git a/tools/node_modules/eslint/lib/rules/no-div-regex.js b/tools/node_modules/eslint/lib/rules/no-div-regex.js
index 87423f8861..c050249fd6 100644
--- a/tools/node_modules/eslint/lib/rules/no-div-regex.js
+++ b/tools/node_modules/eslint/lib/rules/no-div-regex.js
@@ -18,7 +18,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-div-regex"
},
- schema: []
+ schema: [],
+
+ messages: {
+ unexpected: "A regular expression literal can be confused with '/='."
+ }
},
create(context) {
@@ -30,7 +34,7 @@ module.exports = {
const token = sourceCode.getFirstToken(node);
if (token.type === "RegularExpression" && token.value[1] === "=") {
- context.report({ node, message: "A regular expression literal can be confused with '/='." });
+ context.report({ node, messageId: "unexpected" });
}
}
};
diff --git a/tools/node_modules/eslint/lib/rules/no-dupe-args.js b/tools/node_modules/eslint/lib/rules/no-dupe-args.js
index a71d01f9bd..e5a7f4154e 100644
--- a/tools/node_modules/eslint/lib/rules/no-dupe-args.js
+++ b/tools/node_modules/eslint/lib/rules/no-dupe-args.js
@@ -18,7 +18,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-dupe-args"
},
- schema: []
+ schema: [],
+
+ messages: {
+ unexpected: "Duplicate param '{{name}}'."
+ }
},
create(context) {
@@ -54,7 +58,7 @@ module.exports = {
if (defs.length >= 2) {
context.report({
node,
- message: "Duplicate param '{{name}}'.",
+ messageId: "unexpected",
data: { name: variable.name }
});
}
diff --git a/tools/node_modules/eslint/lib/rules/no-dupe-class-members.js b/tools/node_modules/eslint/lib/rules/no-dupe-class-members.js
index cc7f8da284..d0fc359736 100644
--- a/tools/node_modules/eslint/lib/rules/no-dupe-class-members.js
+++ b/tools/node_modules/eslint/lib/rules/no-dupe-class-members.js
@@ -18,7 +18,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-dupe-class-members"
},
- schema: []
+ schema: [],
+
+ messages: {
+ unexpected: "Duplicate name '{{name}}'."
+ }
},
create(context) {
@@ -102,7 +106,7 @@ module.exports = {
}
if (isDuplicate) {
- context.report({ node, message: "Duplicate name '{{name}}'.", data: { name } });
+ context.report({ node, messageId: "unexpected", data: { name } });
}
}
};
diff --git a/tools/node_modules/eslint/lib/rules/no-dupe-keys.js b/tools/node_modules/eslint/lib/rules/no-dupe-keys.js
index 10955e4503..577710c65d 100644
--- a/tools/node_modules/eslint/lib/rules/no-dupe-keys.js
+++ b/tools/node_modules/eslint/lib/rules/no-dupe-keys.js
@@ -91,7 +91,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-dupe-keys"
},
- schema: []
+ schema: [],
+
+ messages: {
+ unexpected: "Duplicate key '{{name}}'."
+ }
},
create(context) {
@@ -123,7 +127,7 @@ module.exports = {
context.report({
node: info.node,
loc: node.key.loc,
- message: "Duplicate key '{{name}}'.",
+ messageId: "unexpected",
data: { name }
});
}
diff --git a/tools/node_modules/eslint/lib/rules/no-duplicate-case.js b/tools/node_modules/eslint/lib/rules/no-duplicate-case.js
index 2a9d955111..128b1fc1b1 100644
--- a/tools/node_modules/eslint/lib/rules/no-duplicate-case.js
+++ b/tools/node_modules/eslint/lib/rules/no-duplicate-case.js
@@ -19,7 +19,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-duplicate-case"
},
- schema: []
+ schema: [],
+
+ messages: {
+ unexpected: "Duplicate case label."
+ }
},
create(context) {
@@ -33,7 +37,7 @@ module.exports = {
const key = sourceCode.getText(switchCase.test);
if (mapping[key]) {
- context.report({ node: switchCase, message: "Duplicate case label." });
+ context.report({ node: switchCase, messageId: "unexpected" });
} else {
mapping[key] = switchCase;
}
diff --git a/tools/node_modules/eslint/lib/rules/no-else-return.js b/tools/node_modules/eslint/lib/rules/no-else-return.js
index 91cb5b9796..5e58acfe05 100644
--- a/tools/node_modules/eslint/lib/rules/no-else-return.js
+++ b/tools/node_modules/eslint/lib/rules/no-else-return.js
@@ -34,7 +34,12 @@ module.exports = {
},
additionalProperties: false
}],
- fixable: "code"
+
+ fixable: "code",
+
+ messages: {
+ unexpected: "Unnecessary 'else' after 'return'."
+ }
},
create(context) {
@@ -52,7 +57,7 @@ module.exports = {
function displayReport(node) {
context.report({
node,
- message: "Unnecessary 'else' after 'return'.",
+ messageId: "unexpected",
fix: fixer => {
const sourceCode = context.getSourceCode();
const startToken = sourceCode.getFirstToken(node);
@@ -212,8 +217,6 @@ module.exports = {
*/
function checkIfWithoutElse(node) {
const parent = node.parent;
- let consequents,
- alternate;
/*
* Fixing this would require splitting one statement into two, so no error should
@@ -223,12 +226,15 @@ module.exports = {
return;
}
- for (consequents = []; node.type === "IfStatement"; node = node.alternate) {
- if (!node.alternate) {
+ const consequents = [];
+ let alternate;
+
+ for (let currentNode = node; currentNode.type === "IfStatement"; currentNode = currentNode.alternate) {
+ if (!currentNode.alternate) {
return;
}
- consequents.push(node.consequent);
- alternate = node.alternate;
+ consequents.push(currentNode.consequent);
+ alternate = currentNode.alternate;
}
if (consequents.every(alwaysReturns)) {
diff --git a/tools/node_modules/eslint/lib/rules/no-empty-character-class.js b/tools/node_modules/eslint/lib/rules/no-empty-character-class.js
index 3c4806632e..e3f06b069a 100644
--- a/tools/node_modules/eslint/lib/rules/no-empty-character-class.js
+++ b/tools/node_modules/eslint/lib/rules/no-empty-character-class.js
@@ -21,7 +21,7 @@
* 4. `[gimuy]*`: optional regexp flags
* 5. `$`: fix the match at the end of the string
*/
-const regex = /^\/([^\\[]|\\.|\[([^\\\]]|\\.)+])*\/[gimuy]*$/;
+const regex = /^\/([^\\[]|\\.|\[([^\\\]]|\\.)+])*\/[gimuys]*$/;
//------------------------------------------------------------------------------
// Rule Definition
@@ -36,7 +36,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-empty-character-class"
},
- schema: []
+ schema: [],
+
+ messages: {
+ unexpected: "Empty class."
+ }
},
create(context) {
@@ -48,7 +52,7 @@ module.exports = {
const token = sourceCode.getFirstToken(node);
if (token.type === "RegularExpression" && !regex.test(token.value)) {
- context.report({ node, message: "Empty class." });
+ context.report({ node, messageId: "unexpected" });
}
}
diff --git a/tools/node_modules/eslint/lib/rules/no-empty-function.js b/tools/node_modules/eslint/lib/rules/no-empty-function.js
index 3852774e6b..d9948cd4a3 100644
--- a/tools/node_modules/eslint/lib/rules/no-empty-function.js
+++ b/tools/node_modules/eslint/lib/rules/no-empty-function.js
@@ -109,7 +109,11 @@ module.exports = {
},
additionalProperties: false
}
- ]
+ ],
+
+ messages: {
+ unexpected: "Unexpected empty {{name}}."
+ }
},
create(context) {
@@ -146,7 +150,7 @@ module.exports = {
context.report({
node,
loc: node.body.loc.start,
- message: "Unexpected empty {{name}}.",
+ messageId: "unexpected",
data: { name }
});
}
diff --git a/tools/node_modules/eslint/lib/rules/no-empty-pattern.js b/tools/node_modules/eslint/lib/rules/no-empty-pattern.js
index 1d0c3ab4b1..939710560f 100644
--- a/tools/node_modules/eslint/lib/rules/no-empty-pattern.js
+++ b/tools/node_modules/eslint/lib/rules/no-empty-pattern.js
@@ -17,19 +17,23 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-empty-pattern"
},
- schema: []
+ schema: [],
+
+ messages: {
+ unexpected: "Unexpected empty {{type}} pattern."
+ }
},
create(context) {
return {
ObjectPattern(node) {
if (node.properties.length === 0) {
- context.report({ node, message: "Unexpected empty object pattern." });
+ context.report({ node, messageId: "unexpected", data: { type: "object" } });
}
},
ArrayPattern(node) {
if (node.elements.length === 0) {
- context.report({ node, message: "Unexpected empty array pattern." });
+ context.report({ node, messageId: "unexpected", data: { type: "array" } });
}
}
};
diff --git a/tools/node_modules/eslint/lib/rules/no-empty.js b/tools/node_modules/eslint/lib/rules/no-empty.js
index 15f1df6790..a598d40f8c 100644
--- a/tools/node_modules/eslint/lib/rules/no-empty.js
+++ b/tools/node_modules/eslint/lib/rules/no-empty.js
@@ -33,7 +33,11 @@ module.exports = {
},
additionalProperties: false
}
- ]
+ ],
+
+ messages: {
+ unexpected: "Empty {{type}} statement."
+ }
},
create(context) {
@@ -64,13 +68,13 @@ module.exports = {
return;
}
- context.report({ node, message: "Empty block statement." });
+ context.report({ node, messageId: "unexpected", data: { type: "block" } });
},
SwitchStatement(node) {
if (typeof node.cases === "undefined" || node.cases.length === 0) {
- context.report({ node, message: "Empty switch statement." });
+ context.report({ node, messageId: "unexpected", data: { type: "switch" } });
}
}
};
diff --git a/tools/node_modules/eslint/lib/rules/no-eq-null.js b/tools/node_modules/eslint/lib/rules/no-eq-null.js
index befb9d46f0..eadd16de37 100644
--- a/tools/node_modules/eslint/lib/rules/no-eq-null.js
+++ b/tools/node_modules/eslint/lib/rules/no-eq-null.js
@@ -19,7 +19,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-eq-null"
},
- schema: []
+ schema: [],
+
+ messages: {
+ unexpected: "Use '===' to compare with null."
+ }
},
create(context) {
@@ -31,7 +35,7 @@ module.exports = {
if (node.right.type === "Literal" && node.right.raw === "null" && badOperator ||
node.left.type === "Literal" && node.left.raw === "null" && badOperator) {
- context.report({ node, message: "Use ā€˜===ā€™ to compare with ā€˜nullā€™." });
+ context.report({ node, messageId: "unexpected" });
}
}
};
diff --git a/tools/node_modules/eslint/lib/rules/no-eval.js b/tools/node_modules/eslint/lib/rules/no-eval.js
index 8cf4aa307b..68ed086a3d 100644
--- a/tools/node_modules/eslint/lib/rules/no-eval.js
+++ b/tools/node_modules/eslint/lib/rules/no-eval.js
@@ -91,7 +91,11 @@ module.exports = {
},
additionalProperties: false
}
- ]
+ ],
+
+ messages: {
+ unexpected: "eval can be harmful."
+ }
},
create(context) {
@@ -147,20 +151,19 @@ module.exports = {
* @returns {void}
*/
function report(node) {
- let locationNode = node;
const parent = node.parent;
+ const locationNode = node.type === "MemberExpression"
+ ? node.property
+ : node;
- if (node.type === "MemberExpression") {
- locationNode = node.property;
- }
- if (parent.type === "CallExpression" && parent.callee === node) {
- node = parent;
- }
+ const reportNode = parent.type === "CallExpression" && parent.callee === node
+ ? parent
+ : node;
context.report({
- node,
+ node: reportNode,
loc: locationNode.loc.start,
- message: "eval can be harmful."
+ messageId: "unexpected"
});
}
diff --git a/tools/node_modules/eslint/lib/rules/no-ex-assign.js b/tools/node_modules/eslint/lib/rules/no-ex-assign.js
index 6ede2fc210..feace415e5 100644
--- a/tools/node_modules/eslint/lib/rules/no-ex-assign.js
+++ b/tools/node_modules/eslint/lib/rules/no-ex-assign.js
@@ -20,7 +20,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-ex-assign"
},
- schema: []
+ schema: [],
+
+ messages: {
+ unexpected: "Do not assign to the exception parameter."
+ }
},
create(context) {
@@ -32,7 +36,7 @@ module.exports = {
*/
function checkVariable(variable) {
astUtils.getModifyingReferences(variable.references).forEach(reference => {
- context.report({ node: reference.identifier, message: "Do not assign to the exception parameter." });
+ context.report({ node: reference.identifier, messageId: "unexpected" });
});
}
diff --git a/tools/node_modules/eslint/lib/rules/no-extend-native.js b/tools/node_modules/eslint/lib/rules/no-extend-native.js
index 2e170017a8..3ba13090a6 100644
--- a/tools/node_modules/eslint/lib/rules/no-extend-native.js
+++ b/tools/node_modules/eslint/lib/rules/no-extend-native.js
@@ -45,7 +45,11 @@ module.exports = {
},
additionalProperties: false
}
- ]
+ ],
+
+ messages: {
+ unexpected: "{{builtin}} prototype is read only, properties should not be added."
+ }
},
create(context) {
@@ -67,7 +71,7 @@ module.exports = {
function reportNode(node, builtin) {
context.report({
node,
- message: "{{builtin}} prototype is read only, properties should not be added.",
+ messageId: "unexpected",
data: {
builtin
}
diff --git a/tools/node_modules/eslint/lib/rules/no-extra-bind.js b/tools/node_modules/eslint/lib/rules/no-extra-bind.js
index 21b96c3c26..8d901808fd 100644
--- a/tools/node_modules/eslint/lib/rules/no-extra-bind.js
+++ b/tools/node_modules/eslint/lib/rules/no-extra-bind.js
@@ -25,7 +25,11 @@ module.exports = {
schema: [],
- fixable: "code"
+ fixable: "code",
+
+ messages: {
+ unexpected: "The function binding is unnecessary."
+ }
},
create(context) {
@@ -41,7 +45,7 @@ module.exports = {
function report(node) {
context.report({
node: node.parent.parent,
- message: "The function binding is unnecessary.",
+ messageId: "unexpected",
loc: node.parent.property.loc.start,
fix(fixer) {
const firstTokenToRemove = context.getSourceCode()
diff --git a/tools/node_modules/eslint/lib/rules/no-extra-boolean-cast.js b/tools/node_modules/eslint/lib/rules/no-extra-boolean-cast.js
index 471e8b5b82..3819136171 100644
--- a/tools/node_modules/eslint/lib/rules/no-extra-boolean-cast.js
+++ b/tools/node_modules/eslint/lib/rules/no-extra-boolean-cast.js
@@ -26,7 +26,12 @@ module.exports = {
schema: [],
- fixable: "code"
+ fixable: "code",
+
+ messages: {
+ unexpectedCall: "Redundant Boolean call.",
+ unexpectedNegation: "Redundant double negation."
+ }
},
create(context) {
@@ -82,7 +87,7 @@ module.exports = {
) {
context.report({
node,
- message: "Redundant double negation.",
+ messageId: "unexpectedNegation",
fix: fixer => fixer.replaceText(parent, sourceCode.getText(node.argument))
});
}
@@ -97,7 +102,7 @@ module.exports = {
if (isInBooleanContext(node, parent)) {
context.report({
node,
- message: "Redundant Boolean call.",
+ messageId: "unexpectedCall",
fix: fixer => {
if (!node.arguments.length) {
return fixer.replaceText(parent, "true");
diff --git a/tools/node_modules/eslint/lib/rules/no-extra-label.js b/tools/node_modules/eslint/lib/rules/no-extra-label.js
index f90a403cbf..73a3fea9c9 100644
--- a/tools/node_modules/eslint/lib/rules/no-extra-label.js
+++ b/tools/node_modules/eslint/lib/rules/no-extra-label.js
@@ -26,7 +26,11 @@ module.exports = {
schema: [],
- fixable: "code"
+ fixable: "code",
+
+ messages: {
+ unexpected: "This label '{{name}}' is unnecessary."
+ }
},
create(context) {
@@ -109,7 +113,7 @@ module.exports = {
if (info.breakable && info.label && info.label.name === labelNode.name) {
context.report({
node: labelNode,
- message: "This label '{{name}}' is unnecessary.",
+ messageId: "unexpected",
data: labelNode,
fix: fixer => fixer.removeRange([sourceCode.getFirstToken(node).range[1], labelNode.range[1]])
});
diff --git a/tools/node_modules/eslint/lib/rules/no-extra-parens.js b/tools/node_modules/eslint/lib/rules/no-extra-parens.js
index 4bf8f99500..9765dfa777 100644
--- a/tools/node_modules/eslint/lib/rules/no-extra-parens.js
+++ b/tools/node_modules/eslint/lib/rules/no-extra-parens.js
@@ -55,6 +55,10 @@ module.exports = {
maxItems: 2
}
]
+ },
+
+ messages: {
+ unexpected: "Gratuitous parentheses around expression."
}
},
@@ -163,12 +167,13 @@ module.exports = {
* @private
*/
function isInReturnStatement(node) {
- while (node) {
- if (node.type === "ReturnStatement" ||
- (node.type === "ArrowFunctionExpression" && node.body.type !== "BlockStatement")) {
+ for (let currentNode = node; currentNode; currentNode = currentNode.parent) {
+ if (
+ currentNode.type === "ReturnStatement" ||
+ (currentNode.type === "ArrowFunctionExpression" && currentNode.body.type !== "BlockStatement")
+ ) {
return true;
}
- node = node.parent;
}
return false;
@@ -312,7 +317,7 @@ module.exports = {
context.report({
node,
loc: leftParenToken.loc.start,
- message: "Gratuitous parentheses around expression.",
+ messageId: "unexpected",
fix(fixer) {
const parenthesizedSource = sourceCode.text.slice(leftParenToken.range[1], rightParenToken.range[0]);
diff --git a/tools/node_modules/eslint/lib/rules/no-extra-semi.js b/tools/node_modules/eslint/lib/rules/no-extra-semi.js
index 5668c7e095..a074108858 100644
--- a/tools/node_modules/eslint/lib/rules/no-extra-semi.js
+++ b/tools/node_modules/eslint/lib/rules/no-extra-semi.js
@@ -26,7 +26,11 @@ module.exports = {
},
fixable: "code",
- schema: []
+ schema: [],
+
+ messages: {
+ unexpected: "Unnecessary semicolon."
+ }
},
create(context) {
@@ -40,7 +44,7 @@ module.exports = {
function report(nodeOrToken) {
context.report({
node: nodeOrToken,
- message: "Unnecessary semicolon.",
+ messageId: "unexpected",
fix(fixer) {
/*
diff --git a/tools/node_modules/eslint/lib/rules/no-implicit-coercion.js b/tools/node_modules/eslint/lib/rules/no-implicit-coercion.js
index 7efab83935..1dd4d431d7 100644
--- a/tools/node_modules/eslint/lib/rules/no-implicit-coercion.js
+++ b/tools/node_modules/eslint/lib/rules/no-implicit-coercion.js
@@ -20,7 +20,6 @@ const ALLOWABLE_OPERATORS = ["~", "!!", "+", "*"];
* @returns {Object} The parsed and normalized option object.
*/
function parseOptions(options) {
- options = options || {};
return {
boolean: "boolean" in options ? Boolean(options.boolean) : true,
number: "number" in options ? Boolean(options.number) : true,
@@ -186,7 +185,7 @@ module.exports = {
},
create(context) {
- const options = parseOptions(context.options[0]);
+ const options = parseOptions(context.options[0] || {});
const sourceCode = context.getSourceCode();
/**
@@ -197,8 +196,6 @@ module.exports = {
* @returns {void}
*/
function report(node, recommendation, shouldFix) {
- shouldFix = typeof shouldFix === "undefined" ? true : shouldFix;
-
context.report({
node,
message: "use `{{recommendation}}` instead.",
@@ -233,7 +230,7 @@ module.exports = {
if (!operatorAllowed && options.boolean && isDoubleLogicalNegating(node)) {
const recommendation = `Boolean(${sourceCode.getText(node.argument.argument)})`;
- report(node, recommendation);
+ report(node, recommendation, true);
}
// ~foo.indexOf(bar)
@@ -249,7 +246,7 @@ module.exports = {
if (!operatorAllowed && options.number && node.operator === "+" && !isNumeric(node.argument)) {
const recommendation = `Number(${sourceCode.getText(node.argument)})`;
- report(node, recommendation);
+ report(node, recommendation, true);
}
},
@@ -264,7 +261,7 @@ module.exports = {
if (nonNumericOperand) {
const recommendation = `Number(${sourceCode.getText(nonNumericOperand)})`;
- report(node, recommendation);
+ report(node, recommendation, true);
}
// "" + foo
@@ -272,7 +269,7 @@ module.exports = {
if (!operatorAllowed && options.string && isConcatWithEmptyString(node)) {
const recommendation = `String(${sourceCode.getText(getNonEmptyOperand(node))})`;
- report(node, recommendation);
+ report(node, recommendation, true);
}
},
@@ -285,7 +282,7 @@ module.exports = {
const code = sourceCode.getText(getNonEmptyOperand(node));
const recommendation = `${code} = String(${code})`;
- report(node, recommendation);
+ report(node, recommendation, true);
}
}
};
diff --git a/tools/node_modules/eslint/lib/rules/no-invalid-regexp.js b/tools/node_modules/eslint/lib/rules/no-invalid-regexp.js
index 8ccb5242b0..7169e0ca77 100644
--- a/tools/node_modules/eslint/lib/rules/no-invalid-regexp.js
+++ b/tools/node_modules/eslint/lib/rules/no-invalid-regexp.js
@@ -8,7 +8,10 @@
// Requirements
//------------------------------------------------------------------------------
-const espree = require("espree");
+const RegExpValidator = require("regexpp").RegExpValidator;
+const validator = new RegExpValidator({ ecmaVersion: 2018 });
+const validFlags = /[gimuys]/g;
+const undefined1 = void 0;
//------------------------------------------------------------------------------
// Rule Definition
@@ -40,10 +43,14 @@ module.exports = {
create(context) {
const options = context.options[0];
- let allowedFlags = "";
+ let allowedFlags = null;
if (options && options.allowConstructorFlags) {
- allowedFlags = options.allowConstructorFlags.join("");
+ const temp = options.allowConstructorFlags.join("").replace(validFlags, "");
+
+ if (temp) {
+ allowedFlags = new RegExp(`[${temp}]`, "gi");
+ }
}
/**
@@ -57,51 +64,61 @@ module.exports = {
}
/**
- * Validate strings passed to the RegExp constructor
- * @param {ASTNode} node node to evaluate
- * @returns {void}
- * @private
+ * Check syntax error in a given pattern.
+ * @param {string} pattern The RegExp pattern to validate.
+ * @param {boolean} uFlag The Unicode flag.
+ * @returns {string|null} The syntax error.
+ */
+ function validateRegExpPattern(pattern, uFlag) {
+ try {
+ validator.validatePattern(pattern, undefined1, undefined1, uFlag);
+ return null;
+ } catch (err) {
+ return err.message;
+ }
+ }
+
+ /**
+ * Check syntax error in a given flags.
+ * @param {string} flags The RegExp flags to validate.
+ * @returns {string|null} The syntax error.
*/
- function check(node) {
- if (node.callee.type === "Identifier" && node.callee.name === "RegExp" && isString(node.arguments[0])) {
+ function validateRegExpFlags(flags) {
+ try {
+ validator.validateFlags(flags);
+ return null;
+ } catch (err) {
+ return `Invalid flags supplied to RegExp constructor '${flags}'`;
+ }
+ }
+
+ return {
+ "CallExpression, NewExpression"(node) {
+ if (node.callee.type !== "Identifier" || node.callee.name !== "RegExp" || !isString(node.arguments[0])) {
+ return;
+ }
+ const pattern = node.arguments[0].value;
let flags = isString(node.arguments[1]) ? node.arguments[1].value : "";
if (allowedFlags) {
- flags = flags.replace(new RegExp(`[${allowedFlags}]`, "gi"), "");
+ flags = flags.replace(allowedFlags, "");
}
- try {
- void new RegExp(node.arguments[0].value);
- } catch (e) {
+ // If flags are unknown, check both are errored or not.
+ const message = validateRegExpFlags(flags) || (
+ flags
+ ? validateRegExpPattern(pattern, flags.indexOf("u") !== -1)
+ : validateRegExpPattern(pattern, true) && validateRegExpPattern(pattern, false)
+ );
+
+ if (message) {
context.report({
node,
message: "{{message}}.",
- data: e
+ data: { message }
});
}
-
- if (flags) {
-
- try {
- espree.parse(`/./${flags}`, context.parserOptions);
- } catch (ex) {
- context.report({
- node,
- message: "Invalid flags supplied to RegExp constructor '{{flags}}'.",
- data: {
- flags
- }
- });
- }
- }
-
}
- }
-
- return {
- CallExpression: check,
- NewExpression: check
};
-
}
};
diff --git a/tools/node_modules/eslint/lib/rules/no-irregular-whitespace.js b/tools/node_modules/eslint/lib/rules/no-irregular-whitespace.js
index e36ec88b01..f1840aaf2d 100644
--- a/tools/node_modules/eslint/lib/rules/no-irregular-whitespace.js
+++ b/tools/node_modules/eslint/lib/rules/no-irregular-whitespace.js
@@ -101,7 +101,7 @@ module.exports = {
*/
function removeInvalidNodeErrorsInIdentifierOrLiteral(node) {
const shouldCheckStrings = skipStrings && (typeof node.value === "string");
- const shouldCheckRegExps = skipRegExps && (node.value instanceof RegExp);
+ const shouldCheckRegExps = skipRegExps && Boolean(node.regex);
if (shouldCheckStrings || shouldCheckRegExps) {
diff --git a/tools/node_modules/eslint/lib/rules/no-loop-func.js b/tools/node_modules/eslint/lib/rules/no-loop-func.js
index 0dce09a61a..d103cb5335 100644
--- a/tools/node_modules/eslint/lib/rules/no-loop-func.js
+++ b/tools/node_modules/eslint/lib/rules/no-loop-func.js
@@ -20,9 +20,9 @@
* `null`.
*/
function getContainingLoopNode(node) {
- let parent = node.parent;
+ for (let currentNode = node; currentNode.parent; currentNode = currentNode.parent) {
+ const parent = currentNode.parent;
- while (parent) {
switch (parent.type) {
case "WhileStatement":
case "DoWhileStatement":
@@ -31,7 +31,7 @@ function getContainingLoopNode(node) {
case "ForStatement":
// `init` is outside of the loop.
- if (parent.init !== node) {
+ if (parent.init !== currentNode) {
return parent;
}
break;
@@ -40,7 +40,7 @@ function getContainingLoopNode(node) {
case "ForOfStatement":
// `right` is outside of the loop.
- if (parent.right !== node) {
+ if (parent.right !== currentNode) {
return parent;
}
break;
@@ -55,9 +55,6 @@ function getContainingLoopNode(node) {
default:
break;
}
-
- node = parent;
- parent = node.parent;
}
return null;
@@ -73,12 +70,13 @@ function getContainingLoopNode(node) {
* @returns {ASTNode} The most outer loop node.
*/
function getTopLoopNode(node, excludedNode) {
- let retv = node;
const border = excludedNode ? excludedNode.range[1] : 0;
+ let retv = node;
+ let containingLoopNode = node;
- while (node && node.range[0] >= border) {
- retv = node;
- node = getContainingLoopNode(node);
+ while (containingLoopNode && containingLoopNode.range[0] >= border) {
+ retv = containingLoopNode;
+ containingLoopNode = getContainingLoopNode(containingLoopNode);
}
return retv;
diff --git a/tools/node_modules/eslint/lib/rules/no-magic-numbers.js b/tools/node_modules/eslint/lib/rules/no-magic-numbers.js
index 20a752e554..2826dbf493 100644
--- a/tools/node_modules/eslint/lib/rules/no-magic-numbers.js
+++ b/tools/node_modules/eslint/lib/rules/no-magic-numbers.js
@@ -101,25 +101,32 @@ module.exports = {
return {
Literal(node) {
- let parent = node.parent,
- value = node.value,
- raw = node.raw;
const okTypes = detectObjects ? [] : ["ObjectExpression", "Property", "AssignmentExpression"];
if (!isNumber(node)) {
return;
}
+ let fullNumberNode;
+ let parent;
+ let value;
+ let raw;
+
// For negative magic numbers: update the value and parent node
- if (parent.type === "UnaryExpression" && parent.operator === "-") {
- node = parent;
+ if (node.parent.type === "UnaryExpression" && node.parent.operator === "-") {
+ fullNumberNode = node.parent;
+ parent = fullNumberNode.parent;
+ value = -node.value;
+ raw = `-${node.raw}`;
+ } else {
+ fullNumberNode = node;
parent = node.parent;
- value = -value;
- raw = `-${raw}`;
+ value = node.value;
+ raw = node.raw;
}
if (shouldIgnoreNumber(value) ||
- shouldIgnoreParseInt(parent, node) ||
+ shouldIgnoreParseInt(parent, fullNumberNode) ||
shouldIgnoreArrayIndexes(parent) ||
shouldIgnoreJSXNumbers(parent)) {
return;
@@ -128,7 +135,7 @@ module.exports = {
if (parent.type === "VariableDeclarator") {
if (enforceConst && parent.parent.kind !== "const") {
context.report({
- node,
+ node: fullNumberNode,
message: "Number constants declarations must use 'const'."
});
}
@@ -137,7 +144,7 @@ module.exports = {
(parent.type === "AssignmentExpression" && parent.left.type === "Identifier")
) {
context.report({
- node,
+ node: fullNumberNode,
message: "No magic number: {{raw}}.",
data: {
raw
diff --git a/tools/node_modules/eslint/lib/rules/no-return-assign.js b/tools/node_modules/eslint/lib/rules/no-return-assign.js
index 0a016cfad5..ca96da9f2f 100644
--- a/tools/node_modules/eslint/lib/rules/no-return-assign.js
+++ b/tools/node_modules/eslint/lib/rules/no-return-assign.js
@@ -46,11 +46,12 @@ module.exports = {
return;
}
- let parent = node.parent;
+ let currentChild = node;
+ let parent = currentChild.parent;
// Find ReturnStatement or ArrowFunctionExpression in ancestors.
while (parent && !SENTINEL_TYPE.test(parent.type)) {
- node = parent;
+ currentChild = parent;
parent = parent.parent;
}
@@ -60,7 +61,7 @@ module.exports = {
node: parent,
message: "Return statement should not contain assignment."
});
- } else if (parent && parent.type === "ArrowFunctionExpression" && parent.body === node) {
+ } else if (parent && parent.type === "ArrowFunctionExpression" && parent.body === currentChild) {
context.report({
node: parent,
message: "Arrow function should not return assignment."
diff --git a/tools/node_modules/eslint/lib/rules/no-self-assign.js b/tools/node_modules/eslint/lib/rules/no-self-assign.js
index 3014042002..8091d7d2e5 100644
--- a/tools/node_modules/eslint/lib/rules/no-self-assign.js
+++ b/tools/node_modules/eslint/lib/rules/no-self-assign.js
@@ -121,7 +121,9 @@ function eachSelfAssignment(left, right, props, report) {
let startJ = 0;
for (let i = right.properties.length - 1; i >= 0; --i) {
- if (right.properties[i].type === "ExperimentalSpreadProperty") {
+ const propType = right.properties[i].type;
+
+ if (propType === "SpreadElement" || propType === "ExperimentalSpreadProperty") {
startJ = i + 1;
break;
}
diff --git a/tools/node_modules/eslint/lib/rules/no-unexpected-multiline.js b/tools/node_modules/eslint/lib/rules/no-unexpected-multiline.js
index c7c26686d9..51ba7cfa75 100644
--- a/tools/node_modules/eslint/lib/rules/no-unexpected-multiline.js
+++ b/tools/node_modules/eslint/lib/rules/no-unexpected-multiline.js
@@ -33,7 +33,7 @@ module.exports = {
const TAGGED_TEMPLATE_MESSAGE = "Unexpected newline between template tag and template literal.";
const DIVISION_MESSAGE = "Unexpected newline between numerator and division operator.";
- const REGEX_FLAG_MATCHER = /^[gimuy]+$/;
+ const REGEX_FLAG_MATCHER = /^[gimsuy]+$/;
const sourceCode = context.getSourceCode();
diff --git a/tools/node_modules/eslint/lib/rules/no-unsafe-finally.js b/tools/node_modules/eslint/lib/rules/no-unsafe-finally.js
index ebef05188f..1ebdd2e377 100644
--- a/tools/node_modules/eslint/lib/rules/no-unsafe-finally.js
+++ b/tools/node_modules/eslint/lib/rules/no-unsafe-finally.js
@@ -60,17 +60,20 @@ module.exports = {
sentinelNodeType = SENTINEL_NODE_TYPE_RETURN_THROW;
}
- while (node && !sentinelNodeType.test(node.type)) {
- if (node.parent.label && label && (node.parent.label.name === label.name)) {
+ for (
+ let currentNode = node;
+ currentNode && !sentinelNodeType.test(currentNode.type);
+ currentNode = currentNode.parent
+ ) {
+ if (currentNode.parent.label && label && (currentNode.parent.label.name === label.name)) {
labelInside = true;
}
- if (isFinallyBlock(node)) {
+ if (isFinallyBlock(currentNode)) {
if (label && labelInside) {
return false;
}
return true;
}
- node = node.parent;
}
return false;
}
diff --git a/tools/node_modules/eslint/lib/rules/no-unused-vars.js b/tools/node_modules/eslint/lib/rules/no-unused-vars.js
index 1d0cef8562..6ba5734986 100644
--- a/tools/node_modules/eslint/lib/rules/no-unused-vars.js
+++ b/tools/node_modules/eslint/lib/rules/no-unused-vars.js
@@ -65,7 +65,7 @@ module.exports = {
create(context) {
const sourceCode = context.getSourceCode();
- const REST_PROPERTY_TYPE = /^(?:Experimental)?RestProperty$/;
+ const REST_PROPERTY_TYPE = /^(?:RestElement|(?:Experimental)?RestProperty)$/;
const config = {
vars: "all",
diff --git a/tools/node_modules/eslint/lib/rules/no-useless-escape.js b/tools/node_modules/eslint/lib/rules/no-useless-escape.js
index 80abec78e8..efc9706f41 100644
--- a/tools/node_modules/eslint/lib/rules/no-useless-escape.js
+++ b/tools/node_modules/eslint/lib/rules/no-useless-escape.js
@@ -25,8 +25,8 @@ function union(setA, setB) {
}
const VALID_STRING_ESCAPES = union(new Set("\\nrvtbfux"), astUtils.LINEBREAKS);
-const REGEX_GENERAL_ESCAPES = new Set("\\bcdDfnrsStvwWxu0123456789]");
-const REGEX_NON_CHARCLASS_ESCAPES = union(REGEX_GENERAL_ESCAPES, new Set("^/.$*+?[{}|()B"));
+const REGEX_GENERAL_ESCAPES = new Set("\\bcdDfnpPrsStvwWxu0123456789]");
+const REGEX_NON_CHARCLASS_ESCAPES = union(REGEX_GENERAL_ESCAPES, new Set("^/.$*+?[{}|()Bk"));
/**
* Parses a regular expression into a list of characters with character class info.
diff --git a/tools/node_modules/eslint/lib/rules/no-useless-return.js b/tools/node_modules/eslint/lib/rules/no-useless-return.js
index 8e2a6d97f6..d801c0e465 100644
--- a/tools/node_modules/eslint/lib/rules/no-useless-return.js
+++ b/tools/node_modules/eslint/lib/rules/no-useless-return.js
@@ -56,12 +56,14 @@ function isRemovable(node) {
* @returns {boolean} `true` if the node is in a `finally` block.
*/
function isInFinally(node) {
- while (node && node.parent && !astUtils.isFunction(node)) {
- if (node.parent.type === "TryStatement" && node.parent.finalizer === node) {
+ for (
+ let currentNode = node;
+ currentNode && currentNode.parent && !astUtils.isFunction(currentNode);
+ currentNode = currentNode.parent
+ ) {
+ if (currentNode.parent.type === "TryStatement" && currentNode.parent.finalizer === currentNode) {
return true;
}
-
- node = node.parent;
}
return false;
@@ -116,13 +118,12 @@ module.exports = {
*
* @param {ASTNode[]} uselessReturns - The collected return statements.
* @param {CodePathSegment[]} prevSegments - The previous segments to traverse.
- * @param {WeakSet<CodePathSegment>} [traversedSegments] A set of segments that have already been traversed in this call
+ * @param {WeakSet<CodePathSegment>} [providedTraversedSegments] A set of segments that have already been traversed in this call
* @returns {ASTNode[]} `uselessReturns`.
*/
- function getUselessReturns(uselessReturns, prevSegments, traversedSegments) {
- if (!traversedSegments) {
- traversedSegments = new WeakSet();
- }
+ function getUselessReturns(uselessReturns, prevSegments, providedTraversedSegments) {
+ const traversedSegments = providedTraversedSegments || new WeakSet();
+
for (const segment of prevSegments) {
if (!segment.reachable) {
if (!traversedSegments.has(segment)) {
diff --git a/tools/node_modules/eslint/lib/rules/no-var.js b/tools/node_modules/eslint/lib/rules/no-var.js
index d95ca539f0..5ca868e65a 100644
--- a/tools/node_modules/eslint/lib/rules/no-var.js
+++ b/tools/node_modules/eslint/lib/rules/no-var.js
@@ -33,10 +33,12 @@ function isGlobal(variable) {
* scope.
*/
function getEnclosingFunctionScope(scope) {
- while (scope.type !== "function" && scope.type !== "global") {
- scope = scope.upper;
+ let currentScope = scope;
+
+ while (currentScope.type !== "function" && currentScope.type !== "global") {
+ currentScope = currentScope.upper;
}
- return scope;
+ return currentScope;
}
/**
@@ -87,12 +89,10 @@ const SCOPE_NODE_TYPE = /^(?:Program|BlockStatement|SwitchStatement|ForStatement
* `ForOfStatement`.
*/
function getScopeNode(node) {
- while (node) {
- if (SCOPE_NODE_TYPE.test(node.type)) {
- return node;
+ for (let currentNode = node; currentNode; currentNode = currentNode.parent) {
+ if (SCOPE_NODE_TYPE.test(currentNode.type)) {
+ return currentNode;
}
-
- node = node.parent;
}
/* istanbul ignore next : unreachable */
diff --git a/tools/node_modules/eslint/lib/rules/object-curly-newline.js b/tools/node_modules/eslint/lib/rules/object-curly-newline.js
index 91b2ca6c97..39043a8b9b 100644
--- a/tools/node_modules/eslint/lib/rules/object-curly-newline.js
+++ b/tools/node_modules/eslint/lib/rules/object-curly-newline.js
@@ -10,6 +10,7 @@
//------------------------------------------------------------------------------
const astUtils = require("../ast-utils");
+const lodash = require("lodash");
//------------------------------------------------------------------------------
// Helpers
@@ -73,19 +74,58 @@ function normalizeOptionValue(value) {
* Normalizes a given option value.
*
* @param {string|Object|undefined} options - An option value to parse.
- * @returns {{ObjectExpression: {multiline: boolean, minProperties: number}, ObjectPattern: {multiline: boolean, minProperties: number}}} Normalized option object.
+ * @returns {{
+ * ObjectExpression: {multiline: boolean, minProperties: number, consistent: boolean},
+ * ObjectPattern: {multiline: boolean, minProperties: number, consistent: boolean},
+ * ImportDeclaration: {multiline: boolean, minProperties: number, consistent: boolean},
+ * ExportNamedDeclaration : {multiline: boolean, minProperties: number, consistent: boolean}
+ * }} Normalized option object.
*/
function normalizeOptions(options) {
- if (options && (options.ObjectExpression || options.ObjectPattern)) {
+ const isNodeSpecificOption = lodash.overSome([lodash.isPlainObject, lodash.isString]);
+
+ if (lodash.isPlainObject(options) && lodash.some(options, isNodeSpecificOption)) {
return {
ObjectExpression: normalizeOptionValue(options.ObjectExpression),
- ObjectPattern: normalizeOptionValue(options.ObjectPattern)
+ ObjectPattern: normalizeOptionValue(options.ObjectPattern),
+ ImportDeclaration: normalizeOptionValue(options.ImportDeclaration),
+ ExportNamedDeclaration: normalizeOptionValue(options.ExportDeclaration)
};
}
const value = normalizeOptionValue(options);
- return { ObjectExpression: value, ObjectPattern: value };
+ return { ObjectExpression: value, ObjectPattern: value, ImportDeclaration: value, ExportNamedDeclaration: value };
+}
+
+/**
+ * Determines if ObjectExpression, ObjectPattern, ImportDeclaration or ExportNamedDeclaration
+ * node needs to be checked for missing line breaks
+ *
+ * @param {ASTNode} node - Node under inspection
+ * @param {Object} options - option specific to node type
+ * @param {Token} first - First object property
+ * @param {Token} last - Last object property
+ * @returns {boolean} `true` if node needs to be checked for missing line breaks
+ */
+function areLineBreaksRequired(node, options, first, last) {
+ let objectProperties;
+
+ if (node.type === "ObjectExpression" || node.type === "ObjectPattern") {
+ objectProperties = node.properties;
+ } else {
+
+ // is ImportDeclaration or ExportNamedDeclaration
+ objectProperties = node.specifiers
+ .filter(s => s.type === "ImportSpecifier" || s.type === "ExportSpecifier");
+ }
+
+ return objectProperties.length >= options.minProperties ||
+ (
+ options.multiline &&
+ objectProperties.length > 0 &&
+ first.loc.start.line !== last.loc.end.line
+ );
}
//------------------------------------------------------------------------------
@@ -109,7 +149,9 @@ module.exports = {
type: "object",
properties: {
ObjectExpression: OPTION_VALUE,
- ObjectPattern: OPTION_VALUE
+ ObjectPattern: OPTION_VALUE,
+ ImportDeclaration: OPTION_VALUE,
+ ExportDeclaration: OPTION_VALUE
},
additionalProperties: false,
minProperties: 1
@@ -125,32 +167,37 @@ module.exports = {
/**
* Reports a given node if it violated this rule.
- *
- * @param {ASTNode} node - A node to check. This is an ObjectExpression node or an ObjectPattern node.
- * @param {{multiline: boolean, minProperties: number}} options - An option object.
+ * @param {ASTNode} node - A node to check. This is an ObjectExpression, ObjectPattern, ImportDeclaration or ExportNamedDeclaration node.
+ * @param {{multiline: boolean, minProperties: number, consistent: boolean}} options - An option object.
* @returns {void}
*/
function check(node) {
const options = normalizedOptions[node.type];
+
+ if (
+ (node.type === "ImportDeclaration" &&
+ !node.specifiers.some(specifier => specifier.type === "ImportSpecifier")) ||
+ (node.type === "ExportNamedDeclaration" &&
+ !node.specifiers.some(specifier => specifier.type === "ExportSpecifier"))
+ ) {
+ return;
+ }
+
const openBrace = sourceCode.getFirstToken(node, token => token.value === "{");
+
let closeBrace;
if (node.typeAnnotation) {
closeBrace = sourceCode.getTokenBefore(node.typeAnnotation);
} else {
- closeBrace = sourceCode.getLastToken(node);
+ closeBrace = sourceCode.getLastToken(node, token => token.value === "}");
}
let first = sourceCode.getTokenAfter(openBrace, { includeComments: true });
let last = sourceCode.getTokenBefore(closeBrace, { includeComments: true });
- const needsLinebreaks = (
- node.properties.length >= options.minProperties ||
- (
- options.multiline &&
- node.properties.length > 0 &&
- first.loc.start.line !== last.loc.end.line
- )
- );
+
+ const needsLineBreaks = areLineBreaksRequired(node, options, first, last);
+
const hasCommentsFirstToken = astUtils.isCommentToken(first);
const hasCommentsLastToken = astUtils.isCommentToken(last);
@@ -165,7 +212,7 @@ module.exports = {
first = sourceCode.getTokenAfter(openBrace);
last = sourceCode.getTokenBefore(closeBrace);
- if (needsLinebreaks) {
+ if (needsLineBreaks) {
if (astUtils.isTokenOnSameLine(openBrace, first)) {
context.report({
message: "Expected a line break after this opening brace.",
@@ -244,7 +291,9 @@ module.exports = {
return {
ObjectExpression: check,
- ObjectPattern: check
+ ObjectPattern: check,
+ ImportDeclaration: check,
+ ExportNamedDeclaration: check
};
}
};
diff --git a/tools/node_modules/eslint/lib/rules/object-property-newline.js b/tools/node_modules/eslint/lib/rules/object-property-newline.js
index 56ca269402..65baf0a95e 100644
--- a/tools/node_modules/eslint/lib/rules/object-property-newline.js
+++ b/tools/node_modules/eslint/lib/rules/object-property-newline.js
@@ -22,7 +22,10 @@ module.exports = {
{
type: "object",
properties: {
- allowMultiplePropertiesPerLine: {
+ allowAllPropertiesOnSameLine: {
+ type: "boolean"
+ },
+ allowMultiplePropertiesPerLine: { // Deprecated
type: "boolean"
}
},
@@ -34,7 +37,10 @@ module.exports = {
},
create(context) {
- const allowSameLine = context.options[0] && Boolean(context.options[0].allowMultiplePropertiesPerLine);
+ const allowSameLine = context.options[0] && (
+ Boolean(context.options[0].allowAllPropertiesOnSameLine) ||
+ Boolean(context.options[0].allowMultiplePropertiesPerLine) // Deprecated
+ );
const errorMessage = allowSameLine
? "Object properties must go on a new line if they aren't all on the same line."
: "Object properties must go on a new line.";
diff --git a/tools/node_modules/eslint/lib/rules/object-shorthand.js b/tools/node_modules/eslint/lib/rules/object-shorthand.js
index c6c0b10445..c5239a71d1 100644
--- a/tools/node_modules/eslint/lib/rules/object-shorthand.js
+++ b/tools/node_modules/eslint/lib/rules/object-shorthand.js
@@ -131,7 +131,7 @@ module.exports = {
*
*/
function canHaveShorthand(property) {
- return (property.kind !== "set" && property.kind !== "get" && property.type !== "SpreadProperty" && property.type !== "ExperimentalSpreadProperty");
+ return (property.kind !== "set" && property.kind !== "get" && property.type !== "SpreadElement" && property.type !== "SpreadProperty" && property.type !== "ExperimentalSpreadProperty");
}
/**
@@ -233,10 +233,11 @@ module.exports = {
const keyText = sourceCode.text.slice(firstKeyToken.range[0], lastKeyToken.range[1]);
let keyPrefix = "";
+ if (node.value.async) {
+ keyPrefix += "async ";
+ }
if (node.value.generator) {
- keyPrefix = "*";
- } else if (node.value.async) {
- keyPrefix = "async ";
+ keyPrefix += "*";
}
if (node.value.type === "FunctionExpression") {
@@ -273,10 +274,11 @@ module.exports = {
const keyText = sourceCode.text.slice(firstKeyToken.range[0], lastKeyToken.range[1]);
let functionHeader = "function";
+ if (node.value.async) {
+ functionHeader = `async ${functionHeader}`;
+ }
if (node.value.generator) {
- functionHeader = "function*";
- } else if (node.value.async) {
- functionHeader = "async function";
+ functionHeader = `${functionHeader}*`;
}
return fixer.replaceTextRange([node.range[0], lastKeyToken.range[1]], `${keyText}: ${functionHeader}`);
diff --git a/tools/node_modules/eslint/lib/rules/one-var.js b/tools/node_modules/eslint/lib/rules/one-var.js
index cd094444b6..40b5f0f0aa 100644
--- a/tools/node_modules/eslint/lib/rules/one-var.js
+++ b/tools/node_modules/eslint/lib/rules/one-var.js
@@ -22,7 +22,7 @@ module.exports = {
{
oneOf: [
{
- enum: ["always", "never"]
+ enum: ["always", "never", "consecutive"]
},
{
type: "object",
@@ -31,13 +31,13 @@ module.exports = {
type: "boolean"
},
var: {
- enum: ["always", "never"]
+ enum: ["always", "never", "consecutive"]
},
let: {
- enum: ["always", "never"]
+ enum: ["always", "never", "consecutive"]
},
const: {
- enum: ["always", "never"]
+ enum: ["always", "never", "consecutive"]
}
},
additionalProperties: false
@@ -46,10 +46,10 @@ module.exports = {
type: "object",
properties: {
initialized: {
- enum: ["always", "never"]
+ enum: ["always", "never", "consecutive"]
},
uninitialized: {
- enum: ["always", "never"]
+ enum: ["always", "never", "consecutive"]
}
},
additionalProperties: false
@@ -60,10 +60,9 @@ module.exports = {
},
create(context) {
-
- const MODE_ALWAYS = "always",
- MODE_NEVER = "never";
-
+ const MODE_ALWAYS = "always";
+ const MODE_NEVER = "never";
+ const MODE_CONSECUTIVE = "consecutive";
const mode = context.options[0] || MODE_ALWAYS;
const options = {};
@@ -273,119 +272,163 @@ module.exports = {
return true;
}
+ /**
+ * Checks a given VariableDeclaration node for errors.
+ * @param {ASTNode} node The VariableDeclaration node to check
+ * @returns {void}
+ * @private
+ */
+ function checkVariableDeclaration(node) {
+ const parent = node.parent;
+ const type = node.kind;
- //--------------------------------------------------------------------------
- // Public API
- //--------------------------------------------------------------------------
+ if (!options[type]) {
+ return;
+ }
- return {
- Program: startFunction,
- FunctionDeclaration: startFunction,
- FunctionExpression: startFunction,
- ArrowFunctionExpression: startFunction,
- BlockStatement: startBlock,
- ForStatement: startBlock,
- ForInStatement: startBlock,
- ForOfStatement: startBlock,
- SwitchStatement: startBlock,
+ const declarations = node.declarations;
+ const declarationCounts = countDeclarations(declarations);
+ const mixedRequires = declarations.some(isRequire) && !declarations.every(isRequire);
+
+ if (options[type].initialized === MODE_ALWAYS) {
+ if (options.separateRequires && mixedRequires) {
+ context.report({
+ node,
+ message: "Split requires to be separated into a single block."
+ });
+ }
+ }
- VariableDeclaration(node) {
- const parent = node.parent;
- const type = node.kind;
+ // consecutive
+ const nodeIndex = (parent.body && parent.body.length > 0 && parent.body.indexOf(node)) || 0;
- if (!options[type]) {
- return;
- }
+ if (nodeIndex > 0) {
+ const previousNode = parent.body[nodeIndex - 1];
+ const isPreviousNodeDeclaration = previousNode.type === "VariableDeclaration";
- const declarations = node.declarations;
- const declarationCounts = countDeclarations(declarations);
- const mixedRequires = declarations.some(isRequire) && !declarations.every(isRequire);
+ if (isPreviousNodeDeclaration && previousNode.kind === type) {
+ const previousDeclCounts = countDeclarations(previousNode.declarations);
- if (options[type].initialized === MODE_ALWAYS) {
- if (options.separateRequires && mixedRequires) {
+ if (options[type].initialized === MODE_CONSECUTIVE && options[type].uninitialized === MODE_CONSECUTIVE) {
+ context.report({
+ node,
+ message: "Combine this with the previous '{{type}}' statement.",
+ data: {
+ type
+ }
+ });
+ } else if (options[type].initialized === MODE_CONSECUTIVE && declarationCounts.initialized > 0 && previousDeclCounts.initialized > 0) {
context.report({
node,
- message: "Split requires to be separated into a single block."
+ message: "Combine this with the previous '{{type}}' statement with initialized variables.",
+ data: {
+ type
+ }
+ });
+ } else if (options[type].uninitialized === MODE_CONSECUTIVE &&
+ declarationCounts.uninitialized > 0 &&
+ previousDeclCounts.uninitialized > 0) {
+ context.report({
+ node,
+ message: "Combine this with the previous '{{type}}' statement with uninitialized variables.",
+ data: {
+ type
+ }
});
}
}
+ }
- // always
- if (!hasOnlyOneStatement(type, declarations)) {
- if (options[type].initialized === MODE_ALWAYS && options[type].uninitialized === MODE_ALWAYS) {
+ // always
+ if (!hasOnlyOneStatement(type, declarations)) {
+ if (options[type].initialized === MODE_ALWAYS && options[type].uninitialized === MODE_ALWAYS) {
+ context.report({
+ node,
+ message: "Combine this with the previous '{{type}}' statement.",
+ data: {
+ type
+ }
+ });
+ } else {
+ if (options[type].initialized === MODE_ALWAYS && declarationCounts.initialized > 0) {
context.report({
node,
- message: "Combine this with the previous '{{type}}' statement.",
+ message: "Combine this with the previous '{{type}}' statement with initialized variables.",
data: {
type
}
});
- } else {
- if (options[type].initialized === MODE_ALWAYS) {
- context.report({
- node,
- message: "Combine this with the previous '{{type}}' statement with initialized variables.",
- data: {
- type
- }
- });
+ }
+ if (options[type].uninitialized === MODE_ALWAYS && declarationCounts.uninitialized > 0) {
+ if (node.parent.left === node && (node.parent.type === "ForInStatement" || node.parent.type === "ForOfStatement")) {
+ return;
}
- if (options[type].uninitialized === MODE_ALWAYS) {
- if (node.parent.left === node && (node.parent.type === "ForInStatement" || node.parent.type === "ForOfStatement")) {
- return;
+ context.report({
+ node,
+ message: "Combine this with the previous '{{type}}' statement with uninitialized variables.",
+ data: {
+ type
}
- context.report({
- node,
- message: "Combine this with the previous '{{type}}' statement with uninitialized variables.",
- data: {
- type
- }
- });
- }
+ });
}
}
+ }
- // never
- if (parent.type !== "ForStatement" || parent.init !== node) {
- const totalDeclarations = declarationCounts.uninitialized + declarationCounts.initialized;
-
- if (totalDeclarations > 1) {
-
- if (options[type].initialized === MODE_NEVER && options[type].uninitialized === MODE_NEVER) {
-
- // both initialized and uninitialized
- context.report({
- node,
- message: "Split '{{type}}' declarations into multiple statements.",
- data: {
- type
- }
- });
- } else if (options[type].initialized === MODE_NEVER && declarationCounts.initialized > 0) {
-
- // initialized
- context.report({
- node,
- message: "Split initialized '{{type}}' declarations into multiple statements.",
- data: {
- type
- }
- });
- } else if (options[type].uninitialized === MODE_NEVER && declarationCounts.uninitialized > 0) {
-
- // uninitialized
- context.report({
- node,
- message: "Split uninitialized '{{type}}' declarations into multiple statements.",
- data: {
- type
- }
- });
- }
+ // never
+ if (parent.type !== "ForStatement" || parent.init !== node) {
+ const totalDeclarations = declarationCounts.uninitialized + declarationCounts.initialized;
+
+ if (totalDeclarations > 1) {
+ if (options[type].initialized === MODE_NEVER && options[type].uninitialized === MODE_NEVER) {
+
+ // both initialized and uninitialized
+ context.report({
+ node,
+ message: "Split '{{type}}' declarations into multiple statements.",
+ data: {
+ type
+ }
+ });
+ } else if (options[type].initialized === MODE_NEVER && declarationCounts.initialized > 0) {
+
+ // initialized
+ context.report({
+ node,
+ message: "Split initialized '{{type}}' declarations into multiple statements.",
+ data: {
+ type
+ }
+ });
+ } else if (options[type].uninitialized === MODE_NEVER && declarationCounts.uninitialized > 0) {
+
+ // uninitialized
+ context.report({
+ node,
+ message: "Split uninitialized '{{type}}' declarations into multiple statements.",
+ data: {
+ type
+ }
+ });
}
}
- },
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ // Public API
+ //--------------------------------------------------------------------------
+ return {
+ Program: startFunction,
+ FunctionDeclaration: startFunction,
+ FunctionExpression: startFunction,
+ ArrowFunctionExpression: startFunction,
+ BlockStatement: startBlock,
+ ForStatement: startBlock,
+ ForInStatement: startBlock,
+ ForOfStatement: startBlock,
+ SwitchStatement: startBlock,
+ VariableDeclaration: checkVariableDeclaration,
"ForStatement:exit": endBlock,
"ForOfStatement:exit": endBlock,
"ForInStatement:exit": endBlock,
diff --git a/tools/node_modules/eslint/lib/rules/padding-line-between-statements.js b/tools/node_modules/eslint/lib/rules/padding-line-between-statements.js
index 9d1a4a3c7e..d2254fa6ab 100644
--- a/tools/node_modules/eslint/lib/rules/padding-line-between-statements.js
+++ b/tools/node_modules/eslint/lib/rules/padding-line-between-statements.js
@@ -358,6 +358,12 @@ const StatementTypes = {
node.loc.start.line !== node.loc.end.line &&
isBlockLikeStatement(sourceCode, node)
},
+ "multiline-expression": {
+ test: (node, sourceCode) =>
+ node.loc.start.line !== node.loc.end.line &&
+ node.type === "ExpressionStatement" &&
+ !isDirectivePrologue(node, sourceCode)
+ },
block: newNodeTypeTester("BlockStatement"),
empty: newNodeTypeTester("EmptyStatement"),
@@ -467,13 +473,15 @@ module.exports = {
* @private
*/
function match(node, type) {
- while (node.type === "LabeledStatement") {
- node = node.body;
+ let innerStatementNode = node;
+
+ while (innerStatementNode.type === "LabeledStatement") {
+ innerStatementNode = innerStatementNode.body;
}
if (Array.isArray(type)) {
- return type.some(match.bind(null, node));
+ return type.some(match.bind(null, innerStatementNode));
}
- return StatementTypes[type].test(node, sourceCode);
+ return StatementTypes[type].test(innerStatementNode, sourceCode);
}
/**
diff --git a/tools/node_modules/eslint/lib/rules/prefer-arrow-callback.js b/tools/node_modules/eslint/lib/rules/prefer-arrow-callback.js
index ff7a0fa7e7..1bc140b101 100644
--- a/tools/node_modules/eslint/lib/rules/prefer-arrow-callback.js
+++ b/tools/node_modules/eslint/lib/rules/prefer-arrow-callback.js
@@ -64,9 +64,10 @@ function getVariableOfArguments(scope) {
*/
function getCallbackInfo(node) {
const retv = { isCallback: false, isLexicalThis: false };
+ let currentNode = node;
let parent = node.parent;
- while (node) {
+ while (currentNode) {
switch (parent.type) {
// Checks parents recursively.
@@ -77,7 +78,7 @@ function getCallbackInfo(node) {
// Checks whether the parent node is `.bind(this)` call.
case "MemberExpression":
- if (parent.object === node &&
+ if (parent.object === currentNode &&
!parent.property.computed &&
parent.property.type === "Identifier" &&
parent.property.name === "bind" &&
@@ -97,7 +98,7 @@ function getCallbackInfo(node) {
// Checks whether the node is a callback.
case "CallExpression":
case "NewExpression":
- if (parent.callee !== node) {
+ if (parent.callee !== currentNode) {
retv.isCallback = true;
}
return retv;
@@ -106,7 +107,7 @@ function getCallbackInfo(node) {
return retv;
}
- node = parent;
+ currentNode = parent;
parent = parent.parent;
}
diff --git a/tools/node_modules/eslint/lib/rules/prefer-destructuring.js b/tools/node_modules/eslint/lib/rules/prefer-destructuring.js
index e9d02da3a1..112ea64613 100644
--- a/tools/node_modules/eslint/lib/rules/prefer-destructuring.js
+++ b/tools/node_modules/eslint/lib/rules/prefer-destructuring.js
@@ -165,8 +165,10 @@ module.exports = {
if (shouldCheck(reportNode.type, "object")) {
const property = rightNode.property;
- if ((property.type === "Literal" && leftNode.name === property.value) || (property.type === "Identifier" &&
- leftNode.name === property.name)) {
+ if (
+ (property.type === "Literal" && leftNode.name === property.value) ||
+ (property.type === "Identifier" && leftNode.name === property.name && !rightNode.computed)
+ ) {
report(reportNode, "object");
}
}
diff --git a/tools/node_modules/eslint/lib/rules/prefer-template.js b/tools/node_modules/eslint/lib/rules/prefer-template.js
index c583bdcf9a..2b893fd371 100644
--- a/tools/node_modules/eslint/lib/rules/prefer-template.js
+++ b/tools/node_modules/eslint/lib/rules/prefer-template.js
@@ -30,10 +30,12 @@ function isConcatenation(node) {
* @returns {ASTNode} the top binary expression node in parents of a given node.
*/
function getTopConcatBinaryExpression(node) {
- while (isConcatenation(node.parent)) {
- node = node.parent;
+ let currentNode = node;
+
+ while (isConcatenation(currentNode.parent)) {
+ currentNode = currentNode.parent;
}
- return node;
+ return currentNode;
}
/**
diff --git a/tools/node_modules/eslint/lib/rules/require-await.js b/tools/node_modules/eslint/lib/rules/require-await.js
index 6adc84ae15..5517cf8672 100644
--- a/tools/node_modules/eslint/lib/rules/require-await.js
+++ b/tools/node_modules/eslint/lib/rules/require-await.js
@@ -90,6 +90,11 @@ module.exports = {
AwaitExpression() {
scopeInfo.hasAwait = true;
+ },
+ ForOfStatement(node) {
+ if (node.await) {
+ scopeInfo.hasAwait = true;
+ }
}
};
}
diff --git a/tools/node_modules/eslint/lib/rules/rest-spread-spacing.js b/tools/node_modules/eslint/lib/rules/rest-spread-spacing.js
index 1fbc2c4cc5..e87d881298 100644
--- a/tools/node_modules/eslint/lib/rules/rest-spread-spacing.js
+++ b/tools/node_modules/eslint/lib/rules/rest-spread-spacing.js
@@ -47,9 +47,15 @@ module.exports = {
switch (node.type) {
case "SpreadElement":
type = "spread";
+ if (node.parent.type === "ObjectExpression") {
+ type += " property";
+ }
break;
case "RestElement":
type = "rest";
+ if (node.parent.type === "ObjectPattern") {
+ type += " property";
+ }
break;
case "ExperimentalSpreadProperty":
type = "spread property";
diff --git a/tools/node_modules/eslint/lib/rules/space-unary-ops.js b/tools/node_modules/eslint/lib/rules/space-unary-ops.js
index 4d122836ad..6fbcc15c04 100644
--- a/tools/node_modules/eslint/lib/rules/space-unary-ops.js
+++ b/tools/node_modules/eslint/lib/rules/space-unary-ops.js
@@ -67,15 +67,6 @@ module.exports = {
}
/**
- * Check if the node's child argument is an "ObjectExpression"
- * @param {ASTnode} node AST node
- * @returns {boolean} Whether or not the argument's type is "ObjectExpression"
- */
- function isArgumentObjectExpression(node) {
- return node.argument && node.argument.type && node.argument.type === "ObjectExpression";
- }
-
- /**
* Checks if an override exists for a given operator.
* @param {string} operator Operator
* @returns {boolean} Whether or not an override has been provided for the operator
@@ -125,7 +116,7 @@ module.exports = {
* @returns {void}
*/
function verifyWordDoesntHaveSpaces(node, firstToken, secondToken, word) {
- if (isArgumentObjectExpression(node)) {
+ if (astUtils.canTokensBeAdjacent(firstToken, secondToken)) {
if (secondToken.range[0] > firstToken.range[1]) {
context.report({
node,
@@ -150,8 +141,6 @@ module.exports = {
* @returns {void}
*/
function checkUnaryWordOperatorForSpaces(node, firstToken, secondToken, word) {
- word = word || firstToken.value;
-
if (overrideExistsForOperator(word)) {
if (overrideEnforcesSpaces(word)) {
verifyWordHasSpaces(node, firstToken, secondToken, word);
@@ -285,7 +274,7 @@ module.exports = {
const secondToken = tokens[1];
if ((node.type === "NewExpression" || node.prefix) && firstToken.type === "Keyword") {
- checkUnaryWordOperatorForSpaces(node, firstToken, secondToken);
+ checkUnaryWordOperatorForSpaces(node, firstToken, secondToken, firstToken.value);
return;
}
diff --git a/tools/node_modules/eslint/lib/rules/spaced-comment.js b/tools/node_modules/eslint/lib/rules/spaced-comment.js
index 9d2f5f49ac..3a76c0c260 100644
--- a/tools/node_modules/eslint/lib/rules/spaced-comment.js
+++ b/tools/node_modules/eslint/lib/rules/spaced-comment.js
@@ -17,10 +17,7 @@ const astUtils = require("../ast-utils");
* @returns {string} An escaped string.
*/
function escape(s) {
- const isOneChar = s.length === 1;
-
- s = lodash.escapeRegExp(s);
- return isOneChar ? s : `(?:${s})`;
+ return `(?:${lodash.escapeRegExp(s)})`;
}
/**
@@ -40,11 +37,10 @@ function escapeAndRepeat(s) {
* @returns {string[]} A marker list.
*/
function parseMarkersOption(markers) {
- markers = markers ? markers.slice(0) : [];
// `*` is a marker for JSDoc comments.
if (markers.indexOf("*") === -1) {
- markers.push("*");
+ return markers.concat("*");
}
return markers;
@@ -244,7 +240,7 @@ module.exports = {
const balanced = config.block && config.block.balanced;
const styleRules = ["block", "line"].reduce((rule, type) => {
- const markers = parseMarkersOption(config[type] && config[type].markers || config.markers);
+ const markers = parseMarkersOption(config[type] && config[type].markers || config.markers || []);
const exceptions = config[type] && config[type].exceptions || config.exceptions || [];
const endNeverPattern = "[ \t]+$";
diff --git a/tools/node_modules/eslint/lib/rules/template-tag-spacing.js b/tools/node_modules/eslint/lib/rules/template-tag-spacing.js
index aee7ac108b..aee7ac108b 100755..100644
--- a/tools/node_modules/eslint/lib/rules/template-tag-spacing.js
+++ b/tools/node_modules/eslint/lib/rules/template-tag-spacing.js
diff --git a/tools/node_modules/eslint/lib/rules/valid-jsdoc.js b/tools/node_modules/eslint/lib/rules/valid-jsdoc.js
index 5e1af10de7..4038f70e56 100644
--- a/tools/node_modules/eslint/lib/rules/valid-jsdoc.js
+++ b/tools/node_modules/eslint/lib/rules/valid-jsdoc.js
@@ -57,7 +57,9 @@ module.exports = {
},
additionalProperties: false
}
- ]
+ ],
+
+ fixable: "code"
},
create(context) {
@@ -145,23 +147,35 @@ module.exports = {
/**
* Extract the current and expected type based on the input type object
* @param {Object} type JSDoc tag
- * @returns {Object} current and expected type object
+ * @returns {{currentType: Doctrine.Type, expectedTypeName: string}} The current type annotation and
+ * the expected name of the annotation
* @private
*/
function getCurrentExpectedTypes(type) {
let currentType;
if (type.name) {
- currentType = type.name;
+ currentType = type;
} else if (type.expression) {
- currentType = type.expression.name;
+ currentType = type.expression;
}
- const expectedType = currentType && preferType[currentType];
-
return {
currentType,
- expectedType
+ expectedTypeName: currentType && preferType[currentType.name]
+ };
+ }
+
+ /**
+ * Gets the location of a JSDoc node in a file
+ * @param {Token} jsdocComment The comment that this node is parsed from
+ * @param {{range: number[]}} parsedJsdocNode A tag or other node which was parsed from this comment
+ * @returns {{start: SourceLocation, end: SourceLocation}} The 0-based source location for the tag
+ */
+ function getAbsoluteRange(jsdocComment, parsedJsdocNode) {
+ return {
+ start: sourceCode.getLocFromIndex(jsdocComment.range[0] + 2 + parsedJsdocNode.range[0]),
+ end: sourceCode.getLocFromIndex(jsdocComment.range[0] + 2 + parsedJsdocNode.range[1])
};
}
@@ -204,14 +218,21 @@ module.exports = {
elements.forEach(validateType.bind(null, jsdocNode));
typesToCheck.forEach(typeToCheck => {
- if (typeToCheck.expectedType &&
- typeToCheck.expectedType !== typeToCheck.currentType) {
+ if (typeToCheck.expectedTypeName &&
+ typeToCheck.expectedTypeName !== typeToCheck.currentType.name) {
context.report({
node: jsdocNode,
- message: "Use '{{expectedType}}' instead of '{{currentType}}'.",
+ message: "Use '{{expectedTypeName}}' instead of '{{currentTypeName}}'.",
+ loc: getAbsoluteRange(jsdocNode, typeToCheck.currentType),
data: {
- currentType: typeToCheck.currentType,
- expectedType: typeToCheck.expectedType
+ currentTypeName: typeToCheck.currentType.name,
+ expectedTypeName: typeToCheck.expectedTypeName
+ },
+ fix(fixer) {
+ return fixer.replaceTextRange(
+ typeToCheck.currentType.range.map(indexInComment => jsdocNode.range[0] + 2 + indexInComment),
+ typeToCheck.expectedTypeName
+ );
}
});
}
@@ -227,8 +248,8 @@ module.exports = {
function checkJSDoc(node) {
const jsdocNode = sourceCode.getJSDocComment(node),
functionData = fns.pop(),
- params = Object.create(null),
- paramsTags = [];
+ paramTagsByName = Object.create(null),
+ paramTags = [];
let hasReturns = false,
returnsTag,
hasConstructor = false,
@@ -244,7 +265,8 @@ module.exports = {
jsdoc = doctrine.parse(jsdocNode.value, {
strict: true,
unwrap: true,
- sloppy: true
+ sloppy: true,
+ range: true
});
} catch (ex) {
@@ -264,7 +286,7 @@ module.exports = {
case "param":
case "arg":
case "argument":
- paramsTags.push(tag);
+ paramTags.push(tag);
break;
case "return":
@@ -297,7 +319,29 @@ module.exports = {
// check tag preferences
if (prefer.hasOwnProperty(tag.title) && tag.title !== prefer[tag.title]) {
- context.report({ node: jsdocNode, message: "Use @{{name}} instead.", data: { name: prefer[tag.title] } });
+ const entireTagRange = getAbsoluteRange(jsdocNode, tag);
+
+ context.report({
+ node: jsdocNode,
+ message: "Use @{{name}} instead.",
+ loc: {
+ start: entireTagRange.start,
+ end: {
+ line: entireTagRange.start.line,
+ column: entireTagRange.start.column + `@${tag.title}`.length
+ }
+ },
+ data: { name: prefer[tag.title] },
+ fix(fixer) {
+ return fixer.replaceTextRange(
+ [
+ jsdocNode.range[0] + tag.range[0] + 3,
+ jsdocNode.range[0] + tag.range[0] + tag.title.length + 3
+ ],
+ prefer[tag.title]
+ );
+ }
+ });
}
// validate the types
@@ -306,17 +350,32 @@ module.exports = {
}
});
- paramsTags.forEach(param => {
+ paramTags.forEach(param => {
if (!param.type) {
- context.report({ node: jsdocNode, message: "Missing JSDoc parameter type for '{{name}}'.", data: { name: param.name } });
+ context.report({
+ node: jsdocNode,
+ message: "Missing JSDoc parameter type for '{{name}}'.",
+ loc: getAbsoluteRange(jsdocNode, param),
+ data: { name: param.name }
+ });
}
if (!param.description && requireParamDescription) {
- context.report({ node: jsdocNode, message: "Missing JSDoc parameter description for '{{name}}'.", data: { name: param.name } });
+ context.report({
+ node: jsdocNode,
+ message: "Missing JSDoc parameter description for '{{name}}'.",
+ loc: getAbsoluteRange(jsdocNode, param),
+ data: { name: param.name }
+ });
}
- if (params[param.name]) {
- context.report({ node: jsdocNode, message: "Duplicate JSDoc parameter '{{name}}'.", data: { name: param.name } });
+ if (paramTagsByName[param.name]) {
+ context.report({
+ node: jsdocNode,
+ message: "Duplicate JSDoc parameter '{{name}}'.",
+ loc: getAbsoluteRange(jsdocNode, param),
+ data: { name: param.name }
+ });
} else if (param.name.indexOf(".") === -1) {
- params[param.name] = 1;
+ paramTagsByName[param.name] = param;
}
});
@@ -325,6 +384,7 @@ module.exports = {
context.report({
node: jsdocNode,
message: "Unexpected @{{title}} tag; function has no return statement.",
+ loc: getAbsoluteRange(jsdocNode, returnsTag),
data: {
title: returnsTag.title
}
@@ -356,28 +416,29 @@ module.exports = {
}
// check the parameters
- const jsdocParams = Object.keys(params);
+ const jsdocParamNames = Object.keys(paramTagsByName);
if (node.params) {
- node.params.forEach((param, i) => {
- if (param.type === "AssignmentPattern") {
- param = param.left;
- }
-
- const name = param.name;
+ node.params.forEach((param, paramsIndex) => {
+ const bindingParam = param.type === "AssignmentPattern"
+ ? param.left
+ : param;
// TODO(nzakas): Figure out logical things to do with destructured, default, rest params
- if (param.type === "Identifier") {
- if (jsdocParams[i] && (name !== jsdocParams[i])) {
+ if (bindingParam.type === "Identifier") {
+ const name = bindingParam.name;
+
+ if (jsdocParamNames[paramsIndex] && (name !== jsdocParamNames[paramsIndex])) {
context.report({
node: jsdocNode,
message: "Expected JSDoc for '{{name}}' but found '{{jsdocName}}'.",
+ loc: getAbsoluteRange(jsdocNode, paramTagsByName[jsdocParamNames[paramsIndex]]),
data: {
name,
- jsdocName: jsdocParams[i]
+ jsdocName: jsdocParamNames[paramsIndex]
}
});
- } else if (!params[name] && !isOverride) {
+ } else if (!paramTagsByName[name] && !isOverride) {
context.report({
node: jsdocNode,
message: "Missing JSDoc for parameter '{{name}}'.",
diff --git a/tools/node_modules/eslint/lib/rules/vars-on-top.js b/tools/node_modules/eslint/lib/rules/vars-on-top.js
index 8f6bf1d977..0489aa61fc 100644
--- a/tools/node_modules/eslint/lib/rules/vars-on-top.js
+++ b/tools/node_modules/eslint/lib/rules/vars-on-top.js
@@ -125,23 +125,13 @@ module.exports = {
//--------------------------------------------------------------------------
return {
- VariableDeclaration(node) {
- const ancestors = context.getAncestors();
- let parent = ancestors.pop();
- let grandParent = ancestors.pop();
-
- if (node.kind === "var") { // check variable is `var` type and not `let` or `const`
- if (parent.type === "ExportNamedDeclaration") {
- node = parent;
- parent = grandParent;
- grandParent = ancestors.pop();
- }
-
- if (parent.type === "Program") { // That means its a global variable
- globalVarCheck(node, parent);
- } else {
- blockScopeVarCheck(node, parent, grandParent);
- }
+ "VariableDeclaration[kind='var']"(node) {
+ if (node.parent.type === "ExportNamedDeclaration") {
+ globalVarCheck(node.parent, node.parent.parent);
+ } else if (node.parent.type === "Program") {
+ globalVarCheck(node, node.parent);
+ } else {
+ blockScopeVarCheck(node, node.parent, node.parent.parent);
}
}
};
diff --git a/tools/node_modules/eslint/lib/timing.js b/tools/node_modules/eslint/lib/timing.js
index e33ac8f458..9452e419b1 100644
--- a/tools/node_modules/eslint/lib/timing.js
+++ b/tools/node_modules/eslint/lib/timing.js
@@ -90,12 +90,10 @@ function display(data) {
.join(" | ")
));
- table.splice(1, 0, widths.map((w, index) => {
- if (index !== 0 && index !== widths.length - 1) {
- w++;
- }
+ table.splice(1, 0, widths.map((width, index) => {
+ const extraAlignment = index !== 0 && index !== widths.length - 1 ? 2 : 1;
- return ALIGN[index](":", w + 1, "-");
+ return ALIGN[index](":", width + extraAlignment, "-");
}).join("|"));
console.log(table.join("\n")); // eslint-disable-line no-console
diff --git a/tools/node_modules/eslint/lib/util/glob-util.js b/tools/node_modules/eslint/lib/util/glob-util.js
index 6a1f150a59..d687aa7462 100644
--- a/tools/node_modules/eslint/lib/util/glob-util.js
+++ b/tools/node_modules/eslint/lib/util/glob-util.js
@@ -8,7 +8,8 @@
// Requirements
//------------------------------------------------------------------------------
-const fs = require("fs"),
+const lodash = require("lodash"),
+ fs = require("fs"),
path = require("path"),
GlobSync = require("./glob"),
@@ -88,24 +89,31 @@ function resolveFileGlobPatterns(patterns, options) {
return patterns.filter(p => p.length).map(processPathExtensions);
}
+const dotfilesPattern = /(?:(?:^\.)|(?:[/\\]\.))[^/\\.].*/;
+
/**
* Build a list of absolute filesnames on which ESLint will act.
* Ignored files are excluded from the results, as are duplicates.
*
- * @param {string[]} globPatterns Glob patterns.
- * @param {Object} [options] An options object.
- * @param {string} [options.cwd] CWD (considered for relative filenames)
- * @param {boolean} [options.ignore] False disables use of .eslintignore.
- * @param {string} [options.ignorePath] The ignore file to use instead of .eslintignore.
- * @param {string} [options.ignorePattern] A pattern of files to ignore.
+ * @param {string[]} globPatterns Glob patterns.
+ * @param {Object} [providedOptions] An options object.
+ * @param {string} [providedOptions.cwd] CWD (considered for relative filenames)
+ * @param {boolean} [providedOptions.ignore] False disables use of .eslintignore.
+ * @param {string} [providedOptions.ignorePath] The ignore file to use instead of .eslintignore.
+ * @param {string} [providedOptions.ignorePattern] A pattern of files to ignore.
* @returns {string[]} Resolved absolute filenames.
*/
-function listFilesToProcess(globPatterns, options) {
- options = options || { ignore: true };
- const files = [],
- added = {};
+function listFilesToProcess(globPatterns, providedOptions) {
+ const options = providedOptions || { ignore: true };
+ const files = [];
+ const added = {};
- const cwd = (options && options.cwd) || process.cwd();
+ const cwd = options.cwd || process.cwd();
+
+ const getIgnorePaths = lodash.memoize(
+ optionsObj =>
+ new IgnoredPaths(optionsObj)
+ );
/**
* Executes the linter on a file defined by the `filename`. Skips
@@ -151,15 +159,20 @@ function listFilesToProcess(globPatterns, options) {
const file = path.resolve(cwd, pattern);
if (fs.existsSync(file) && fs.statSync(file).isFile()) {
- const ignoredPaths = new IgnoredPaths(options);
+ const ignoredPaths = getIgnorePaths(options);
addFile(fs.realpathSync(file), true, ignoredPaths);
} else {
// regex to find .hidden or /.hidden patterns, but not ./relative or ../relative
- const globIncludesDotfiles = /(?:(?:^\.)|(?:[/\\]\.))[^/\\.].*/.test(pattern);
+ const globIncludesDotfiles = dotfilesPattern.test(pattern);
+ let newOptions = options;
+
+ if (!options.dotfiles) {
+ newOptions = Object.assign({}, options, { dotfiles: globIncludesDotfiles });
+ }
- const ignoredPaths = new IgnoredPaths(Object.assign({}, options, { dotfiles: options.dotfiles || globIncludesDotfiles }));
+ const ignoredPaths = getIgnorePaths(newOptions);
const shouldIgnore = ignoredPaths.getIgnoredFoldersGlobChecker();
const globOptions = {
nodir: true,
diff --git a/tools/node_modules/eslint/lib/util/interpolate.js b/tools/node_modules/eslint/lib/util/interpolate.js
index e0f2d027d1..cefdcca545 100644
--- a/tools/node_modules/eslint/lib/util/interpolate.js
+++ b/tools/node_modules/eslint/lib/util/interpolate.js
@@ -13,7 +13,11 @@ module.exports = (text, data) => {
if (!data) {
return text;
}
- return text.replace(/\{\{\s*([^{}]+?)\s*\}\}/g, (fullMatch, term) => {
+
+ // Substitution content for any {{ }} markers.
+ return text.replace(/\{\{([^{}]+?)\}\}/g, (fullMatch, termWithWhitespace) => {
+ const term = termWithWhitespace.trim();
+
if (term in data) {
return data[term];
}
diff --git a/tools/node_modules/eslint/lib/util/naming.js b/tools/node_modules/eslint/lib/util/naming.js
index dcac81bbd6..c5ff429aa4 100644
--- a/tools/node_modules/eslint/lib/util/naming.js
+++ b/tools/node_modules/eslint/lib/util/naming.js
@@ -23,17 +23,18 @@ const NAMESPACE_REGEX = /^@.*\//i;
* @private
*/
function normalizePackageName(name, prefix) {
+ let normalizedName = name;
/**
* On Windows, name can come in with Windows slashes instead of Unix slashes.
* Normalize to Unix first to avoid errors later on.
* https://github.com/eslint/eslint/issues/5644
*/
- if (name.indexOf("\\") > -1) {
- name = pathUtil.convertPathToPosix(name);
+ if (normalizedName.indexOf("\\") > -1) {
+ normalizedName = pathUtil.convertPathToPosix(normalizedName);
}
- if (name.charAt(0) === "@") {
+ if (normalizedName.charAt(0) === "@") {
/**
* it's a scoped package
@@ -42,21 +43,21 @@ function normalizePackageName(name, prefix) {
const scopedPackageShortcutRegex = new RegExp(`^(@[^/]+)(?:/(?:${prefix})?)?$`),
scopedPackageNameRegex = new RegExp(`^${prefix}(-|$)`);
- if (scopedPackageShortcutRegex.test(name)) {
- name = name.replace(scopedPackageShortcutRegex, `$1/${prefix}`);
- } else if (!scopedPackageNameRegex.test(name.split("/")[1])) {
+ if (scopedPackageShortcutRegex.test(normalizedName)) {
+ normalizedName = normalizedName.replace(scopedPackageShortcutRegex, `$1/${prefix}`);
+ } else if (!scopedPackageNameRegex.test(normalizedName.split("/")[1])) {
/**
* for scoped packages, insert the prefix after the first / unless
* the path is already @scope/eslint or @scope/eslint-xxx-yyy
*/
- name = name.replace(/^@([^/]+)\/(.*)$/, `@$1/${prefix}-$2`);
+ normalizedName = normalizedName.replace(/^@([^/]+)\/(.*)$/, `@$1/${prefix}-$2`);
}
- } else if (name.indexOf(`${prefix}-`) !== 0) {
- name = `${prefix}-${name}`;
+ } else if (normalizedName.indexOf(`${prefix}-`) !== 0) {
+ normalizedName = `${prefix}-${normalizedName}`;
}
- return name;
+ return normalizedName;
}
/**
diff --git a/tools/node_modules/eslint/lib/util/npm-util.js b/tools/node_modules/eslint/lib/util/npm-util.js
index 6c431e0395..0b21f62613 100644
--- a/tools/node_modules/eslint/lib/util/npm-util.js
+++ b/tools/node_modules/eslint/lib/util/npm-util.js
@@ -50,17 +50,15 @@ function findPackageJson(startDir) {
* @returns {void}
*/
function installSyncSaveDev(packages) {
- if (!Array.isArray(packages)) {
- packages = [packages];
- }
- const npmProcess = spawn.sync("npm", ["i", "--save-dev"].concat(packages),
+ const packageList = Array.isArray(packages) ? packages : [packages];
+ const npmProcess = spawn.sync("npm", ["i", "--save-dev"].concat(packageList),
{ stdio: "inherit" });
const error = npmProcess.error;
if (error && error.code === "ENOENT") {
- const pluralS = packages.length > 1 ? "s" : "";
+ const pluralS = packageList.length > 1 ? "s" : "";
- log.error(`Could not execute npm. Please install the following package${pluralS} with your package manager of choice: ${packages.join(", ")}`);
+ log.error(`Could not execute npm. Please install the following package${pluralS} with a package manager of your choice: ${packageList.join(", ")}`);
}
}
diff --git a/tools/node_modules/eslint/lib/util/path-util.js b/tools/node_modules/eslint/lib/util/path-util.js
index 4100ff91a0..54460ffd1f 100644
--- a/tools/node_modules/eslint/lib/util/path-util.js
+++ b/tools/node_modules/eslint/lib/util/path-util.js
@@ -48,20 +48,18 @@ function convertPathToPosix(filepath) {
* @returns {string} Relative filepath
*/
function getRelativePath(filepath, baseDir) {
- let relativePath;
+ const absolutePath = path.isAbsolute(filepath)
+ ? filepath
+ : path.resolve(filepath);
- if (!path.isAbsolute(filepath)) {
- filepath = path.resolve(filepath);
- }
if (baseDir) {
if (!path.isAbsolute(baseDir)) {
throw new Error("baseDir should be an absolute path");
}
- relativePath = path.relative(baseDir, filepath);
- } else {
- relativePath = filepath.replace(/^\//, "");
+ return path.relative(baseDir, absolutePath);
}
- return relativePath;
+ return absolutePath.replace(/^\//, "");
+
}
//------------------------------------------------------------------------------
diff --git a/tools/node_modules/eslint/lib/util/source-code-util.js b/tools/node_modules/eslint/lib/util/source-code-util.js
index 6ffd243e2e..815fad9112 100644
--- a/tools/node_modules/eslint/lib/util/source-code-util.js
+++ b/tools/node_modules/eslint/lib/util/source-code-util.js
@@ -55,50 +55,47 @@ function getSourceCodeOfFile(filename, options) {
/**
* Gets the SourceCode of a single file, or set of files.
- * @param {string[]|string} patterns A filename, directory name, or glob,
- * or an array of them
- * @param {Object} [options] A CLIEngine options object. If not provided,
- * the default cli options will be used.
- * @param {progressCallback} [cb] Callback for reporting execution status
- * @returns {Object} The SourceCode of all processed files.
+ * @param {string[]|string} patterns A filename, directory name, or glob, or an array of them
+ * @param {Object} [providedOptions] A CLIEngine options object. If not provided, the default cli options will be used.
+ * @param {progressCallback} [providedCallback] Callback for reporting execution status
+ * @returns {Object} The SourceCode of all processed files.
*/
-function getSourceCodeOfFiles(patterns, options, cb) {
+function getSourceCodeOfFiles(patterns, providedOptions, providedCallback) {
const sourceCodes = {};
- let opts;
-
- if (typeof patterns === "string") {
- patterns = [patterns];
- }
+ const globPatternsList = typeof patterns === "string" ? [patterns] : patterns;
+ let options, callback;
const defaultOptions = Object.assign({}, baseDefaultOptions, { cwd: process.cwd() });
- if (typeof options === "undefined") {
- opts = defaultOptions;
- } else if (typeof options === "function") {
- cb = options;
- opts = defaultOptions;
- } else if (typeof options === "object") {
- opts = Object.assign({}, defaultOptions, options);
+ if (typeof providedOptions === "undefined") {
+ options = defaultOptions;
+ callback = null;
+ } else if (typeof providedOptions === "function") {
+ callback = providedOptions;
+ options = defaultOptions;
+ } else if (typeof providedOptions === "object") {
+ options = Object.assign({}, defaultOptions, providedOptions);
+ callback = providedCallback;
}
- debug("constructed options:", opts);
- patterns = globUtil.resolveFileGlobPatterns(patterns, opts);
+ debug("constructed options:", options);
+ const resolvedPatterns = globUtil.resolveFileGlobPatterns(globPatternsList, options);
- const filenames = globUtil.listFilesToProcess(patterns, opts)
+ const filenames = globUtil.listFilesToProcess(resolvedPatterns, options)
.filter(fileInfo => !fileInfo.ignored)
.reduce((files, fileInfo) => files.concat(fileInfo.filename), []);
if (filenames.length === 0) {
- debug(`Did not find any files matching pattern(s): ${patterns}`);
+ debug(`Did not find any files matching pattern(s): ${resolvedPatterns}`);
}
filenames.forEach(filename => {
- const sourceCode = getSourceCodeOfFile(filename, opts);
+ const sourceCode = getSourceCodeOfFile(filename, options);
if (sourceCode) {
debug("got sourceCode of", filename);
sourceCodes[filename] = sourceCode;
}
- if (cb) {
- cb(filenames.length); // eslint-disable-line callback-return
+ if (callback) {
+ callback(filenames.length); // eslint-disable-line callback-return
}
});
return sourceCodes;
diff --git a/tools/node_modules/eslint/lib/util/source-code.js b/tools/node_modules/eslint/lib/util/source-code.js
index dee81aa10c..3375f4483d 100644
--- a/tools/node_modules/eslint/lib/util/source-code.js
+++ b/tools/node_modules/eslint/lib/util/source-code.js
@@ -90,15 +90,16 @@ class SourceCode extends TokenStore {
* @param {Object|null} textOrConfig.parserServices - The parser srevices.
* @param {ScopeManager|null} textOrConfig.scopeManager - The scope of this source code.
* @param {Object|null} textOrConfig.visitorKeys - The visitor keys to traverse AST.
- * @param {ASTNode} [ast] - The Program node of the AST representing the code. This AST should be created from the text that BOM was stripped.
+ * @param {ASTNode} [astIfNoConfig] - The Program node of the AST representing the code. This AST should be created from the text that BOM was stripped.
* @constructor
*/
- constructor(textOrConfig, ast) {
- let text, parserServices, scopeManager, visitorKeys;
+ constructor(textOrConfig, astIfNoConfig) {
+ let text, ast, parserServices, scopeManager, visitorKeys;
// Process overloading.
if (typeof textOrConfig === "string") {
text = textOrConfig;
+ ast = astIfNoConfig;
} else if (typeof textOrConfig === "object" && textOrConfig !== null) {
text = textOrConfig.text;
ast = textOrConfig.ast;