summaryrefslogtreecommitdiff
path: root/tools/node_modules/eslint/lib
diff options
context:
space:
mode:
Diffstat (limited to 'tools/node_modules/eslint/lib')
-rw-r--r--tools/node_modules/eslint/lib/cli-engine/cli-engine.js7
-rw-r--r--tools/node_modules/eslint/lib/cli-engine/config-array-factory.js2
-rw-r--r--tools/node_modules/eslint/lib/cli-engine/file-enumerator.js18
-rw-r--r--tools/node_modules/eslint/lib/init/config-initializer.js28
-rw-r--r--tools/node_modules/eslint/lib/linter/linter.js2
-rw-r--r--tools/node_modules/eslint/lib/rule-tester/rule-tester.js2
-rw-r--r--tools/node_modules/eslint/lib/rules/arrow-body-style.js4
-rw-r--r--tools/node_modules/eslint/lib/rules/dot-location.js38
-rw-r--r--tools/node_modules/eslint/lib/rules/no-extra-parens.js258
-rw-r--r--tools/node_modules/eslint/lib/rules/no-param-reassign.js13
-rw-r--r--tools/node_modules/eslint/lib/rules/prefer-const.js12
-rw-r--r--tools/node_modules/eslint/lib/rules/utils/ast-utils.js27
-rw-r--r--tools/node_modules/eslint/lib/shared/naming.js (renamed from tools/node_modules/eslint/lib/cli-engine/naming.js)0
13 files changed, 343 insertions, 68 deletions
diff --git a/tools/node_modules/eslint/lib/cli-engine/cli-engine.js b/tools/node_modules/eslint/lib/cli-engine/cli-engine.js
index 81e1b07c83..7f80887f08 100644
--- a/tools/node_modules/eslint/lib/cli-engine/cli-engine.js
+++ b/tools/node_modules/eslint/lib/cli-engine/cli-engine.js
@@ -20,6 +20,7 @@ const path = require("path");
const defaultOptions = require("../../conf/default-cli-options");
const pkg = require("../../package.json");
const ConfigOps = require("../shared/config-ops");
+const naming = require("../shared/naming");
const ModuleResolver = require("../shared/relative-module-resolver");
const { Linter } = require("../linter");
const builtInRules = require("../rules");
@@ -29,7 +30,6 @@ const { FileEnumerator } = require("./file-enumerator");
const hash = require("./hash");
const { IgnoredPaths } = require("./ignored-paths");
const LintResultCache = require("./lint-result-cache");
-const naming = require("./naming");
const debug = require("debug")("eslint:cli-engine");
const validFixTypes = new Set(["problem", "suggestion", "layout"]);
@@ -734,7 +734,10 @@ class CLIEngine {
try {
fs.unlinkSync(cacheFilePath);
} catch (error) {
- if (!error || error.code !== "ENOENT") {
+ const errorCode = error && error.code;
+
+ // Ignore errors when no such file exists or file system is read only (and cache file does not exist)
+ if (errorCode !== "ENOENT" && !(errorCode === "EROFS" && !fs.existsSync(cacheFilePath))) {
throw error;
}
}
diff --git a/tools/node_modules/eslint/lib/cli-engine/config-array-factory.js b/tools/node_modules/eslint/lib/cli-engine/config-array-factory.js
index 782bb1d148..95430c358d 100644
--- a/tools/node_modules/eslint/lib/cli-engine/config-array-factory.js
+++ b/tools/node_modules/eslint/lib/cli-engine/config-array-factory.js
@@ -38,9 +38,9 @@ const path = require("path");
const importFresh = require("import-fresh");
const stripComments = require("strip-json-comments");
const { validateConfigSchema } = require("../shared/config-validator");
+const naming = require("../shared/naming");
const ModuleResolver = require("../shared/relative-module-resolver");
const { ConfigArray, ConfigDependency, OverrideTester } = require("./config-array");
-const naming = require("./naming");
const debug = require("debug")("eslint:config-array-factory");
//------------------------------------------------------------------------------
diff --git a/tools/node_modules/eslint/lib/cli-engine/file-enumerator.js b/tools/node_modules/eslint/lib/cli-engine/file-enumerator.js
index 2840d9fe2d..a027359ae5 100644
--- a/tools/node_modules/eslint/lib/cli-engine/file-enumerator.js
+++ b/tools/node_modules/eslint/lib/cli-engine/file-enumerator.js
@@ -292,26 +292,18 @@ class FileEnumerator {
_iterateFiles(pattern) {
const { cwd, globInputPaths } = internalSlotsMap.get(this);
const absolutePath = path.resolve(cwd, pattern);
-
- if (globInputPaths && isGlobPattern(pattern)) {
- return this._iterateFilesWithGlob(
- absolutePath,
- dotfilesPattern.test(pattern)
- );
- }
-
+ const isDot = dotfilesPattern.test(pattern);
const stat = statSafeSync(absolutePath);
if (stat && stat.isDirectory()) {
- return this._iterateFilesWithDirectory(
- absolutePath,
- dotfilesPattern.test(pattern)
- );
+ return this._iterateFilesWithDirectory(absolutePath, isDot);
}
-
if (stat && stat.isFile()) {
return this._iterateFilesWithFile(absolutePath);
}
+ if (globInputPaths && isGlobPattern(pattern)) {
+ return this._iterateFilesWithGlob(absolutePath, isDot);
+ }
return [];
}
diff --git a/tools/node_modules/eslint/lib/init/config-initializer.js b/tools/node_modules/eslint/lib/init/config-initializer.js
index 4d52377d26..17aa96505a 100644
--- a/tools/node_modules/eslint/lib/init/config-initializer.js
+++ b/tools/node_modules/eslint/lib/init/config-initializer.js
@@ -18,6 +18,7 @@ const util = require("util"),
recConfig = require("../../conf/eslint-recommended"),
ConfigOps = require("../shared/config-ops"),
log = require("../shared/logging"),
+ naming = require("../shared/naming"),
ModuleResolver = require("../shared/relative-module-resolver"),
autoconfig = require("./autoconfig.js"),
ConfigFile = require("./config-file"),
@@ -97,17 +98,26 @@ function getModulesList(config, installESLint) {
// Create a list of modules which should be installed based on config
if (config.plugins) {
for (const plugin of config.plugins) {
- modules[`eslint-plugin-${plugin}`] = "latest";
+ const moduleName = naming.normalizePackageName(plugin, "eslint-plugin");
+
+ modules[moduleName] = "latest";
}
}
- if (config.extends && config.extends.indexOf("eslint:") === -1) {
- const moduleName = `eslint-config-${config.extends}`;
-
- modules[moduleName] = "latest";
- Object.assign(
- modules,
- getPeerDependencies(`${moduleName}@latest`)
- );
+ if (config.extends) {
+ const extendList = Array.isArray(config.extends) ? config.extends : [config.extends];
+
+ for (const extend of extendList) {
+ if (extend.startsWith("eslint:") || extend.startsWith("plugin:")) {
+ continue;
+ }
+ const moduleName = naming.normalizePackageName(extend, "eslint-config");
+
+ modules[moduleName] = "latest";
+ Object.assign(
+ modules,
+ getPeerDependencies(`${moduleName}@latest`)
+ );
+ }
}
if (installESLint === false) {
diff --git a/tools/node_modules/eslint/lib/linter/linter.js b/tools/node_modules/eslint/lib/linter/linter.js
index 6324706974..a49d850859 100644
--- a/tools/node_modules/eslint/lib/linter/linter.js
+++ b/tools/node_modules/eslint/lib/linter/linter.js
@@ -262,7 +262,7 @@ function createDisableDirectives(options) {
*/
function getDirectiveComments(filename, ast, ruleMapper) {
const configuredRules = {};
- const enabledGlobals = {};
+ const enabledGlobals = Object.create(null);
const exportedVariables = {};
const problems = [];
const disableDirectives = [];
diff --git a/tools/node_modules/eslint/lib/rule-tester/rule-tester.js b/tools/node_modules/eslint/lib/rule-tester/rule-tester.js
index 81f3a2fc4e..0d1319c11a 100644
--- a/tools/node_modules/eslint/lib/rule-tester/rule-tester.js
+++ b/tools/node_modules/eslint/lib/rule-tester/rule-tester.js
@@ -549,8 +549,8 @@ class RuleTester {
assert(false, `Invalid messageId '${error.messageId}'. Expected one of ${friendlyIDList}.`);
}
assert.strictEqual(
- error.messageId,
message.messageId,
+ error.messageId,
`messageId '${message.messageId}' does not match expected messageId '${error.messageId}'.`
);
if (hasOwnProperty(error, "data")) {
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 6d84c7adfb..8d3b400037 100644
--- a/tools/node_modules/eslint/lib/rules/arrow-body-style.js
+++ b/tools/node_modules/eslint/lib/rules/arrow-body-style.js
@@ -175,10 +175,10 @@ module.exports = {
}
/*
- * If the first token of the reutrn value is `{`,
+ * If the first token of the reutrn value is `{` or the return value is a sequence expression,
* enclose the return value by parentheses to avoid syntax error.
*/
- if (astUtils.isOpeningBraceToken(firstValueToken)) {
+ if (astUtils.isOpeningBraceToken(firstValueToken) || blockBody[0].argument.type === "SequenceExpression") {
fixes.push(
fixer.insertTextBefore(firstValueToken, "("),
fixer.insertTextAfter(lastValueToken, ")")
diff --git a/tools/node_modules/eslint/lib/rules/dot-location.js b/tools/node_modules/eslint/lib/rules/dot-location.js
index b9857ae239..c2e734a1a0 100644
--- a/tools/node_modules/eslint/lib/rules/dot-location.js
+++ b/tools/node_modules/eslint/lib/rules/dot-location.js
@@ -54,29 +54,31 @@ module.exports = {
*/
function checkDotLocation(obj, prop, node) {
const dot = sourceCode.getTokenBefore(prop);
- const textBeforeDot = sourceCode.getText().slice(obj.range[1], dot.range[0]);
+
+ // `obj` expression can be parenthesized, but those paren tokens are not a part of the `obj` node.
+ const tokenBeforeDot = sourceCode.getTokenBefore(dot);
+
+ const textBeforeDot = sourceCode.getText().slice(tokenBeforeDot.range[1], dot.range[0]);
const textAfterDot = sourceCode.getText().slice(dot.range[1], prop.range[0]);
- if (dot.type === "Punctuator" && dot.value === ".") {
- if (onObject) {
- if (!astUtils.isTokenOnSameLine(obj, dot)) {
- const neededTextAfterObj = astUtils.isDecimalInteger(obj) ? " " : "";
-
- context.report({
- node,
- loc: dot.loc.start,
- messageId: "expectedDotAfterObject",
- fix: fixer => fixer.replaceTextRange([obj.range[1], prop.range[0]], `${neededTextAfterObj}.${textBeforeDot}${textAfterDot}`)
- });
- }
- } else if (!astUtils.isTokenOnSameLine(dot, prop)) {
+ if (onObject) {
+ if (!astUtils.isTokenOnSameLine(tokenBeforeDot, dot)) {
+ const neededTextAfterToken = astUtils.isDecimalIntegerNumericToken(tokenBeforeDot) ? " " : "";
+
context.report({
node,
loc: dot.loc.start,
- messageId: "expectedDotBeforeProperty",
- fix: fixer => fixer.replaceTextRange([obj.range[1], prop.range[0]], `${textBeforeDot}${textAfterDot}.`)
+ messageId: "expectedDotAfterObject",
+ fix: fixer => fixer.replaceTextRange([tokenBeforeDot.range[1], prop.range[0]], `${neededTextAfterToken}.${textBeforeDot}${textAfterDot}`)
});
}
+ } else if (!astUtils.isTokenOnSameLine(dot, prop)) {
+ context.report({
+ node,
+ loc: dot.loc.start,
+ messageId: "expectedDotBeforeProperty",
+ fix: fixer => fixer.replaceTextRange([tokenBeforeDot.range[1], prop.range[0]], `${textBeforeDot}${textAfterDot}.`)
+ });
}
}
@@ -86,7 +88,9 @@ module.exports = {
* @returns {void}
*/
function checkNode(node) {
- checkDotLocation(node.object, node.property, node);
+ if (!node.computed) {
+ checkDotLocation(node.object, node.property, node);
+ }
}
return {
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 98fc49654c..6c3198b5f0 100644
--- a/tools/node_modules/eslint/lib/rules/no-extra-parens.js
+++ b/tools/node_modules/eslint/lib/rules/no-extra-parens.js
@@ -81,6 +81,8 @@ module.exports = {
const PRECEDENCE_OF_ASSIGNMENT_EXPR = precedence({ type: "AssignmentExpression" });
const PRECEDENCE_OF_UPDATE_EXPR = precedence({ type: "UpdateExpression" });
+ let reportsBuffer;
+
/**
* Determines if this rule should be enforced for a node given the current configuration.
* @param {ASTNode} node - The node to be checked.
@@ -316,19 +318,33 @@ module.exports = {
}
}
- context.report({
- node,
- loc: leftParenToken.loc.start,
- messageId: "unexpected",
- fix(fixer) {
- const parenthesizedSource = sourceCode.text.slice(leftParenToken.range[1], rightParenToken.range[0]);
+ /**
+ * Finishes reporting
+ * @returns {void}
+ * @private
+ */
+ function finishReport() {
+ context.report({
+ node,
+ loc: leftParenToken.loc.start,
+ messageId: "unexpected",
+ fix(fixer) {
+ const parenthesizedSource = sourceCode.text.slice(leftParenToken.range[1], rightParenToken.range[0]);
+
+ return fixer.replaceTextRange([
+ leftParenToken.range[0],
+ rightParenToken.range[1]
+ ], (requiresLeadingSpace(node) ? " " : "") + parenthesizedSource + (requiresTrailingSpace(node) ? " " : ""));
+ }
+ });
+ }
- return fixer.replaceTextRange([
- leftParenToken.range[0],
- rightParenToken.range[1]
- ], (requiresLeadingSpace(node) ? " " : "") + parenthesizedSource + (requiresTrailingSpace(node) ? " " : ""));
- }
- });
+ if (reportsBuffer) {
+ reportsBuffer.reports.push({ node, finishReport });
+ return;
+ }
+
+ finishReport();
}
/**
@@ -498,6 +514,126 @@ module.exports = {
}
}
+ /**
+ * Finds the path from the given node to the specified ancestor.
+ * @param {ASTNode} node First node in the path.
+ * @param {ASTNode} ancestor Last node in the path.
+ * @returns {ASTNode[]} Path, including both nodes.
+ * @throws {Error} If the given node does not have the specified ancestor.
+ */
+ function pathToAncestor(node, ancestor) {
+ const path = [node];
+ let currentNode = node;
+
+ while (currentNode !== ancestor) {
+
+ currentNode = currentNode.parent;
+
+ /* istanbul ignore if */
+ if (currentNode === null) {
+ throw new Error("Nodes are not in the ancestor-descendant relationship.");
+ }
+
+ path.push(currentNode);
+ }
+
+ return path;
+ }
+
+ /**
+ * Finds the path from the given node to the specified descendant.
+ * @param {ASTNode} node First node in the path.
+ * @param {ASTNode} descendant Last node in the path.
+ * @returns {ASTNode[]} Path, including both nodes.
+ * @throws {Error} If the given node does not have the specified descendant.
+ */
+ function pathToDescendant(node, descendant) {
+ return pathToAncestor(descendant, node).reverse();
+ }
+
+ /**
+ * Checks whether the syntax of the given ancestor of an 'in' expression inside a for-loop initializer
+ * is preventing the 'in' keyword from being interpreted as a part of an ill-formed for-in loop.
+ *
+ * @param {ASTNode} node Ancestor of an 'in' expression.
+ * @param {ASTNode} child Child of the node, ancestor of the same 'in' expression or the 'in' expression itself.
+ * @returns {boolean} True if the keyword 'in' would be interpreted as the 'in' operator, without any parenthesis.
+ */
+ function isSafelyEnclosingInExpression(node, child) {
+ switch (node.type) {
+ case "ArrayExpression":
+ case "ArrayPattern":
+ case "BlockStatement":
+ case "ObjectExpression":
+ case "ObjectPattern":
+ case "TemplateLiteral":
+ return true;
+ case "ArrowFunctionExpression":
+ case "FunctionExpression":
+ return node.params.includes(child);
+ case "CallExpression":
+ case "NewExpression":
+ return node.arguments.includes(child);
+ case "MemberExpression":
+ return node.computed && node.property === child;
+ case "ConditionalExpression":
+ return node.consequent === child;
+ default:
+ return false;
+ }
+ }
+
+ /**
+ * Starts a new reports buffering. Warnings will be stored in a buffer instead of being reported immediately.
+ * An additional logic that requires multiple nodes (e.g. a whole subtree) may dismiss some of the stored warnings.
+ *
+ * @returns {void}
+ */
+ function startNewReportsBuffering() {
+ reportsBuffer = {
+ upper: reportsBuffer,
+ inExpressionNodes: [],
+ reports: []
+ };
+ }
+
+ /**
+ * Ends the current reports buffering.
+ * @returns {void}
+ */
+ function endCurrentReportsBuffering() {
+ const { upper, inExpressionNodes, reports } = reportsBuffer;
+
+ if (upper) {
+ upper.inExpressionNodes.push(...inExpressionNodes);
+ upper.reports.push(...reports);
+ } else {
+
+ // flush remaining reports
+ reports.forEach(({ finishReport }) => finishReport());
+ }
+
+ reportsBuffer = upper;
+ }
+
+ /**
+ * Checks whether the given node is in the current reports buffer.
+ * @param {ASTNode} node Node to check.
+ * @returns {boolean} True if the node is in the current buffer, false otherwise.
+ */
+ function isInCurrentReportsBuffer(node) {
+ return reportsBuffer.reports.some(r => r.node === node);
+ }
+
+ /**
+ * Removes the given node from the current reports buffer.
+ * @param {ASTNode} node Node to remove.
+ * @returns {void}
+ */
+ function removeFromCurrentReportsBuffer(node) {
+ reportsBuffer.reports = reportsBuffer.reports.filter(r => r.node !== node);
+ }
+
return {
ArrayExpression(node) {
node.elements
@@ -540,7 +676,14 @@ module.exports = {
}
},
- BinaryExpression: checkBinaryLogical,
+ BinaryExpression(node) {
+ if (reportsBuffer && node.operator === "in") {
+ reportsBuffer.inExpressionNodes.push(node);
+ }
+
+ checkBinaryLogical(node);
+ },
+
CallExpression: checkCallNew,
ConditionalExpression(node) {
@@ -602,10 +745,6 @@ module.exports = {
},
ForStatement(node) {
- if (node.init && hasExcessParens(node.init)) {
- report(node.init);
- }
-
if (node.test && hasExcessParens(node.test) && !isCondAssignException(node)) {
report(node.test);
}
@@ -613,6 +752,81 @@ module.exports = {
if (node.update && hasExcessParens(node.update)) {
report(node.update);
}
+
+ if (node.init) {
+ startNewReportsBuffering();
+
+ if (hasExcessParens(node.init)) {
+ report(node.init);
+ }
+ }
+ },
+
+ "ForStatement > *.init:exit"(node) {
+
+ /*
+ * Removing parentheses around `in` expressions might change semantics and cause errors.
+ *
+ * For example, this valid for loop:
+ * for (let a = (b in c); ;);
+ * after removing parentheses would be treated as an invalid for-in loop:
+ * for (let a = b in c; ;);
+ */
+
+ if (reportsBuffer.reports.length) {
+ reportsBuffer.inExpressionNodes.forEach(inExpressionNode => {
+ const path = pathToDescendant(node, inExpressionNode);
+ let nodeToExclude;
+
+ for (let i = 0; i < path.length; i++) {
+ const pathNode = path[i];
+
+ if (i < path.length - 1) {
+ const nextPathNode = path[i + 1];
+
+ if (isSafelyEnclosingInExpression(pathNode, nextPathNode)) {
+
+ // The 'in' expression in safely enclosed by the syntax of its ancestor nodes (e.g. by '{}' or '[]').
+ return;
+ }
+ }
+
+ if (isParenthesised(pathNode)) {
+ if (isInCurrentReportsBuffer(pathNode)) {
+
+ // This node was supposed to be reported, but parentheses might be necessary.
+
+ if (isParenthesisedTwice(pathNode)) {
+
+ /*
+ * This node is parenthesised twice, it certainly has at least one pair of `extra` parentheses.
+ * If the --fix option is on, the current fixing iteration will remove only one pair of parentheses.
+ * The remaining pair is safely enclosing the 'in' expression.
+ */
+ return;
+ }
+
+ // Exclude the outermost node only.
+ if (!nodeToExclude) {
+ nodeToExclude = pathNode;
+ }
+
+ // Don't break the loop here, there might be some safe nodes or parentheses that will stay inside.
+
+ } else {
+
+ // This node will stay parenthesised, the 'in' expression in safely enclosed by '()'.
+ return;
+ }
+ }
+ }
+
+ // Exclude the node from the list (i.e. treat parentheses as necessary)
+ removeFromCurrentReportsBuffer(nodeToExclude);
+ });
+ }
+
+ endCurrentReportsBuffering();
},
IfStatement(node) {
@@ -664,6 +878,16 @@ module.exports = {
}).forEach(property => report(property.value));
},
+ Property(node) {
+ if (node.computed) {
+ const { key } = node;
+
+ if (key && hasExcessParens(key) && precedence(key) >= PRECEDENCE_OF_ASSIGNMENT_EXPR) {
+ report(key);
+ }
+ }
+ },
+
ReturnStatement(node) {
const returnToken = sourceCode.getFirstToken(node);
diff --git a/tools/node_modules/eslint/lib/rules/no-param-reassign.js b/tools/node_modules/eslint/lib/rules/no-param-reassign.js
index 880ff93cb5..9b8c828d2c 100644
--- a/tools/node_modules/eslint/lib/rules/no-param-reassign.js
+++ b/tools/node_modules/eslint/lib/rules/no-param-reassign.js
@@ -67,7 +67,8 @@ module.exports = {
let node = reference.identifier;
let parent = node.parent;
- while (parent && !stopNodePattern.test(parent.type)) {
+ while (parent && (!stopNodePattern.test(parent.type) ||
+ parent.type === "ForInStatement" || parent.type === "ForOfStatement")) {
switch (parent.type) {
// e.g. foo.a = 0;
@@ -85,6 +86,16 @@ module.exports = {
}
break;
+ // e.g. for (foo.a in b) {}
+ case "ForInStatement":
+ case "ForOfStatement":
+ if (parent.left === node) {
+ return true;
+ }
+
+ // this is a stop node for parent.right and parent.body
+ return false;
+
// EXCLUDES: e.g. cache.get(foo.a).b = 0;
case "CallExpression":
if (parent.callee !== node) {
diff --git a/tools/node_modules/eslint/lib/rules/prefer-const.js b/tools/node_modules/eslint/lib/rules/prefer-const.js
index 68c07da4ed..854da310e4 100644
--- a/tools/node_modules/eslint/lib/rules/prefer-const.js
+++ b/tools/node_modules/eslint/lib/rules/prefer-const.js
@@ -420,8 +420,9 @@ module.exports = {
let shouldFix = varDeclParent &&
- // Don't do a fix unless the variable is initialized (or it's in a for-in or for-of loop)
- (varDeclParent.parent.type === "ForInStatement" || varDeclParent.parent.type === "ForOfStatement" || varDeclParent.declarations[0].init) &&
+ // Don't do a fix unless all variables in the declarations are initialized (or it's in a for-in or for-of loop)
+ (varDeclParent.parent.type === "ForInStatement" || varDeclParent.parent.type === "ForOfStatement" ||
+ varDeclParent.declarations.every(declaration => declaration.init)) &&
/*
* If options.destructuring is "all", then this warning will not occur unless
@@ -450,7 +451,12 @@ module.exports = {
node,
messageId: "useConst",
data: node,
- fix: shouldFix ? fixer => fixer.replaceText(sourceCode.getFirstToken(varDeclParent), "const") : null
+ fix: shouldFix
+ ? fixer => fixer.replaceText(
+ sourceCode.getFirstToken(varDeclParent, t => t.value === varDeclParent.kind),
+ "const"
+ )
+ : null
});
});
}
diff --git a/tools/node_modules/eslint/lib/rules/utils/ast-utils.js b/tools/node_modules/eslint/lib/rules/utils/ast-utils.js
index 1aef4c162d..78ae7bc015 100644
--- a/tools/node_modules/eslint/lib/rules/utils/ast-utils.js
+++ b/tools/node_modules/eslint/lib/rules/utils/ast-utils.js
@@ -37,6 +37,8 @@ const LINEBREAKS = new Set(["\r\n", "\r", "\n", "\u2028", "\u2029"]);
// A set of node types that can contain a list of statements
const STATEMENT_LIST_PARENTS = new Set(["Program", "BlockStatement", "SwitchCase"]);
+const DECIMAL_INTEGER_PATTERN = /^(0|[1-9]\d*)$/u;
+
/**
* Checks reference if is non initializer and writable.
* @param {Reference} reference - A reference to check.
@@ -284,6 +286,16 @@ function isCommaToken(token) {
}
/**
+ * Checks if the given token is a dot token or not.
+ *
+ * @param {Token} token - The token to check.
+ * @returns {boolean} `true` if the token is a dot token.
+ */
+function isDotToken(token) {
+ return token.value === "." && token.type === "Punctuator";
+}
+
+/**
* Checks if the given token is a semicolon token or not.
*
* @param {Token} token - The token to check.
@@ -462,12 +474,14 @@ module.exports = {
isColonToken,
isCommaToken,
isCommentToken,
+ isDotToken,
isKeywordToken,
isNotClosingBraceToken: negate(isClosingBraceToken),
isNotClosingBracketToken: negate(isClosingBracketToken),
isNotClosingParenToken: negate(isClosingParenToken),
isNotColonToken: negate(isColonToken),
isNotCommaToken: negate(isCommaToken),
+ isNotDotToken: negate(isDotToken),
isNotOpeningBraceToken: negate(isOpeningBraceToken),
isNotOpeningBracketToken: negate(isOpeningBracketToken),
isNotOpeningParenToken: negate(isOpeningParenToken),
@@ -988,7 +1002,18 @@ module.exports = {
* '5' // false
*/
isDecimalInteger(node) {
- return node.type === "Literal" && typeof node.value === "number" && /^(0|[1-9]\d*)$/u.test(node.raw);
+ return node.type === "Literal" && typeof node.value === "number" &&
+ DECIMAL_INTEGER_PATTERN.test(node.raw);
+ },
+
+ /**
+ * Determines whether this token is a decimal integer numeric token.
+ * This is similar to isDecimalInteger(), but for tokens.
+ * @param {Token} token - The token to check.
+ * @returns {boolean} `true` if this token is a decimal integer.
+ */
+ isDecimalIntegerNumericToken(token) {
+ return token.type === "Numeric" && DECIMAL_INTEGER_PATTERN.test(token.value);
},
/**
diff --git a/tools/node_modules/eslint/lib/cli-engine/naming.js b/tools/node_modules/eslint/lib/shared/naming.js
index b99155f15c..b99155f15c 100644
--- a/tools/node_modules/eslint/lib/cli-engine/naming.js
+++ b/tools/node_modules/eslint/lib/shared/naming.js