tools: update ESLint to 5.9.0

Update ESLint to 5.9.0.

PR-URL: https://github.com/nodejs/node/pull/24280
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
This commit is contained in:
cjihrig 2018-11-09 14:00:16 -05:00 committed by Rich Trott
parent 0229e378e8
commit d72d43f9bf
369 changed files with 2470 additions and 1747 deletions

View File

@ -19,8 +19,10 @@ const fs = require("fs"),
path = require("path"),
defaultOptions = require("../conf/default-cli-options"),
Linter = require("./linter"),
lodash = require("lodash"),
IgnoredPaths = require("./ignored-paths"),
Config = require("./config"),
ConfigOps = require("./config/config-ops"),
LintResultCache = require("./util/lint-result-cache"),
globUtils = require("./util/glob-utils"),
validator = require("./config/config-validator"),
@ -31,6 +33,7 @@ const fs = require("fs"),
const debug = require("debug")("eslint:cli-engine");
const resolver = new ModuleResolver();
const validFixTypes = new Set(["problem", "suggestion", "layout"]);
//------------------------------------------------------------------------------
// Typedefs
@ -48,6 +51,7 @@ const resolver = new ModuleResolver();
* @property {string[]} envs An array of environments to load.
* @property {string[]} extensions An array of file extensions to check.
* @property {boolean|Function} fix Execute in autofix mode. If a function, should return a boolean.
* @property {string[]} fixTypes Array of rule types to apply fixes for.
* @property {string[]} globals An array of global variables to declare.
* @property {boolean} ignore False disables use of .eslintignore.
* @property {string} ignorePath The ignore file to use instead of .eslintignore.
@ -84,6 +88,21 @@ const resolver = new ModuleResolver();
// Helpers
//------------------------------------------------------------------------------
/**
* Determines if each fix type in an array is supported by ESLint and throws
* an error if not.
* @param {string[]} fixTypes An array of fix types to check.
* @returns {void}
* @throws {Error} If an invalid fix type is found.
*/
function validateFixTypes(fixTypes) {
for (const fixType of fixTypes) {
if (!validFixTypes.has(fixType)) {
throw new Error(`Invalid fix type "${fixType}" found.`);
}
}
}
/**
* It will calculate the error and warning count for collection of messages per file
* @param {Object[]} messages - Collection of messages
@ -142,7 +161,7 @@ function calculateStatsPerRun(results) {
* @param {boolean} allowInlineConfig Allow/ignore comments that change config.
* @param {boolean} reportUnusedDisableDirectives Allow/ignore comments that change config.
* @param {Linter} linter Linter context
* @returns {LintResult} The results for linting on this text.
* @returns {{rules: LintResult, config: Object}} The results for linting on this text and the fully-resolved config for it.
* @private
*/
function processText(text, configHelper, filename, fix, allowInlineConfig, reportUnusedDisableDirectives, linter) {
@ -174,7 +193,6 @@ function processText(text, configHelper, filename, fix, allowInlineConfig, repor
}
const autofixingEnabled = typeof fix !== "undefined" && (!processor || processor.supportsAutofix);
const fixedResult = linter.verifyAndFix(text, config, {
filename: effectiveFilename,
allowInlineConfig,
@ -183,7 +201,6 @@ function processText(text, configHelper, filename, fix, allowInlineConfig, repor
preprocess: processor && (rawText => processor.preprocess(rawText, effectiveFilename)),
postprocess: processor && (problemLists => processor.postprocess(problemLists, effectiveFilename))
});
const stats = calculateStatsPerFile(fixedResult.messages);
const result = {
@ -203,7 +220,7 @@ function processText(text, configHelper, filename, fix, allowInlineConfig, repor
result.source = text;
}
return result;
return { result, config };
}
/**
@ -213,24 +230,22 @@ function processText(text, configHelper, filename, fix, allowInlineConfig, repor
* @param {Object} configHelper The configuration options for ESLint.
* @param {Object} options The CLIEngine options object.
* @param {Linter} linter Linter context
* @returns {LintResult} The results for linting on this file.
* @returns {{rules: LintResult, config: Object}} The results for linting on this text and the fully-resolved config for it.
* @private
*/
function processFile(filename, configHelper, options, linter) {
const text = fs.readFileSync(path.resolve(filename), "utf8"),
result = processText(
text,
configHelper,
filename,
options.fix,
options.allowInlineConfig,
options.reportUnusedDisableDirectives,
linter
);
return result;
const text = fs.readFileSync(path.resolve(filename), "utf8");
return processText(
text,
configHelper,
filename,
options.fix,
options.allowInlineConfig,
options.reportUnusedDisableDirectives,
linter
);
}
/**
@ -272,6 +287,33 @@ function createIgnoreResult(filePath, baseDir) {
};
}
/**
* Produces rule warnings (i.e. deprecation) from configured rules
* @param {(Array<string>|Set<string>)} usedRules - Rules configured
* @param {Map} loadedRules - Map of loaded rules
* @returns {Array<Object>} Contains rule warnings
* @private
*/
function createRuleDeprecationWarnings(usedRules, loadedRules) {
const usedDeprecatedRules = [];
usedRules.forEach(name => {
const loadedRule = loadedRules.get(name);
if (loadedRule && loadedRule.meta && loadedRule.meta.deprecated) {
const deprecatedRule = { ruleId: name };
const replacedBy = lodash.get(loadedRule, "meta.replacedBy", []);
if (replacedBy.every(newRule => lodash.isString(newRule))) {
deprecatedRule.replacedBy = replacedBy;
}
usedDeprecatedRules.push(deprecatedRule);
}
});
return usedDeprecatedRules;
}
/**
* Checks if the given message is an error message.
@ -429,6 +471,33 @@ class CLIEngine {
*/
this._lintResultCache = new LintResultCache(cacheFile, this.config);
}
// setup special filter for fixes
if (this.options.fix && this.options.fixTypes && this.options.fixTypes.length > 0) {
debug(`Using fix types ${this.options.fixTypes}`);
// throw an error if any invalid fix types are found
validateFixTypes(this.options.fixTypes);
// convert to Set for faster lookup
const fixTypes = new Set(this.options.fixTypes);
// save original value of options.fix in case it's a function
const originalFix = (typeof this.options.fix === "function")
? this.options.fix : () => this.options.fix;
// create a cache of rules (but don't populate until needed)
this._rulesCache = null;
this.options.fix = lintResult => {
const rule = this._rulesCache.get(lintResult.ruleId);
const matches = rule.meta && fixTypes.has(rule.meta.type);
return matches && originalFix(lintResult);
};
}
}
getRules() {
@ -511,6 +580,7 @@ class CLIEngine {
const startTime = Date.now();
const fileList = globUtils.listFilesToProcess(patterns, options);
const allUsedRules = new Set();
const results = fileList.map(fileInfo => {
if (fileInfo.ignored) {
return createIgnoreResult(fileInfo.filename, options.cwd);
@ -532,9 +602,20 @@ class CLIEngine {
}
}
// if there's a cache, populate it
if ("_rulesCache" in this) {
this._rulesCache = this.getRules();
}
debug(`Processing ${fileInfo.filename}`);
return processFile(fileInfo.filename, configHelper, options, this.linter);
const { result, config } = processFile(fileInfo.filename, configHelper, options, this.linter);
Object.keys(config.rules)
.filter(ruleId => ConfigOps.getRuleSeverity(config.rules[ruleId]))
.forEach(ruleId => allUsedRules.add(ruleId));
return result;
});
if (options.cache) {
@ -555,6 +636,8 @@ class CLIEngine {
const stats = calculateStatsPerRun(results);
const usedDeprecatedRules = createRuleDeprecationWarnings(allUsedRules, this.getRules());
debug(`Linting complete in: ${Date.now() - startTime}ms`);
return {
@ -562,7 +645,8 @@ class CLIEngine {
errorCount: stats.errorCount,
warningCount: stats.warningCount,
fixableErrorCount: stats.fixableErrorCount,
fixableWarningCount: stats.fixableWarningCount
fixableWarningCount: stats.fixableWarningCount,
usedDeprecatedRules
};
}
@ -585,22 +669,34 @@ class CLIEngine {
const resolvedFilename = filename && !path.isAbsolute(filename)
? path.resolve(options.cwd, filename)
: filename;
let usedDeprecatedRules;
if (resolvedFilename && ignoredPaths.contains(resolvedFilename)) {
if (warnIgnored) {
results.push(createIgnoreResult(resolvedFilename, options.cwd));
}
usedDeprecatedRules = [];
} else {
results.push(
processText(
text,
configHelper,
resolvedFilename,
options.fix,
options.allowInlineConfig,
options.reportUnusedDisableDirectives,
this.linter
)
// if there's a cache, populate it
if ("_rulesCache" in this) {
this._rulesCache = this.getRules();
}
const { result, config } = processText(
text,
configHelper,
resolvedFilename,
options.fix,
options.allowInlineConfig,
options.reportUnusedDisableDirectives,
this.linter
);
results.push(result);
usedDeprecatedRules = createRuleDeprecationWarnings(
Object.keys(config.rules).filter(rule => ConfigOps.getRuleSeverity(config.rules[rule])),
this.getRules()
);
}
@ -611,7 +707,8 @@ class CLIEngine {
errorCount: stats.errorCount,
warningCount: stats.warningCount,
fixableErrorCount: stats.fixableErrorCount,
fixableWarningCount: stats.fixableWarningCount
fixableWarningCount: stats.fixableWarningCount,
usedDeprecatedRules
};
}

View File

@ -64,6 +64,7 @@ function translateOptions(cliOptions) {
cacheFile: cliOptions.cacheFile,
cacheLocation: cliOptions.cacheLocation,
fix: (cliOptions.fix || cliOptions.fixDryRun) && (cliOptions.quiet ? quietFixPredicate : true),
fixTypes: cliOptions.fixType,
allowInlineConfig: cliOptions.inlineConfig,
reportUnusedDisableDirectives: cliOptions.reportUnusedDisableDirectives
};
@ -187,8 +188,12 @@ const cli = {
return 2;
}
const engine = new CLIEngine(translateOptions(currentOptions));
if (currentOptions.fixType && !currentOptions.fix && !currentOptions.fixDryRun) {
log.error("The --fix-type option requires either --fix or --fix-dry-run.");
return 2;
}
const engine = new CLIEngine(translateOptions(currentOptions));
const report = useStdin ? engine.executeOnText(text, currentOptions.stdinFilename, true) : engine.executeOnFiles(files);
if (currentOptions.fix) {

View File

@ -97,6 +97,11 @@ module.exports = optionator({
default: false,
description: "Automatically fix problems without saving the changes to the file system"
},
{
option: "fix-type",
type: "Array",
description: "Specify the types of fixes to apply (problem, suggestion, layout)"
},
{
heading: "Ignoring files"
},

View File

@ -72,12 +72,15 @@ function isPropertyDescriptor(node) {
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "enforce getter and setter pairs in objects",
category: "Best Practices",
recommended: false,
url: "https://eslint.org/docs/rules/accessor-pairs"
},
schema: [{
type: "object",
properties: {
@ -90,6 +93,7 @@ module.exports = {
},
additionalProperties: false
}],
messages: {
getter: "Getter is not present.",
setter: "Setter is not present."

View File

@ -13,13 +13,17 @@ const astUtils = require("../util/ast-utils");
module.exports = {
meta: {
type: "layout",
docs: {
description: "enforce linebreaks after opening and before closing array brackets",
category: "Stylistic Issues",
recommended: false,
url: "https://eslint.org/docs/rules/array-bracket-newline"
},
fixable: "whitespace",
schema: [
{
oneOf: [
@ -42,6 +46,7 @@ module.exports = {
]
}
],
messages: {
unexpectedOpeningLinebreak: "There should be no linebreak after '['.",
unexpectedClosingLinebreak: "There should be no linebreak before ']'.",

View File

@ -12,13 +12,17 @@ const astUtils = require("../util/ast-utils");
module.exports = {
meta: {
type: "layout",
docs: {
description: "enforce consistent spacing inside array brackets",
category: "Stylistic Issues",
recommended: false,
url: "https://eslint.org/docs/rules/array-bracket-spacing"
},
fixable: "whitespace",
schema: [
{
enum: ["always", "never"]
@ -39,6 +43,7 @@ module.exports = {
additionalProperties: false
}
],
messages: {
unexpectedSpaceAfter: "There should be no space after '{{tokenValue}}'.",
unexpectedSpaceBefore: "There should be no space before '{{tokenValue}}'.",

View File

@ -141,6 +141,8 @@ function isCallbackOfArrayMethod(node) {
module.exports = {
meta: {
type: "problem",
docs: {
description: "enforce `return` statements in callbacks of array methods",
category: "Best Practices",

View File

@ -13,13 +13,17 @@ const astUtils = require("../util/ast-utils");
module.exports = {
meta: {
type: "layout",
docs: {
description: "enforce line breaks after each array element",
category: "Stylistic Issues",
recommended: false,
url: "https://eslint.org/docs/rules/array-element-newline"
},
fixable: "whitespace",
schema: [
{
oneOf: [

View File

@ -16,6 +16,8 @@ const astUtils = require("../util/ast-utils");
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "require braces around arrow function bodies",
category: "ECMAScript 6",

View File

@ -16,6 +16,8 @@ const astUtils = require("../util/ast-utils");
module.exports = {
meta: {
type: "layout",
docs: {
description: "require parentheses around arrow function arguments",
category: "ECMAScript 6",

View File

@ -16,6 +16,8 @@ const astUtils = require("../util/ast-utils");
module.exports = {
meta: {
type: "layout",
docs: {
description: "enforce consistent spacing before and after the arrow in arrow functions",
category: "ECMAScript 6",

View File

@ -10,6 +10,8 @@
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "enforce the use of variables within the scope they are defined",
category: "Best Practices",

View File

@ -13,6 +13,8 @@ const util = require("../util/ast-utils");
module.exports = {
meta: {
type: "layout",
docs: {
description: "disallow or enforce spaces inside of blocks after opening block and before closing block",
category: "Stylistic Issues",

View File

@ -13,6 +13,8 @@ const astUtils = require("../util/ast-utils");
module.exports = {
meta: {
type: "layout",
docs: {
description: "enforce consistent brace style for blocks",
category: "Stylistic Issues",

View File

@ -10,6 +10,8 @@
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "require `return` statements after callbacks",
category: "Node.js and CommonJS",

View File

@ -11,6 +11,8 @@
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "enforce camelcase naming convention",
category: "Stylistic Issues",

View File

@ -108,13 +108,17 @@ function createRegExpForIgnorePatterns(normalizedOptions) {
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "enforce or disallow capitalization of the first letter of a comment",
category: "Stylistic Issues",
recommended: false,
url: "https://eslint.org/docs/rules/capitalized-comments"
},
fixable: "code",
schema: [
{ enum: ["always", "never"] },
{

View File

@ -11,12 +11,15 @@
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "enforce that class methods utilize `this`",
category: "Best Practices",
recommended: false,
url: "https://eslint.org/docs/rules/class-methods-use-this"
},
schema: [{
type: "object",
properties: {

View File

@ -76,13 +76,17 @@ function normalizeOptions(optionValue) {
module.exports = {
meta: {
type: "layout",
docs: {
description: "require or disallow trailing commas",
category: "Stylistic Issues",
recommended: false,
url: "https://eslint.org/docs/rules/comma-dangle"
},
fixable: "code",
schema: {
definitions: {
value: {

View File

@ -12,6 +12,8 @@ const astUtils = require("../util/ast-utils");
module.exports = {
meta: {
type: "layout",
docs: {
description: "enforce consistent spacing before and after commas",
category: "Stylistic Issues",

View File

@ -13,13 +13,17 @@ const astUtils = require("../util/ast-utils");
module.exports = {
meta: {
type: "layout",
docs: {
description: "enforce consistent comma style",
category: "Stylistic Issues",
recommended: false,
url: "https://eslint.org/docs/rules/comma-style"
},
fixable: "code",
schema: [
{
enum: ["first", "last"]
@ -37,6 +41,7 @@ module.exports = {
additionalProperties: false
}
],
messages: {
unexpectedLineBeforeAndAfterComma: "Bad line breaking before and after ','.",
expectedCommaFirst: "',' should be placed first.",

View File

@ -20,6 +20,8 @@ const astUtils = require("../util/ast-utils");
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "enforce a maximum cyclomatic complexity allowed in a program",
category: "Best Practices",

View File

@ -12,6 +12,8 @@ const astUtils = require("../util/ast-utils");
module.exports = {
meta: {
type: "layout",
docs: {
description: "enforce consistent spacing inside computed property brackets",
category: "Stylistic Issues",

View File

@ -53,6 +53,8 @@ function isClassConstructor(node) {
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "require `return` statements to either always or never specify values",
category: "Best Practices",

View File

@ -10,6 +10,8 @@
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "enforce consistent naming when capturing the current execution context",
category: "Stylistic Issues",

View File

@ -92,6 +92,8 @@ function isPossibleConstructor(node) {
module.exports = {
meta: {
type: "problem",
docs: {
description: "require `super()` calls in constructors",
category: "ECMAScript 6",

View File

@ -16,6 +16,8 @@ const astUtils = require("../util/ast-utils");
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "enforce consistent brace style for all control statements",
category: "Best Practices",

View File

@ -12,6 +12,8 @@ const DEFAULT_COMMENT_PATTERN = /^no default$/i;
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "require `default` cases in `switch` statements",
category: "Best Practices",

View File

@ -13,6 +13,8 @@ const astUtils = require("../util/ast-utils");
module.exports = {
meta: {
type: "layout",
docs: {
description: "enforce consistent newlines before and after dots",
category: "Best Practices",

View File

@ -19,6 +19,8 @@ const keywords = require("../util/keywords");
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "enforce dot notation whenever possible",
category: "Best Practices",

View File

@ -16,18 +16,23 @@ const lodash = require("lodash");
module.exports = {
meta: {
type: "layout",
docs: {
description: "require or disallow newline at the end of files",
category: "Stylistic Issues",
recommended: false,
url: "https://eslint.org/docs/rules/eol-last"
},
fixable: "whitespace",
schema: [
{
enum: ["always", "never", "unix", "windows"]
}
],
messages: {
missing: "Newline required at end of file but not found.",
unexpected: "Newline not allowed at end of file."

View File

@ -17,6 +17,8 @@ const astUtils = require("../util/ast-utils");
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "require the use of `===` and `!==`",
category: "Best Practices",

View File

@ -11,14 +11,18 @@
module.exports = {
meta: {
type: "problem",
docs: {
description: "enforce \"for\" loop update clause moving the counter in the right direction.",
category: "Possible Errors",
recommended: true,
url: "https://eslint.org/docs/rules/for-direction"
},
fixable: null,
schema: [],
messages: {
incorrectDirection: "The update clause in this loop moves the variable in the wrong direction."
}

View File

@ -17,6 +17,8 @@ const astUtils = require("../util/ast-utils");
module.exports = {
meta: {
type: "layout",
docs: {
description: "require or disallow spacing between function identifiers and their invocations",
category: "Stylistic Issues",
@ -25,6 +27,7 @@ module.exports = {
},
fixable: "whitespace",
schema: {
anyOf: [
{
@ -58,6 +61,7 @@ module.exports = {
}
]
},
messages: {
unexpected: "Unexpected newline between function name and paren.",
missing: "Missing space between function name and paren."

View File

@ -70,6 +70,8 @@ const optionsObject = {
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "require function names to match the name of the variable or property to which they are assigned",
category: "Stylistic Issues",
@ -88,6 +90,7 @@ module.exports = {
items: [optionsObject]
}]
},
messages: {
matchProperty: "Function name `{{funcName}}` should match property name `{{name}}`",
matchVariable: "Function name `{{funcName}}` should match variable name `{{name}}`",

View File

@ -26,6 +26,8 @@ function isFunctionName(variable) {
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "require or disallow named `function` expressions",
category: "Stylistic Issues",
@ -58,6 +60,7 @@ module.exports = {
}
]
},
messages: {
unnamed: "Unexpected unnamed {{name}}.",
named: "Unexpected named {{name}}."

View File

@ -10,6 +10,8 @@
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "enforce the consistent use of either `function` declarations or expressions",
category: "Stylistic Issues",
@ -31,6 +33,7 @@ module.exports = {
additionalProperties: false
}
],
messages: {
expression: "Expected a function expression.",
declaration: "Expected a function declaration."

View File

@ -16,13 +16,17 @@ const astUtils = require("../util/ast-utils");
module.exports = {
meta: {
type: "layout",
docs: {
description: "enforce consistent line breaks inside function parentheses",
category: "Stylistic Issues",
recommended: false,
url: "https://eslint.org/docs/rules/function-paren-newline"
},
fixable: "whitespace",
schema: [
{
oneOf: [
@ -42,6 +46,7 @@ module.exports = {
]
}
],
messages: {
expectedBefore: "Expected newline before ')'.",
expectedAfter: "Expected newline after '('.",

View File

@ -27,6 +27,8 @@ const OVERRIDE_SCHEMA = {
module.exports = {
meta: {
type: "layout",
docs: {
description: "enforce consistent spacing around `*` operators in generator functions",
category: "ECMAScript 6",
@ -56,6 +58,7 @@ module.exports = {
]
}
],
messages: {
missingBefore: "Missing space before *.",
missingAfter: "Missing space after *.",

View File

@ -44,13 +44,17 @@ function getId(node) {
module.exports = {
meta: {
type: "problem",
docs: {
description: "enforce `return` statements in getters",
category: "Possible Errors",
recommended: true,
url: "https://eslint.org/docs/rules/getter-return"
},
fixable: null,
schema: [
{
type: "object",
@ -62,6 +66,7 @@ module.exports = {
additionalProperties: false
}
],
messages: {
expected: "Expected to return a value in {{name}}.",
expectedAlways: "Expected {{name}} to always return a value."

View File

@ -48,6 +48,8 @@ function isShadowed(scope, node) {
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "require `require()` calls to be placed at top-level module scope",
category: "Node.js and CommonJS",

View File

@ -11,6 +11,8 @@
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "require `for-in` loops to include an `if` statement",
category: "Best Practices",

View File

@ -11,6 +11,8 @@
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "require error handling in callbacks",
category: "Node.js and CommonJS",

View File

@ -12,6 +12,8 @@
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "disallow specified identifiers",
category: "Stylistic Issues",

View File

@ -12,6 +12,8 @@
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "enforce minimum and maximum identifier lengths",
category: "Stylistic Issues",

View File

@ -11,6 +11,8 @@
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "require identifiers to match a specified regular expression",
category: "Stylistic Issues",
@ -27,6 +29,12 @@ module.exports = {
properties: {
properties: {
type: "boolean"
},
onlyDeclarations: {
type: "boolean"
},
ignoreDestructuring: {
type: "boolean"
}
}
}
@ -36,15 +44,25 @@ module.exports = {
create(context) {
//--------------------------------------------------------------------------
// Helpers
// Options
//--------------------------------------------------------------------------
const pattern = context.options[0] || "^.+$",
regexp = new RegExp(pattern);
const options = context.options[1] || {},
properties = !!options.properties,
onlyDeclarations = !!options.onlyDeclarations;
onlyDeclarations = !!options.onlyDeclarations,
ignoreDestructuring = !!options.ignoreDestructuring;
//--------------------------------------------------------------------------
// Helpers
//--------------------------------------------------------------------------
// contains reported nodes to avoid reporting twice on destructuring with shorthand notation
const reported = new Map();
const ALLOWED_PARENT_TYPES = new Set(["CallExpression", "NewExpression"]);
const DECLARATION_TYPES = new Set(["FunctionDeclaration", "VariableDeclarator"]);
const IMPORT_TYPES = new Set(["ImportSpecifier", "ImportNamespaceSpecifier", "ImportDefaultSpecifier"]);
/**
* Checks if a string matches the provided pattern
@ -56,6 +74,26 @@ module.exports = {
return !regexp.test(name);
}
/**
* Checks if a parent of a node is an ObjectPattern.
* @param {ASTNode} node The node to check.
* @returns {boolean} if the node is inside an ObjectPattern
* @private
*/
function isInsideObjectPattern(node) {
let { parent } = node;
while (parent) {
if (parent.type === "ObjectPattern") {
return true;
}
parent = parent.parent;
}
return false;
}
/**
* Verifies if we should report an error or not based on the effective
* parent node and the identifier name.
@ -64,9 +102,8 @@ module.exports = {
* @returns {boolean} whether an error should be reported or not
*/
function shouldReport(effectiveParent, name) {
return effectiveParent.type !== "CallExpression" &&
effectiveParent.type !== "NewExpression" &&
isInvalid(name);
return (!onlyDeclarations || DECLARATION_TYPES.has(effectiveParent.type)) &&
!ALLOWED_PARENT_TYPES.has(effectiveParent.type) && isInvalid(name);
}
/**
@ -76,14 +113,17 @@ module.exports = {
* @private
*/
function report(node) {
context.report({
node,
message: "Identifier '{{name}}' does not match the pattern '{{pattern}}'.",
data: {
name: node.name,
pattern
}
});
if (!reported.has(node)) {
context.report({
node,
message: "Identifier '{{name}}' does not match the pattern '{{pattern}}'.",
data: {
name: node.name,
pattern
}
});
reported.set(node, true);
}
}
return {
@ -106,36 +146,70 @@ module.exports = {
report(node);
}
// Report AssignmentExpressions only if they are the left side of the assignment
// Report AssignmentExpressions left side's assigned variable id
} else if (effectiveParent.type === "AssignmentExpression" &&
(effectiveParent.right.type !== "MemberExpression" ||
effectiveParent.left.type === "MemberExpression" &&
effectiveParent.left.property.name === name)) {
effectiveParent.left.property.name === node.name) {
if (isInvalid(name)) {
report(node);
}
// Report AssignmentExpressions only if they are the left side of the assignment
} else if (effectiveParent.type === "AssignmentExpression" && effectiveParent.right.type !== "MemberExpression") {
if (isInvalid(name)) {
report(node);
}
}
} else if (parent.type === "Property") {
/*
* Properties have their own rules, and
* AssignmentPattern nodes can be treated like Properties:
* e.g.: const { no_camelcased = false } = bar;
*/
} else if (parent.type === "Property" || parent.type === "AssignmentPattern") {
if (!properties || parent.key.name !== name) {
if (parent.parent && parent.parent.type === "ObjectPattern") {
if (parent.shorthand && parent.value.left && isInvalid(name)) {
report(node);
}
const assignmentKeyEqualsValue = parent.key.name === parent.value.name;
// prevent checking righthand side of destructured object
if (!assignmentKeyEqualsValue && parent.key === node) {
return;
}
const valueIsInvalid = parent.value.name && isInvalid(name);
// ignore destructuring if the option is set, unless a new identifier is created
if (valueIsInvalid && !(assignmentKeyEqualsValue && ignoreDestructuring)) {
report(node);
}
}
// never check properties or always ignore destructuring
if (!properties || (ignoreDestructuring && isInsideObjectPattern(node))) {
return;
}
if (shouldReport(effectiveParent, name)) {
// don't check right hand side of AssignmentExpression to prevent duplicate warnings
if (parent.right !== node && shouldReport(effectiveParent, name)) {
report(node);
}
} else {
const isDeclaration = effectiveParent.type === "FunctionDeclaration" || effectiveParent.type === "VariableDeclarator";
// Check if it's an import specifier
} else if (IMPORT_TYPES.has(parent.type)) {
if (onlyDeclarations && !isDeclaration) {
return;
}
if (shouldReport(effectiveParent, name)) {
// Report only if the local imported identifier is invalid
if (parent.local && parent.local.name === node.name && isInvalid(name)) {
report(node);
}
// Report anything that is invalid that isn't a CallExpression
} else if (shouldReport(effectiveParent, name)) {
report(node);
}
}

View File

@ -9,13 +9,17 @@
//------------------------------------------------------------------------------
module.exports = {
meta: {
type: "layout",
docs: {
description: "enforce the location of arrow function bodies",
category: "Stylistic Issues",
recommended: false,
url: "https://eslint.org/docs/rules/implicit-arrow-linebreak"
},
fixable: "whitespace",
schema: [
{
enum: ["beside", "below"]

View File

@ -21,16 +21,19 @@ const astUtils = require("../util/ast-utils");
/* istanbul ignore next: this rule has known coverage issues, but it's deprecated and shouldn't be updated in the future anyway. */
module.exports = {
meta: {
type: "layout",
docs: {
description: "enforce consistent indentation",
category: "Stylistic Issues",
recommended: false,
replacedBy: ["indent"],
url: "https://eslint.org/docs/rules/indent-legacy"
},
deprecated: true,
replacedBy: ["indent"],
fixable: "whitespace",
schema: [

View File

@ -490,6 +490,8 @@ const ELEMENT_LIST_SCHEMA = {
module.exports = {
meta: {
type: "layout",
docs: {
description: "enforce consistent indentation",
category: "Stylistic Issues",

View File

@ -44,6 +44,8 @@ function isInitialized(node) {
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "require or disallow initialization in variable declarations",
category: "Variables",

View File

@ -38,6 +38,8 @@ const QUOTE_SETTINGS = {
module.exports = {
meta: {
type: "layout",
docs: {
description: "enforce the consistent use of either double or single quotes in JSX attributes",
category: "Stylistic Issues",

View File

@ -128,6 +128,8 @@ const messages = {
module.exports = {
meta: {
type: "layout",
docs: {
description: "enforce consistent spacing between keys and values in object literal properties",
category: "Stylistic Issues",
@ -360,10 +362,9 @@ module.exports = {
*/
function isKeyValueProperty(property) {
return !(
property.method ||
(property.method ||
property.shorthand ||
property.kind !== "init" ||
property.type !== "Property" // Could be "ExperimentalSpreadProperty" or "SpreadElement"
property.kind !== "init" || property.type !== "Property") // Could be "ExperimentalSpreadProperty" or "SpreadElement"
);
}

View File

@ -65,6 +65,8 @@ function isCloseParenOfTemplate(token) {
module.exports = {
meta: {
type: "layout",
docs: {
description: "enforce consistent spacing before and after keywords",
category: "Stylistic Issues",

View File

@ -12,6 +12,8 @@ const astUtils = require("../util/ast-utils");
module.exports = {
meta: {
type: "layout",
docs: {
description: "enforce position of line comments",
category: "Stylistic Issues",

View File

@ -17,6 +17,8 @@ const astUtils = require("../util/ast-utils");
module.exports = {
meta: {
type: "layout",
docs: {
description: "enforce consistent linebreak style",
category: "Stylistic Issues",

View File

@ -52,6 +52,8 @@ function getCommentLineNums(comments) {
module.exports = {
meta: {
type: "layout",
docs: {
description: "require empty lines around comments",
category: "Stylistic Issues",

View File

@ -14,13 +14,15 @@ const astUtils = require("../util/ast-utils");
module.exports = {
meta: {
type: "layout",
docs: {
description: "require or disallow newlines around directives",
category: "Stylistic Issues",
recommended: false,
replacedBy: ["padding-line-between-statements"],
url: "https://eslint.org/docs/rules/lines-around-directive"
},
schema: [{
oneOf: [
{
@ -41,8 +43,10 @@ module.exports = {
}
]
}],
fixable: "whitespace",
deprecated: true
deprecated: true,
replacedBy: ["padding-line-between-statements"]
},
create(context) {

View File

@ -12,6 +12,8 @@ const astUtils = require("../util/ast-utils");
module.exports = {
meta: {
type: "layout",
docs: {
description: "require or disallow an empty line between class members",
category: "Stylistic Issues",

View File

@ -15,18 +15,22 @@
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "enforce a maximum number of classes per file",
category: "Best Practices",
recommended: false,
url: "https://eslint.org/docs/rules/max-classes-per-file"
},
schema: [
{
type: "integer",
minimum: 1
}
],
messages: {
maximumExceeded: "Number of classes per file must not exceed {{ max }}"
}

View File

@ -11,6 +11,8 @@
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "enforce a maximum depth that blocks can be nested",
category: "Stylistic Issues",

View File

@ -65,6 +65,8 @@ const OPTIONS_OR_INTEGER_SCHEMA = {
module.exports = {
meta: {
type: "layout",
docs: {
description: "enforce a maximum line length",
category: "Stylistic Issues",

View File

@ -69,6 +69,8 @@ function getCommentLineNumbers(comments) {
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "enforce a maximum number of line of code in a function",
category: "Stylistic Issues",

View File

@ -17,6 +17,8 @@ const astUtils = require("../util/ast-utils");
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "enforce a maximum number of lines per file",
category: "Stylistic Issues",

View File

@ -11,6 +11,8 @@
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "enforce a maximum depth that callbacks can be nested",
category: "Stylistic Issues",

View File

@ -19,6 +19,8 @@ const astUtils = require("../util/ast-utils");
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "enforce a maximum number of parameters in function definitions",
category: "Stylistic Issues",

View File

@ -16,6 +16,8 @@ const astUtils = require("../util/ast-utils");
module.exports = {
meta: {
type: "layout",
docs: {
description: "enforce a maximum number of statements allowed per line",
category: "Stylistic Issues",

View File

@ -19,6 +19,8 @@ const astUtils = require("../util/ast-utils");
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "enforce a maximum number of statements allowed in function blocks",
category: "Stylistic Issues",

View File

@ -12,12 +12,15 @@ const astUtils = require("../util/ast-utils");
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "enforce a particular style for multiline comments",
category: "Stylistic Issues",
recommended: false,
url: "https://eslint.org/docs/rules/multiline-comment-style"
},
fixable: "whitespace",
schema: [{ enum: ["starred-block", "separate-lines", "bare-block"] }]
},

View File

@ -13,12 +13,15 @@ const astUtils = require("../util/ast-utils");
module.exports = {
meta: {
type: "layout",
docs: {
description: "enforce newlines between operands of ternary expressions",
category: "Stylistic Issues",
recommended: false,
url: "https://eslint.org/docs/rules/multiline-ternary"
},
schema: [
{
enum: ["always", "always-multiline", "never"]

View File

@ -74,6 +74,8 @@ function calculateCapIsNewExceptions(config) {
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "require constructor names to begin with a capital letter",
category: "Stylistic Issues",

View File

@ -21,6 +21,8 @@ const astUtils = require("../util/ast-utils");
module.exports = {
meta: {
type: "layout",
docs: {
description: "require parentheses when invoking a constructor with no arguments",
category: "Stylistic Issues",
@ -29,7 +31,6 @@ module.exports = {
},
schema: [],
fixable: "code"
},

View File

@ -18,11 +18,12 @@ const astUtils = require("../util/ast-utils");
module.exports = {
meta: {
type: "layout",
docs: {
description: "require or disallow an empty line after variable declarations",
category: "Stylistic Issues",
recommended: false,
replacedBy: ["padding-line-between-statements"],
url: "https://eslint.org/docs/rules/newline-after-var"
},
@ -34,7 +35,9 @@ module.exports = {
fixable: "whitespace",
deprecated: true
deprecated: true,
replacedBy: ["padding-line-between-statements"]
},
create(context) {

View File

@ -11,16 +11,19 @@
module.exports = {
meta: {
type: "layout",
docs: {
description: "require an empty line before `return` statements",
category: "Stylistic Issues",
recommended: false,
replacedBy: ["padding-line-between-statements"],
url: "https://eslint.org/docs/rules/newline-before-return"
},
fixable: "whitespace",
schema: [],
deprecated: true
deprecated: true,
replacedBy: ["padding-line-between-statements"]
},
create(context) {

View File

@ -14,13 +14,17 @@ const astUtils = require("../util/ast-utils");
module.exports = {
meta: {
type: "layout",
docs: {
description: "require a newline after each call in a method chain",
category: "Stylistic Issues",
recommended: false,
url: "https://eslint.org/docs/rules/newline-per-chained-call"
},
fixable: "whitespace",
schema: [{
type: "object",
properties: {

View File

@ -74,6 +74,8 @@ function isGlobalThisReferenceOrGlobalWindow(scope, node) {
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "disallow the use of `alert`, `confirm`, and `prompt`",
category: "Best Practices",

View File

@ -11,6 +11,8 @@
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "disallow `Array` constructors",
category: "Stylistic Issues",

View File

@ -10,12 +10,15 @@
module.exports = {
meta: {
type: "problem",
docs: {
description: "disallow using an async function as a Promise executor",
category: "Possible Errors",
recommended: false,
url: "https://eslint.org/docs/rules/no-async-promise-executor"
},
fixable: null,
schema: []
},

View File

@ -55,13 +55,17 @@ function isLooped(node, parent) {
module.exports = {
meta: {
type: "problem",
docs: {
description: "disallow `await` inside of loops",
category: "Possible Errors",
recommended: false,
url: "https://eslint.org/docs/rules/no-await-in-loop"
},
schema: [],
messages: {
unexpectedAwait: "Unexpected `await` inside a loop."
}

View File

@ -22,6 +22,8 @@ const BITWISE_OPERATORS = [
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "disallow bitwise operators",
category: "Stylistic Issues",

View File

@ -10,13 +10,17 @@
module.exports = {
meta: {
type: "problem",
docs: {
description: "disallow use of the `Buffer()` constructor",
category: "Node.js and CommonJS",
recommended: false,
url: "https://eslint.org/docs/rules/no-buffer-constructor"
},
schema: [],
messages: {
deprecated: "{{expr}} is deprecated. Use Buffer.from(), Buffer.alloc(), or Buffer.allocUnsafe() instead."
}

View File

@ -11,6 +11,8 @@
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "disallow the use of `arguments.caller` or `arguments.callee`",
category: "Best Practices",

View File

@ -10,6 +10,8 @@
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "disallow lexical declarations in case clauses",
category: "Best Practices",

View File

@ -18,15 +18,18 @@ const astUtils = require("../util/ast-utils");
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "disallow `catch` clause parameters from shadowing variables in the outer scope",
category: "Variables",
recommended: false,
url: "https://eslint.org/docs/rules/no-catch-shadow",
replacedBy: ["no-shadow"]
url: "https://eslint.org/docs/rules/no-catch-shadow"
},
deprecated: true,
replacedBy: ["no-shadow"],
deprecated: true,
schema: [],
messages: {

View File

@ -13,6 +13,8 @@ const astUtils = require("../util/ast-utils");
module.exports = {
meta: {
type: "problem",
docs: {
description: "disallow reassigning class members",
category: "ECMAScript 6",

View File

@ -10,14 +10,18 @@
module.exports = {
meta: {
type: "problem",
docs: {
description: "disallow comparing against -0",
category: "Possible Errors",
recommended: true,
url: "https://eslint.org/docs/rules/no-compare-neg-zero"
},
fixable: null,
schema: [],
messages: {
unexpected: "Do not use the '{{operator}}' operator to compare against -0."
}

View File

@ -19,6 +19,8 @@ const NODE_DESCRIPTIONS = {
module.exports = {
meta: {
type: "problem",
docs: {
description: "disallow assignment operators in conditional expressions",
category: "Possible Errors",

View File

@ -27,6 +27,8 @@ function isConditional(node) {
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "disallow arrow functions where they could be confused with comparisons",
category: "ECMAScript 6",

View File

@ -17,6 +17,8 @@ const astUtils = require("../util/ast-utils");
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "disallow the use of `console`",
category: "Possible Errors",

View File

@ -13,6 +13,8 @@ const astUtils = require("../util/ast-utils");
module.exports = {
meta: {
type: "problem",
docs: {
description: "disallow reassigning `const` variables",
category: "ECMAScript 6",

View File

@ -11,6 +11,8 @@
module.exports = {
meta: {
type: "problem",
docs: {
description: "disallow constant expressions in conditions",
category: "Possible Errors",

View File

@ -11,6 +11,8 @@
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "disallow `continue` statements",
category: "Stylistic Issues",

View File

@ -6,7 +6,7 @@
"use strict";
const RegExpValidator = require("regexpp").RegExpValidator;
const collector = new class {
const collector = new (class {
constructor() {
this.ecmaVersion = 2018;
this._source = "";
@ -41,7 +41,7 @@ const collector = new class {
}
return this._controlChars;
}
}();
})();
//------------------------------------------------------------------------------
// Rule Definition
@ -49,6 +49,8 @@ const collector = new class {
module.exports = {
meta: {
type: "problem",
docs: {
description: "disallow control characters in regular expressions",
category: "Possible Errors",

View File

@ -11,14 +11,18 @@
module.exports = {
meta: {
type: "problem",
docs: {
description: "disallow the use of `debugger`",
category: "Possible Errors",
recommended: true,
url: "https://eslint.org/docs/rules/no-debugger"
},
fixable: null,
schema: [],
messages: {
unexpected: "Unexpected 'debugger' statement."
}

View File

@ -11,6 +11,8 @@
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "disallow deleting variables",
category: "Variables",

View File

@ -11,6 +11,8 @@
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "disallow division operators explicitly at the beginning of regular expressions",
category: "Best Practices",

View File

@ -11,6 +11,8 @@
module.exports = {
meta: {
type: "problem",
docs: {
description: "disallow duplicate arguments in `function` definitions",
category: "Possible Errors",

View File

@ -11,6 +11,8 @@
module.exports = {
meta: {
type: "problem",
docs: {
description: "disallow duplicate class members",
category: "ECMAScript 6",

View File

@ -84,6 +84,8 @@ class ObjectInfo {
module.exports = {
meta: {
type: "problem",
docs: {
description: "disallow duplicate keys in object literals",
category: "Possible Errors",

View File

@ -12,6 +12,8 @@
module.exports = {
meta: {
type: "problem",
docs: {
description: "disallow duplicate case labels",
category: "Possible Errors",

View File

@ -101,6 +101,8 @@ function handleExports(context, importsInFile, exportsInFile) {
module.exports = {
meta: {
type: "problem",
docs: {
description: "disallow duplicate module imports",
category: "ECMAScript 6",

Some files were not shown because too many files have changed in this diff Show More