tools: update ESLint to 7.0.0-alpha.1

Update ESLint to 7.0.0-alpha.1

PR-URL: https://github.com/nodejs/node/pull/31400
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
This commit is contained in:
cjihrig
2020-02-28 17:07:33 -05:00
committed by Anna Henningsen
parent 7eaa813fcf
commit 2348ca0ce4
118 changed files with 921 additions and 451 deletions

46
tools/node_modules/eslint/README.md generated vendored
View File

@@ -1,9 +1,12 @@
[![NPM version][npm-image]][npm-url]
[![NPM version](https://img.shields.io/npm/v/eslint.svg)](https://www.npmjs.com/package/eslint)
[![Downloads](https://img.shields.io/npm/dm/eslint.svg)](https://www.npmjs.com/package/eslint)
[![Build Status](https://github.com/eslint/eslint/workflows/CI/badge.svg)](https://github.com/eslint/eslint/actions)
[![Downloads][downloads-image]][downloads-url]
[![Bountysource](https://www.bountysource.com/badge/tracker?tracker_id=282608)](https://www.bountysource.com/trackers/282608-eslint?utm_source=282608&utm_medium=shield&utm_campaign=TRACKER_BADGE)
[![Join the chat at https://gitter.im/eslint/eslint](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/eslint/eslint?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Feslint%2Feslint.svg?type=shield)](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Feslint%2Feslint?ref=badge_shield)
<br />
[![Open Collective Backers](https://img.shields.io/opencollective/backers/eslint)](https://opencollective.com/eslint)
[![Open Collective Sponsors](https://img.shields.io/opencollective/sponsors/eslint)](https://opencollective.com/eslint)
[![Join the chat at https://gitter.im/eslint/eslint](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/eslint/eslint?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Follow us on Twitter](https://img.shields.io/twitter/follow/geteslint?label=Follow&style=social)](https://twitter.com/intent/user?screen_name=geteslint)
# ESLint
@@ -185,16 +188,6 @@ The people who manage releases, review feature requests, and meet regularly to e
Nicholas C. Zakas
</a>
</td><td align="center" valign="top" width="11%">
<a href="https://github.com/platinumazure">
<img src="https://github.com/platinumazure.png?s=75" width="75" height="75"><br />
Kevin Partington
</a>
</td><td align="center" valign="top" width="11%">
<a href="https://github.com/ilyavolodin">
<img src="https://github.com/ilyavolodin.png?s=75" width="75" height="75"><br />
Ilya Volodin
</a>
</td><td align="center" valign="top" width="11%">
<a href="https://github.com/btmills">
<img src="https://github.com/btmills.png?s=75" width="75" height="75"><br />
Brandon Mills
@@ -209,11 +202,6 @@ Toru Nagashima
<img src="https://github.com/kaicataldo.png?s=75" width="75" height="75"><br />
Kai Cataldo
</a>
</td><td align="center" valign="top" width="11%">
<a href="https://github.com/not-an-aardvark">
<img src="https://github.com/not-an-aardvark.png?s=75" width="75" height="75"><br />
Teddy Katz
</a>
</td></tr></tbody></table>
@@ -236,16 +224,16 @@ The people who review and implement new features.
The people who review and fix bugs and help triage issues.
<table><tbody><tr><td align="center" valign="top" width="11%">
<a href="https://github.com/gyandeeps">
<img src="https://github.com/gyandeeps.png?s=75" width="75" height="75"><br />
Gyandeep Singh
</a>
</td><td align="center" valign="top" width="11%">
<a href="https://github.com/g-plane">
<img src="https://github.com/g-plane.png?s=75" width="75" height="75"><br />
Pig Fang
</a>
</td><td align="center" valign="top" width="11%">
<a href="https://github.com/yeonjuan">
<img src="https://github.com/yeonjuan.png?s=75" width="75" height="75"><br />
YeonJuan
</a>
</td><td align="center" valign="top" width="11%">
<a href="https://github.com/mdjermanovic">
<img src="https://github.com/mdjermanovic.png?s=75" width="75" height="75"><br />
Milos Djermanovic
@@ -262,17 +250,11 @@ The following companies, organizations, and individuals support ESLint's ongoing
<!-- NOTE: This section is autogenerated. Do not manually edit.-->
<!--sponsorsstart-->
<h3>Gold Sponsors</h3>
<p><a href="https://www.shopify.com"><img src="https://images.opencollective.com/shopify/eeb91aa/logo.png" alt="Shopify" height="96"></a> <a href="http://engineering.salesforce.com"><img src="https://images.opencollective.com/salesforce/ca8f997/logo.png" alt="Salesforce" height="96"></a> <a href="https://badoo.com/team?utm_source=eslint"><img src="https://images.opencollective.com/badoo/2826a3b/logo.png" alt="Badoo" height="96"></a> <a href="https://www.airbnb.com/"><img src="https://images.opencollective.com/airbnb/d327d66/logo.png" alt="Airbnb" height="96"></a> <a href="https://opensource.facebook.com"><img src="https://images.opencollective.com/fbopensource/fbb8a5b/logo.png" alt="Facebook Open Source" height="96"></a></p><h3>Silver Sponsors</h3>
<p><a href="https://www.shopify.com"><img src="https://images.opencollective.com/shopify/eeb91aa/logo.png" alt="Shopify" height="96"></a> <a href="http://engineering.salesforce.com"><img src="https://images.opencollective.com/salesforce/ca8f997/logo.png" alt="Salesforce" height="96"></a> <a href="https://magiclab.co/?utm_source=eslint"><img src="https://images.opencollective.com/magiclab/bbf6345/logo.png" alt="MagicLab" height="96"></a> <a href="https://www.airbnb.com/"><img src="https://images.opencollective.com/airbnb/d327d66/logo.png" alt="Airbnb" height="96"></a> <a href="https://opensource.facebook.com"><img src="https://images.opencollective.com/fbopensource/fbb8a5b/logo.png" alt="Facebook Open Source" height="96"></a></p><h3>Silver Sponsors</h3>
<p><a href="https://www.ampproject.org/"><img src="https://images.opencollective.com/amp/c8a3b25/logo.png" alt="AMP Project" height="64"></a></p><h3>Bronze Sponsors</h3>
<p><a href="https://icons8.com"><img src="https://images.opencollective.com/icons8/0b37d14/logo.png" alt="Free Icons by Icons8" height="32"></a> <a href="https://www.bonus.com.de/freispiele"><img src="https://images.opencollective.com/bonusfinder-deutschland/646169e/logo.png" alt="BonusFinder Deutschland" height="32"></a> <a href="https://edubirdie.com/"><img src="https://images.opencollective.com/edubirdie2/b1d51ab/logo.png" alt="EduBirdie" height="32"></a> <a href="https://www.bugsnag.com/platforms?utm_source=Open Collective&utm_medium=Website&utm_content=open-source&utm_campaign=2019-community&utm_term="><img src="https://images.opencollective.com/bugsnag-stability-monitoring/c2cef36/logo.png" alt="Bugsnag Stability Monitoring" height="32"></a> <a href="https://www.crosswordsolver.com"><img src="https://images.opencollective.com/crosswordsolver/d4481d6/logo.png" alt="Crosswordsolver" height="32"></a> <a href="https://www.codacy.com/?utm_source=eslint&utm_medium=cpm&utm_campaign=eslint-sponsorship"><img src="https://images.opencollective.com/codacy/ed22716/logo.png" alt="Codacy" height="32"></a> <a href="https://mixpanel.com"><img src="https://images.opencollective.com/mixpanel/cd682f7/logo.png" alt="Mixpanel" height="32"></a> <a href="https://www.vpsserver.com"><img src="https://images.opencollective.com/vpsservercom/logo.png" alt="VPS Server" height="32"></a> <a href="https://medium.com/@niksundin/best-web-design-companies-1872e445775f"><img src="https://images.opencollective.com/top-web-design-agencies/d92d747/logo.png" alt="Top Web Design Agencies" height="32"></a> <a href="https://uxplanet.org/top-ui-ux-design-agencies-user-experience-firms-8c54697e290"><img src="https://images.opencollective.com/ui-ux-design-agencies/cae5dfe/logo.png" alt="UI UX Design Agencies" height="32"></a> <a href="https://clay.global"><img src="https://images.opencollective.com/clayglobal/2468f34/logo.png" alt="clay" height="32"></a> <a href="https://discordapp.com"><img src="https://images.opencollective.com/discordapp/7e3d9a9/logo.png" alt="Discord" height="32"></a> <a href="https://themeisle.com"><img src="https://images.opencollective.com/themeisle/d5592fe/logo.png" alt="ThemeIsle" height="32"></a> <a href="https://tekhattan.com"><img src="https://images.opencollective.com/tekhattan/bc73c28/logo.png" alt="TekHattan" height="32"></a> <a href="https://www.marfeel.com/"><img src="https://images.opencollective.com/marfeel/4b88e30/logo.png" alt="Marfeel" height="32"></a> <a href="http://www.firesticktricks.com"><img src="https://images.opencollective.com/fire-stick-tricks/b8fbe2c/logo.png" alt="Fire Stick Tricks" height="32"></a> <a href="https://jsheroes.io/"><img src="https://images.opencollective.com/jsheroes1/9fedf0b/logo.png" alt="JSHeroes " height="32"></a></p>
<p><a href="https://www.bonus.com.de/freispiele"><img src="https://images.opencollective.com/bonusfinder-deutschland/646169e/logo.png" alt="BonusFinder Deutschland" height="32"></a> <a href="https://medium.com/@niksundin/best-web-design-companies-1872e445775f"><img src="https://images.opencollective.com/top-web-design-agencies/d92d747/logo.png" alt="Top Web Design Agencies" height="32"></a> <a href="https://www.bugsnag.com/platforms?utm_source=Open Collective&utm_medium=Website&utm_content=open-source&utm_campaign=2019-community&utm_term="><img src="https://images.opencollective.com/bugsnag-stability-monitoring/c2cef36/logo.png" alt="Bugsnag Stability Monitoring" height="32"></a> <a href="https://www.crosswordsolver.com"><img src="https://images.opencollective.com/crosswordsolver/d4481d6/logo.png" alt="Crosswordsolver" height="32"></a> <a href="https://mixpanel.com"><img src="https://images.opencollective.com/mixpanel/cd682f7/logo.png" alt="Mixpanel" height="32"></a> <a href="https://www.vpsserver.com"><img src="https://images.opencollective.com/vpsservercom/logo.png" alt="VPS Server" height="32"></a> <a href="https://icons8.com"><img src="https://images.opencollective.com/icons8/0b37d14/logo.png" alt="Free Icons by Icons8" height="32"></a> <a href="https://uxplanet.org/top-ui-ux-design-agencies-user-experience-firms-8c54697e290"><img src="https://images.opencollective.com/ui-ux-design-agencies/cae5dfe/logo.png" alt="UI UX Design Agencies" height="32"></a> <a href="https://clay.global"><img src="https://images.opencollective.com/clayglobal/2468f34/logo.png" alt="clay" height="32"></a> <a href="https://discordapp.com"><img src="https://images.opencollective.com/discordapp/7e3d9a9/logo.png" alt="Discord" height="32"></a> <a href="https://themeisle.com"><img src="https://images.opencollective.com/themeisle/d5592fe/logo.png" alt="ThemeIsle" height="32"></a> <a href="https://tekhattan.com"><img src="https://images.opencollective.com/tekhattan/bc73c28/logo.png" alt="TekHattan" height="32"></a> <a href="https://www.marfeel.com/"><img src="https://images.opencollective.com/marfeel/4b88e30/logo.png" alt="Marfeel" height="32"></a> <a href="http://www.firesticktricks.com"><img src="https://images.opencollective.com/fire-stick-tricks/b8fbe2c/logo.png" alt="Fire Stick Tricks" height="32"></a> <a href="https://jsheroes.io/"><img src="https://images.opencollective.com/jsheroes1/9fedf0b/logo.png" alt="JSHeroes " height="32"></a></p>
<!--sponsorsend-->
## <a name="technology-sponsors"></a>Technology Sponsors
* Site search ([eslint.org](https://eslint.org)) is sponsored by [Algolia](https://www.algolia.com)
[npm-image]: https://img.shields.io/npm/v/eslint.svg?style=flat-square
[npm-url]: https://www.npmjs.com/package/eslint
[downloads-image]: https://img.shields.io/npm/dm/eslint.svg?style=flat-square
[downloads-url]: https://www.npmjs.com/package/eslint

View File

@@ -15,7 +15,7 @@ const globals = require("globals");
//------------------------------------------------------------------------------
/**
* Get the object that has differentce.
* Get the object that has difference.
* @param {Record<string,boolean>} current The newer object.
* @param {Record<string,boolean>} prev The older object.
* @returns {Record<string,boolean>} The difference object.

View File

@@ -278,14 +278,11 @@ function createIgnoreResult(filePath, baseDir) {
let message;
const isHidden = /^\./u.test(path.basename(filePath));
const isInNodeModules = baseDir && path.relative(baseDir, filePath).startsWith("node_modules");
const isInBowerComponents = baseDir && path.relative(baseDir, filePath).startsWith("bower_components");
if (isHidden) {
message = "File ignored by default. Use a negated ignore pattern (like \"--ignore-pattern '!<relative/path/to/filename>'\") to override.";
} else if (isInNodeModules) {
message = "File ignored by default. Use \"--ignore-pattern '!node_modules/*'\" to override.";
} else if (isInBowerComponents) {
message = "File ignored by default. Use \"--ignore-pattern '!bower_components/*'\" to override.";
} else {
message = "File ignored because of a matching ignore pattern. Use \"--no-ignore\" to override.";
}

View File

@@ -5,7 +5,7 @@
* config file, base config files that were extended, loaded parsers, and loaded
* plugins.
*
* `ConfigArray` class provies three properties and two methods.
* `ConfigArray` class provides three properties and two methods.
*
* - `pluginEnvironments`
* - `pluginProcessors`

View File

@@ -103,8 +103,8 @@ function dirSuffix(filePath) {
return isDir ? "/" : "";
}
const DefaultPatterns = Object.freeze(["/node_modules/*", "/bower_components/*"]);
const DotPatterns = Object.freeze([".*", "!../"]);
const DefaultPatterns = Object.freeze(["/**/node_modules/*"]);
const DotPatterns = Object.freeze([".*", "!.eslintrc.*", "!../"]);
//------------------------------------------------------------------------------
// Public

View File

@@ -6,7 +6,7 @@
* 1. Find target files by processing glob patterns.
* 2. Tie each target file and appropriate configuration.
*
* It provies a method:
* It provides a method:
*
* - `iterateFiles(patterns)`
* Iterate files which are matched by given patterns together with the
@@ -283,7 +283,7 @@ class FileEnumerator {
continue;
}
// Iterate files of this pttern.
// Iterate files of this pattern.
for (const { config, filePath, flag } of this._iterateFiles(pattern)) {
foundRegardlessOfIgnored = true;
if (flag === IGNORED_SILENTLY) {

View File

@@ -135,7 +135,7 @@ function check(packages, opt) {
*
* Convenience wrapper around check().
* @param {string[]} packages Array of node modules to check.
* @param {string} rootDir The directory contianing a package.json
* @param {string} rootDir The directory containing a package.json
* @returns {Object} An object whose keys are the module names
* and values are booleans indicating installation.
*/

View File

@@ -518,6 +518,7 @@ function processCodePathToExit(analyzer, node) {
case "ImportExpression":
case "MemberExpression":
case "NewExpression":
case "YieldExpression":
state.makeFirstThrowablePathInTryBlock();
break;

View File

@@ -70,7 +70,7 @@ module.exports = {
/**
* Dumps a DOT code of a given code path.
* The DOT code can be visialized with Graphvis.
* The DOT code can be visualized with Graphvis.
* @param {CodePath} codePath A code path to dump.
* @returns {void}
* @see http://www.graphviz.org
@@ -135,7 +135,7 @@ module.exports = {
/**
* Makes a DOT code of a given code path.
* The DOT code can be visialized with Graphvis.
* The DOT code can be visualized with Graphvis.
* @param {CodePath} codePath A code path to make DOT.
* @param {Object} traceMap Optional. A map to check whether or not segments had been done.
* @returns {string} A DOT code of the code path.

View File

@@ -211,7 +211,7 @@ class ForkContext {
}
/**
* Clears all secments in this context.
* Clears all segments in this context.
* @returns {void}
*/
clear() {

View File

@@ -1272,7 +1272,7 @@ class Linter {
* @param {string|SourceCode} textOrSourceCode The source code.
* @param {ConfigData|ExtractedConfig} config The config array.
* @param {VerifyOptions&ProcessorOptions} options The options.
* @param {ConfigArray} [configForRecursive] The `CofnigArray` object to apply multiple processors recursively.
* @param {ConfigArray} [configForRecursive] The `ConfigArray` object to apply multiple processors recursively.
* @returns {LintMessage[]} The found problems.
*/
_verifyWithProcessor(textOrSourceCode, config, options, configForRecursive) {

View File

@@ -18,7 +18,7 @@ const astUtils = require("./utils/ast-utils");
//------------------------------------------------------------------------------
const TARGET_NODE_TYPE = /^(?:Arrow)?FunctionExpression$/u;
const TARGET_METHODS = /^(?:every|filter|find(?:Index)?|flatMap|map|reduce(?:Right)?|some|sort)$/u;
const TARGET_METHODS = /^(?:every|filter|find(?:Index)?|flatMap|forEach|map|reduce(?:Right)?|some|sort)$/u;
/**
* Checks a given code path segment is reachable.
@@ -61,12 +61,13 @@ function isTargetMethod(node) {
/**
* Checks whether or not a given node is a function expression which is the
* callback of an array method.
* callback of an array method, returning the method name.
* @param {ASTNode} node A node to check. This is one of
* FunctionExpression or ArrowFunctionExpression.
* @returns {boolean} `true` if the node is the callback of an array method.
* @returns {string} The method name if the node is a callback method,
* null otherwise.
*/
function isCallbackOfArrayMethod(node) {
function getArrayMethodName(node) {
let currentNode = node;
while (currentNode) {
@@ -95,7 +96,7 @@ function isCallbackOfArrayMethod(node) {
const func = astUtils.getUpperFunction(parent);
if (func === null || !astUtils.isCallee(func)) {
return false;
return null;
}
currentNode = func.parent;
break;
@@ -108,27 +109,31 @@ function isCallbackOfArrayMethod(node) {
*/
case "CallExpression":
if (astUtils.isArrayFromMethod(parent.callee)) {
return (
if (
parent.arguments.length >= 2 &&
parent.arguments[1] === currentNode
);
) {
return "from";
}
}
if (isTargetMethod(parent.callee)) {
return (
if (
parent.arguments.length >= 1 &&
parent.arguments[0] === currentNode
);
) {
return astUtils.getStaticPropertyName(parent.callee);
}
}
return false;
return null;
// Otherwise this node is not target.
default:
return false;
return null;
}
}
/* istanbul ignore next: unreachable */
return false;
return null;
}
//------------------------------------------------------------------------------
@@ -153,6 +158,10 @@ module.exports = {
allowImplicit: {
type: "boolean",
default: false
},
checkForEach: {
type: "boolean",
default: false
}
},
additionalProperties: false
@@ -162,15 +171,17 @@ module.exports = {
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."
expectedReturnValue: "{{name}} expected a return value.",
expectedNoReturnValue: "{{name}} did not expect a return value."
}
},
create(context) {
const options = context.options[0] || { allowImplicit: false };
const options = context.options[0] || { allowImplicit: false, checkForEach: false };
let funcInfo = {
arrayMethodName: null,
upper: null,
codePath: null,
hasReturn: false,
@@ -188,18 +199,32 @@ module.exports = {
* @returns {void}
*/
function checkLastSegment(node) {
if (funcInfo.shouldCheck &&
funcInfo.codePath.currentSegments.some(isReachable)
) {
if (!funcInfo.shouldCheck) {
return;
}
let messageId = null;
if (funcInfo.arrayMethodName === "forEach") {
if (options.checkForEach && node.type === "ArrowFunctionExpression" && node.expression) {
messageId = "expectedNoReturnValue";
}
} else {
if (node.body.type === "BlockStatement" && funcInfo.codePath.currentSegments.some(isReachable)) {
messageId = funcInfo.hasReturn ? "expectedAtEnd" : "expectedInside";
}
}
if (messageId) {
let name = astUtils.getFunctionNameWithKind(funcInfo.node);
name = messageId === "expectedNoReturnValue" ? lodash.upperFirst(name) : name;
context.report({
node,
loc: getLocation(node, context.getSourceCode()).loc.start,
messageId: funcInfo.hasReturn
? "expectedAtEnd"
: "expectedInside",
data: {
name: astUtils.getFunctionNameWithKind(funcInfo.node)
}
messageId,
data: { name }
});
}
}
@@ -208,14 +233,20 @@ module.exports = {
// Stacks this function's information.
onCodePathStart(codePath, node) {
let methodName = null;
if (TARGET_NODE_TYPE.test(node.type)) {
methodName = getArrayMethodName(node);
}
funcInfo = {
arrayMethodName: methodName,
upper: funcInfo,
codePath,
hasReturn: false,
shouldCheck:
TARGET_NODE_TYPE.test(node.type) &&
node.body.type === "BlockStatement" &&
isCallbackOfArrayMethod(node) &&
methodName &&
!node.async &&
!node.generator,
node
@@ -229,20 +260,38 @@ module.exports = {
// Checks the return statement is valid.
ReturnStatement(node) {
if (funcInfo.shouldCheck) {
funcInfo.hasReturn = true;
if (!funcInfo.shouldCheck) {
return;
}
funcInfo.hasReturn = true;
let messageId = null;
if (funcInfo.arrayMethodName === "forEach") {
// if checkForEach: true, returning a value at any path inside a forEach is not allowed
if (options.checkForEach && node.argument) {
messageId = "expectedNoReturnValue";
}
} else {
// if allowImplicit: false, should also check node.argument
if (!options.allowImplicit && !node.argument) {
context.report({
node,
messageId: "expectedReturnValue",
data: {
name: lodash.upperFirst(astUtils.getFunctionNameWithKind(funcInfo.node))
}
});
messageId = "expectedReturnValue";
}
}
if (messageId) {
context.report({
node,
messageId,
data: {
name: lodash.upperFirst(astUtils.getFunctionNameWithKind(funcInfo.node))
}
});
}
},
// Reports a given function if the last path is reachable.

View File

@@ -1,6 +1,6 @@
/**
* @fileoverview Counts the cyclomatic complexity of each function of the script. See http://en.wikipedia.org/wiki/Cyclomatic_complexity.
* Counts the number of if, conditional, for, whilte, try, switch/case,
* Counts the number of if, conditional, for, while, try, switch/case,
* @author Patrick Brosset
*/

View File

@@ -114,7 +114,7 @@ module.exports = {
}
/**
* Check each alias to ensure that is was assinged to the correct value.
* Check each alias to ensure that is was assigned to the correct value.
* @returns {void}
*/
function ensureWasAssigned() {

View File

@@ -41,6 +41,7 @@ module.exports = {
//--------------------------------------------------------------------------
const blacklist = context.options;
const reportedNodes = new Set();
/**
@@ -54,18 +55,46 @@ module.exports = {
}
/**
* Verifies if we should report an error or not based on the effective
* parent node and the identifier name.
* @param {ASTNode} effectiveParent The effective parent node of the node to be reported
* @param {string} name The identifier name of the identifier node
* Checks whether the given node represents an imported name that is renamed in the same import/export specifier.
*
* Examples:
* import { a as b } from 'mod'; // node `a` is renamed import
* export { a as b } from 'mod'; // node `a` is renamed import
* @param {ASTNode} node `Identifier` node to check.
* @returns {boolean} `true` if the node is a renamed import.
*/
function isRenamedImport(node) {
const parent = node.parent;
return (
(
parent.type === "ImportSpecifier" &&
parent.imported !== parent.local &&
parent.imported === node
) ||
(
parent.type === "ExportSpecifier" &&
parent.parent.source && // re-export
parent.local !== parent.exported &&
parent.local === node
)
);
}
/**
* Verifies if we should report an error or not.
* @param {ASTNode} node The node to check
* @returns {boolean} whether an error should be reported or not
*/
function shouldReport(effectiveParent, name) {
function shouldReport(node) {
const parent = node.parent;
return (
effectiveParent.type !== "CallExpression" &&
effectiveParent.type !== "NewExpression" &&
effectiveParent.parent.type !== "ObjectPattern" &&
isInvalid(name)
parent.type !== "CallExpression" &&
parent.type !== "NewExpression" &&
parent.parent.type !== "ObjectPattern" &&
!isRenamedImport(node) &&
isInvalid(node.name)
);
}
@@ -76,27 +105,30 @@ module.exports = {
* @private
*/
function report(node) {
context.report({
node,
messageId: "blacklisted",
data: {
name: node.name
}
});
if (!reportedNodes.has(node)) {
context.report({
node,
messageId: "blacklisted",
data: {
name: node.name
}
});
reportedNodes.add(node);
}
}
return {
Identifier(node) {
const name = node.name,
effectiveParent = (node.parent.type === "MemberExpression") ? node.parent.parent : node.parent;
// MemberExpressions get special rules
if (node.parent.type === "MemberExpression") {
const name = node.name,
effectiveParent = node.parent.parent;
// Always check object names
if (node.parent.object.type === "Identifier" &&
node.parent.object.name === node.name) {
node.parent.object.name === name) {
if (isInvalid(name)) {
report(node);
}
@@ -105,21 +137,13 @@ module.exports = {
} else if (effectiveParent.type === "AssignmentExpression" &&
(effectiveParent.right.type !== "MemberExpression" ||
effectiveParent.left.type === "MemberExpression" &&
effectiveParent.left.property.name === node.name)) {
effectiveParent.left.property.name === name)) {
if (isInvalid(name)) {
report(node);
}
}
// Properties have their own rules
} else if (node.parent.type === "Property") {
if (shouldReport(effectiveParent, name)) {
report(node);
}
// Report anything that is a match and not a CallExpression
} else if (shouldReport(effectiveParent, name)) {
} else if (shouldReport(node)) {
report(node);
}
}

View File

@@ -64,7 +64,7 @@ module.exports = {
//--------------------------------------------------------------------------
return {
Program: function checkForlinebreakStyle(node) {
Program: function checkForLinebreakStyle(node) {
const linebreakStyle = context.options[0] || "unix",
expectedLF = linebreakStyle === "unix",
expectedLFChars = expectedLF ? "\n" : "\r\n",

View File

@@ -203,7 +203,7 @@ module.exports = {
* stripped.
* @param {string} line The source line with a trailing comment
* @param {ASTNode} comment The comment to remove
* @returns {string} Line without comment and trailing whitepace
* @returns {string} Line without comment and trailing whitespace
*/
function stripTrailingComment(line, comment) {

View File

@@ -316,6 +316,10 @@ module.exports = {
const [, prefix = "", initialOffset = ""] = lineTextToAlignWith.match(/^(\s*(?:\/?\*)?(\s*))/u) || [];
offset = `${commentTextPrefix.slice(prefix.length)}${initialOffset}`;
if (/^\s*\//u.test(lineText) && offset.length === 0) {
offset += " ";
}
break;
}

View File

@@ -1,6 +1,6 @@
/**
* @fileoverview A rule to warn against using arrow functions when they could be
* confused with comparisions
* confused with comparisons
* @author Jxck <https://github.com/Jxck>
*/
@@ -71,7 +71,7 @@ module.exports = {
messageId: "confusing",
fix(fixer) {
// if `allowParens` is not set to true dont bother wrapping in parens
// if `allowParens` is not set to true don't bother wrapping in parens
return allowParens && fixer.replaceText(node.body, `(${sourceCode.getText(node.body)})`);
}
});

View File

@@ -90,13 +90,27 @@ module.exports = {
* @private
*/
function isConstant(node, inBooleanPosition) {
// node.elements can return null values in the case of sparse arrays ex. [,]
if (!node) {
return true;
}
switch (node.type) {
case "Literal":
case "ArrowFunctionExpression":
case "FunctionExpression":
case "ObjectExpression":
case "ArrayExpression":
return true;
case "TemplateLiteral":
return (inBooleanPosition && node.quasis.some(quasi => quasi.value.cooked.length)) ||
node.expressions.every(exp => isConstant(exp, inBooleanPosition));
case "ArrayExpression": {
if (node.parent.type === "BinaryExpression" && node.parent.operator === "+") {
return node.elements.every(element => isConstant(element, false));
}
return true;
}
case "UnaryExpression":
if (node.operator === "void") {

View File

@@ -1,5 +1,5 @@
/**
* @fileoverview Rule to forbid control charactes from regular expressions.
* @fileoverview Rule to forbid control characters from regular expressions.
* @author Nicholas C. Zakas
*/

View File

@@ -74,11 +74,12 @@ module.exports = {
// Reports the node if its name has been declared already.
MethodDefinition(node) {
if (node.computed) {
const name = astUtils.getStaticPropertyName(node);
if (name === null || node.kind === "constructor") {
return;
}
const name = astUtils.getStaticPropertyName(node) || "";
const state = getState(name, node.static);
let isDuplicate = false;

View File

@@ -702,8 +702,7 @@ module.exports = {
}
if (node.body.type === "ConditionalExpression" &&
IGNORE_ARROW_CONDITIONALS &&
!isParenthesisedTwice(node.body)
IGNORE_ARROW_CONDITIONALS
) {
return;
}

View File

@@ -39,9 +39,11 @@ module.exports = {
}
},
additionalProperties: false
}]
}],
// no messages, because the error text comes directly from the regexpp module
messages: {
regexMessage: "{{message}}."
}
},
create(context) {
@@ -118,7 +120,7 @@ module.exports = {
if (message) {
context.report({
node,
message: "{{message}}.",
messageId: "regexMessage",
data: { message }
});
}

View File

@@ -1,5 +1,5 @@
/**
* @fileoverview Rule to disalow whitespace that is not a tab or space, whitespace inside strings and comments are allowed
* @fileoverview Rule to disallow whitespace that is not a tab or space, whitespace inside strings and comments are allowed
* @author Jonathan Kingston
* @author Christophe Porteneuve
*/

View File

@@ -5,6 +5,12 @@
"use strict";
//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------
const { getStaticPropertyName } = require("./utils/ast-utils");
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
@@ -33,9 +39,7 @@ module.exports = {
MemberExpression(node) {
if (node.property &&
(node.property.type === "Identifier" && node.property.name === "__iterator__" && !node.computed) ||
(node.property.type === "Literal" && node.property.value === "__iterator__")) {
if (getStaticPropertyName(node) === "__iterator__") {
context.report({
node,
messageId: "noIterator"

View File

@@ -1,5 +1,5 @@
/**
* @fileoverview Rule to disallow if as the only statmenet in an else block
* @fileoverview Rule to disallow if as the only statement in an else block
* @author Brandon Mills
*/
"use strict";

View File

@@ -110,11 +110,14 @@ module.exports = {
/**
* Returns whether the number should be ignored when used as an array index with enabled 'ignoreArrayIndexes' option.
* @param {ASTNode} parent the non-"UnaryExpression" parent.
* @param {ASTNode} node Node to check
* @returns {boolean} true if the number should be ignored
*/
function shouldIgnoreArrayIndexes(parent) {
return parent.type === "MemberExpression" && ignoreArrayIndexes;
function shouldIgnoreArrayIndexes(node) {
const parent = node.parent;
return ignoreArrayIndexes &&
parent.type === "MemberExpression" && parent.property === node;
}
return {
@@ -145,7 +148,7 @@ module.exports = {
if (shouldIgnoreNumber(value) ||
shouldIgnoreParseInt(parent, fullNumberNode) ||
shouldIgnoreArrayIndexes(parent) ||
shouldIgnoreArrayIndexes(fullNumberNode) ||
shouldIgnoreJSXNumbers(parent)) {
return;
}

View File

@@ -37,7 +37,11 @@ module.exports = {
},
additionalProperties: false
}
]
],
messages: {
nativeReassign: "Read-only global '{{name}}' should not be modified."
}
},
create(context) {
@@ -65,7 +69,7 @@ module.exports = {
) {
context.report({
node: identifier,
message: "Read-only global '{{name}}' should not be modified.",
messageId: "nativeReassign",
data: identifier
});
}

View File

@@ -24,7 +24,11 @@ module.exports = {
replacedBy: ["no-unsafe-negation"],
deprecated: true,
schema: []
schema: [],
messages: {
negatedLHS: "The 'in' expression's left operand is negated."
}
},
create(context) {
@@ -33,7 +37,7 @@ module.exports = {
BinaryExpression(node) {
if (node.operator === "in" && node.left.type === "UnaryExpression" && node.left.operator === "!") {
context.report({ node, message: "The 'in' expression's left operand is negated." });
context.report({ node, messageId: "negatedLHS" });
}
}
};

View File

@@ -47,8 +47,8 @@ module.exports = {
const tracker = new ReferenceTracker(scope);
const traceMap = {};
for (const global of nonCallableGlobals) {
traceMap[global] = {
for (const g of nonCallableGlobals) {
traceMap[g] = {
[CALL]: true
};
}

View File

@@ -19,7 +19,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-process-env"
},
schema: []
schema: [],
messages: {
unexpectedProcessEnv: "Unexpected use of process.env."
}
},
create(context) {
@@ -31,7 +35,7 @@ module.exports = {
propertyName = node.property.name;
if (objectName === "process" && !node.computed && propertyName && propertyName === "env") {
context.report({ node, message: "Unexpected use of process.env." });
context.report({ node, messageId: "unexpectedProcessEnv" });
}
}

View File

@@ -19,7 +19,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-process-exit"
},
schema: []
schema: [],
messages: {
noProcessExit: "Don't use process.exit(); throw an error instead."
}
},
create(context) {
@@ -30,7 +34,7 @@ module.exports = {
return {
"CallExpression > MemberExpression.callee[object.name = 'process'][property.name = 'exit']"(node) {
context.report({ node: node.parent, message: "Don't use process.exit(); throw an error instead." });
context.report({ node: node.parent, messageId: "noProcessExit" });
}
};

View File

@@ -5,6 +5,12 @@
"use strict";
//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------
const { getStaticPropertyName } = require("./utils/ast-utils");
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
@@ -20,7 +26,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-proto"
},
schema: []
schema: [],
messages: {
unexpectedProto: "The '__proto__' property is deprecated."
}
},
create(context) {
@@ -28,11 +38,8 @@ module.exports = {
return {
MemberExpression(node) {
if (node.property &&
(node.property.type === "Identifier" && node.property.name === "__proto__" && !node.computed) ||
(node.property.type === "Literal" && node.property.value === "__proto__")) {
context.report({ node, message: "The '__proto__' property is deprecated." });
if (getStaticPropertyName(node) === "__proto__") {
context.report({ node, messageId: "unexpectedProto" });
}
}
};

View File

@@ -19,7 +19,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-prototype-builtins"
},
schema: []
schema: [],
messages: {
prototypeBuildIn: "Do not access Object.prototype method '{{prop}}' from target object."
}
},
create(context) {
@@ -42,7 +46,7 @@ module.exports = {
if (DISALLOWED_PROPS.indexOf(propName) > -1) {
context.report({
message: "Do not access Object.prototype method '{{prop}}' from target object.",
messageId: "prototypeBuildIn",
loc: node.callee.property.loc.start,
data: { prop: propName },
node

View File

@@ -45,7 +45,11 @@ module.exports = {
},
schema: [],
fixable: "code"
fixable: "code",
messages: {
multipleSpaces: "Spaces are hard to count. Use {{{length}}}."
}
},
create(context) {
@@ -96,7 +100,7 @@ module.exports = {
) {
context.report({
node: nodeToReport,
message: "Spaces are hard to count. Use {{{length}}}.",
messageId: "multipleSpaces",
data: { length },
fix(fixer) {
if (pattern !== rawPattern) {
@@ -109,7 +113,7 @@ module.exports = {
}
});
// Report only the first occurence of consecutive spaces
// Report only the first occurrence of consecutive spaces
return;
}
}

View File

@@ -4,13 +4,6 @@
*/
"use strict";
//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
const DEFAULT_MESSAGE_TEMPLATE = "'{{moduleName}}' module is restricted from being used.";
const CUSTOM_MESSAGE_TEMPLATE = "'{{moduleName}}' module is restricted from being used. {{customMessage}}";
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
@@ -72,6 +65,13 @@ module.exports = {
additionalItems: false
}
]
},
messages: {
defaultMessage: "'{{name}}' module is restricted from being used.",
// eslint-disable-next-line eslint-plugin/report-message-format
customMessage: "'{{name}}' module is restricted from being used. {{customMessage}}",
patternMessage: "'{{name}}' module is restricted from being used by a pattern."
}
},
@@ -126,17 +126,17 @@ module.exports = {
* @private
*/
function reportPath(node) {
const moduleName = node.arguments[0].value.trim();
const customMessage = restrictedPathMessages[moduleName];
const message = customMessage
? CUSTOM_MESSAGE_TEMPLATE
: DEFAULT_MESSAGE_TEMPLATE;
const name = node.arguments[0].value.trim();
const customMessage = restrictedPathMessages[name];
const messageId = customMessage
? "customMessage"
: "defaultMessage";
context.report({
node,
message,
messageId,
data: {
moduleName,
name,
customMessage
}
});
@@ -158,18 +158,18 @@ module.exports = {
// node has arguments and first argument is string
if (node.arguments.length && isString(node.arguments[0])) {
const moduleName = node.arguments[0].value.trim();
const name = node.arguments[0].value.trim();
// check if argument value is in restricted modules array
if (isRestrictedPath(moduleName)) {
if (isRestrictedPath(name)) {
reportPath(node);
}
if (restrictedPatterns.length > 0 && ig.ignores(moduleName)) {
if (restrictedPatterns.length > 0 && ig.ignores(name)) {
context.report({
node,
message: "'{{moduleName}}' module is restricted from being used by a pattern.",
data: { moduleName }
messageId: "patternMessage",
data: { name }
});
}
}

View File

@@ -61,6 +61,13 @@ module.exports = {
]
},
uniqueItems: true
},
messages: {
// eslint-disable-next-line eslint-plugin/report-message-format
restrictedObjectProperty: "'{{objectName}}.{{propertyName}}' is restricted from being used.{{message}}",
// eslint-disable-next-line eslint-plugin/report-message-format
restrictedProperty: "'{{propertyName}}' is restricted from being used.{{message}}"
}
},
@@ -114,8 +121,7 @@ module.exports = {
context.report({
node,
// eslint-disable-next-line eslint-plugin/report-message-format
message: "'{{objectName}}.{{propertyName}}' is restricted from being used.{{message}}",
messageId: "restrictedObjectProperty",
data: {
objectName,
propertyName,
@@ -127,8 +133,7 @@ module.exports = {
context.report({
node,
// eslint-disable-next-line eslint-plugin/report-message-format
message: "'{{propertyName}}' is restricted from being used.{{message}}",
messageId: "restrictedProperty",
data: {
propertyName,
message

View File

@@ -39,6 +39,11 @@ module.exports = {
},
uniqueItems: true,
minItems: 0
},
messages: {
// eslint-disable-next-line eslint-plugin/report-message-format
restrictedSyntax: "{{message}}"
}
},
@@ -48,14 +53,14 @@ module.exports = {
const hasCustomMessage = !isStringFormat && Boolean(selectorOrObject.message);
const selector = isStringFormat ? selectorOrObject : selectorOrObject.selector;
const message = hasCustomMessage ? selectorOrObject.message : "Using '{{selector}}' is not allowed.";
const message = hasCustomMessage ? selectorOrObject.message : `Using '${selector}' is not allowed.`;
return Object.assign(result, {
[selector](node) {
context.report({
node,
message,
data: hasCustomMessage ? {} : { selector }
messageId: "restrictedSyntax",
data: { message }
});
}
});

View File

@@ -35,7 +35,12 @@ module.exports = {
{
enum: ["except-parens", "always"]
}
]
],
messages: {
returnAssignment: "Return statement should not contain assignment.",
arrowAssignment: "Arrow function should not return assignment."
}
},
create(context) {
@@ -61,12 +66,12 @@ module.exports = {
if (parent && parent.type === "ReturnStatement") {
context.report({
node: parent,
message: "Return statement should not contain assignment."
messageId: "returnAssignment"
});
} else if (parent && parent.type === "ArrowFunctionExpression" && parent.body === currentChild) {
context.report({
node: parent,
message: "Arrow function should not return assignment."
messageId: "arrowAssignment"
});
}
}

View File

@@ -10,8 +10,6 @@ const astUtils = require("./utils/ast-utils");
// Rule Definition
//------------------------------------------------------------------------------
const message = "Redundant use of `await` on a return value.";
module.exports = {
meta: {
type: "suggestion",
@@ -28,7 +26,11 @@ module.exports = {
fixable: null,
schema: [
]
],
messages: {
redundantUseOfAwait: "Redundant use of `await` on a return value."
}
},
create(context) {
@@ -42,7 +44,7 @@ module.exports = {
context.report({
node: context.getSourceCode().getFirstToken(node),
loc: node.loc,
message
messageId: "redundantUseOfAwait"
});
}

View File

@@ -22,7 +22,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-script-url"
},
schema: []
schema: [],
messages: {
unexpectedScriptURL: "Script URL is a form of eval."
}
},
create(context) {
@@ -34,7 +38,7 @@ module.exports = {
const value = node.value.toLowerCase();
if (value.indexOf("javascript:") === 0) {
context.report({ node, message: "Script URL is a form of eval." });
context.report({ node, messageId: "unexpectedScriptURL" });
}
}
}

View File

@@ -196,7 +196,11 @@ module.exports = {
},
additionalProperties: false
}
]
],
messages: {
selfAssignment: "'{{name}}' is assigned to itself."
}
},
create(context) {
@@ -211,7 +215,7 @@ module.exports = {
function report(node) {
context.report({
node,
message: "'{{name}}' is assigned to itself.",
messageId: "selfAssignment",
data: {
name: sourceCode.getText(node).replace(SPACES, "")
}

View File

@@ -21,7 +21,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-self-compare"
},
schema: []
schema: [],
messages: {
comparingToSelf: "Comparing to itself is potentially pointless."
}
},
create(context) {
@@ -47,7 +51,7 @@ module.exports = {
const operators = new Set(["===", "==", "!==", "!=", ">", "<", ">=", "<="]);
if (operators.has(node.operator) && hasSameTokens(node.left, node.right)) {
context.report({ node, message: "Comparing to itself is potentially pointless." });
context.report({ node, messageId: "comparingToSelf" });
}
}
};

View File

@@ -26,7 +26,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-sequences"
},
schema: []
schema: [],
messages: {
unexpectedCommaExpression: "Unexpected use of comma operator."
}
},
create(context) {
@@ -107,7 +111,7 @@ module.exports = {
const firstCommaToken = sourceCode.getTokenAfter(node.expressions[0], astUtils.isCommaToken);
context.report({ node, loc: firstCommaToken.loc, message: "Unexpected use of comma operator." });
context.report({ node, loc: firstCommaToken.loc, messageId: "unexpectedCommaExpression" });
}
};

View File

@@ -32,7 +32,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-shadow-restricted-names"
},
schema: []
schema: [],
messages: {
shadowingRestrictedName: "Shadowing of global property '{{name}}'."
}
},
create(context) {
@@ -46,9 +50,9 @@ module.exports = {
if (variable.defs.length > 0 && RESTRICTED.has(variable.name) && !safelyShadowsUndefined(variable)) {
context.report({
node: variable.defs[0].name,
message: "Shadowing of global property '{{idName}}'.",
messageId: "shadowingRestrictedName",
data: {
idName: variable.name
name: variable.name
}
});
}

View File

@@ -26,7 +26,11 @@ module.exports = {
replacedBy: ["func-call-spacing"],
fixable: "whitespace",
schema: []
schema: [],
messages: {
noSpacedFunction: "Unexpected space between function name and paren."
}
},
create(context) {
@@ -62,7 +66,7 @@ module.exports = {
context.report({
node,
loc: lastCalleeToken.loc.start,
message: "Unexpected space between function name and paren.",
messageId: "noSpacedFunction",
fix(fixer) {
return fixer.removeRange([prevToken.range[1], parenToken.range[0]]);
}

View File

@@ -19,7 +19,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-sparse-arrays"
},
schema: []
schema: [],
messages: {
unexpectedSparseArray: "Unexpected comma in middle of array."
}
},
create(context) {
@@ -36,7 +40,7 @@ module.exports = {
const emptySpot = node.elements.indexOf(null) > -1;
if (emptySpot) {
context.report({ node, message: "Unexpected comma in middle of array." });
context.report({ node, messageId: "unexpectedSparseArray" });
}
}

View File

@@ -33,7 +33,11 @@ module.exports = {
},
additionalProperties: false
}
]
],
messages: {
noSync: "Unexpected sync method: '{{propertyName}}'."
}
},
create(context) {
@@ -45,7 +49,7 @@ module.exports = {
[selector](node) {
context.report({
node,
message: "Unexpected sync method: '{{propertyName}}'.",
messageId: "noSync",
data: {
propertyName: node.property.name
}

View File

@@ -35,7 +35,11 @@ module.exports = {
}
},
additionalProperties: false
}]
}],
messages: {
unexpectedTab: "Unexpected tab character."
}
},
create(context) {
@@ -64,7 +68,7 @@ module.exports = {
column: match.index + match[0].length
}
},
message: "Unexpected tab character."
messageId: "unexpectedTab"
});
}
});

View File

@@ -19,7 +19,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-template-curly-in-string"
},
schema: []
schema: [],
messages: {
unexpectedTemplateExpression: "Unexpected template string expression."
}
},
create(context) {
@@ -30,7 +34,7 @@ module.exports = {
if (typeof node.value === "string" && regex.test(node.value)) {
context.report({
node,
message: "Unexpected template string expression."
messageId: "unexpectedTemplateExpression"
});
}
}

View File

@@ -20,7 +20,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-ternary"
},
schema: []
schema: [],
messages: {
noTernaryOperator: "Ternary operator used."
}
},
create(context) {
@@ -28,7 +32,7 @@ module.exports = {
return {
ConditionalExpression(node) {
context.report({ node, message: "Ternary operator used." });
context.report({ node, messageId: "noTernaryOperator" });
}
};

View File

@@ -45,7 +45,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-this-before-super"
},
schema: []
schema: [],
messages: {
noBeforeSuper: "'{{kind}}' is not allowed before 'super()'."
}
},
create(context) {
@@ -187,7 +191,7 @@ module.exports = {
const invalidNode = info.invalidNodes[i];
context.report({
message: "'{{kind}}' is not allowed before 'super()'.",
messageId: "noBeforeSuper",
node: invalidNode,
data: {
kind: invalidNode.type === "Super" ? "super" : "this"

View File

@@ -42,7 +42,11 @@ module.exports = {
},
additionalProperties: false
}
]
],
messages: {
trailingSpace: "Trailing spaces not allowed."
}
},
create(context) {
@@ -74,7 +78,7 @@ module.exports = {
context.report({
node,
loc: location,
message: "Trailing spaces not allowed.",
messageId: "trailingSpace",
fix(fixer) {
return fixer.removeRange(fixRange);
}

View File

@@ -23,7 +23,11 @@ module.exports = {
},
schema: [],
fixable: "code"
fixable: "code",
messages: {
unnecessaryUndefinedInit: "It's not necessary to initialize '{{name}}' to undefined."
}
},
create(context) {
@@ -43,7 +47,7 @@ module.exports = {
if (init === "undefined" && node.parent.kind !== "const" && !shadowed) {
context.report({
node,
message: "It's not necessary to initialize '{{name}}' to undefined.",
messageId: "unnecessaryUndefinedInit",
data: { name },
fix(fixer) {
if (node.parent.kind === "var") {

View File

@@ -19,7 +19,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-undefined"
},
schema: []
schema: [],
messages: {
unexpectedUndefined: "Unexpected use of undefined."
}
},
create(context) {
@@ -32,7 +36,7 @@ module.exports = {
function report(node) {
context.report({
node,
message: "Unexpected use of undefined."
messageId: "unexpectedUndefined"
});
}

View File

@@ -49,7 +49,11 @@ module.exports = {
},
additionalProperties: false
}
]
],
messages: {
unexpectedUnderscore: "Unexpected dangling '_' in '{{identifier}}'."
}
},
create(context) {
@@ -134,7 +138,7 @@ module.exports = {
if (typeof identifier !== "undefined" && hasTrailingUnderscore(identifier) && !isAllowed(identifier)) {
context.report({
node,
message: "Unexpected dangling '_' in '{{identifier}}'.",
messageId: "unexpectedUnderscore",
data: {
identifier
}
@@ -156,7 +160,7 @@ module.exports = {
!isSpecialCaseIdentifierInVariableExpression(identifier) && !isAllowed(identifier)) {
context.report({
node,
message: "Unexpected dangling '_' in '{{identifier}}'.",
messageId: "unexpectedUnderscore",
data: {
identifier
}
@@ -183,7 +187,7 @@ module.exports = {
!isSpecialCaseIdentifierForMemberExpression(identifier) && !isAllowed(identifier)) {
context.report({
node,
message: "Unexpected dangling '_' in '{{identifier}}'.",
messageId: "unexpectedUnderscore",
data: {
identifier
}
@@ -204,7 +208,7 @@ module.exports = {
if (typeof identifier !== "undefined" && enforceInMethodNames && isMethod && hasTrailingUnderscore(identifier)) {
context.report({
node,
message: "Unexpected dangling '_' in '{{identifier}}'.",
messageId: "unexpectedUnderscore",
data: {
identifier
}

View File

@@ -167,7 +167,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-unmodified-loop-condition"
},
schema: []
schema: [],
messages: {
loopConditionNotModified: "'{{name}}' is not modified in this loop."
}
},
create(context) {
@@ -184,7 +188,7 @@ module.exports = {
context.report({
node,
message: "'{{name}}' is not modified in this loop.",
messageId: "loopConditionNotModified",
data: node
});
}

View File

@@ -47,7 +47,12 @@ module.exports = {
}
],
fixable: "code"
fixable: "code",
messages: {
unnecessaryConditionalExpression: "Unnecessary use of boolean literals in conditional expression.",
unnecessaryConditionalAssignment: "Unnecessary use of conditional expression for default assignment."
}
},
create(context) {
@@ -118,7 +123,7 @@ module.exports = {
context.report({
node,
loc: node.consequent.loc.start,
message: "Unnecessary use of boolean literals in conditional expression.",
messageId: "unnecessaryConditionalExpression",
fix(fixer) {
if (node.consequent.value === node.alternate.value) {
@@ -140,7 +145,7 @@ module.exports = {
context.report({
node,
loc: node.consequent.loc.start,
message: "Unnecessary use of conditional expression for default assignment.",
messageId: "unnecessaryConditionalAssignment",
fix: fixer => {
const shouldParenthesizeAlternate = (
astUtils.getPrecedence(node.alternate) < OR_PRECEDENCE &&

View File

@@ -110,7 +110,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-unreachable"
},
schema: []
schema: [],
messages: {
unreachableCode: "Unreachable code."
}
},
create(context) {
@@ -154,7 +158,7 @@ module.exports = {
*/
if (!range.isEmpty) {
context.report({
message: "Unreachable code.",
messageId: "unreachableCode",
loc: range.location,
node: range.startNode
});

View File

@@ -29,7 +29,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-unsafe-finally"
},
schema: []
schema: [],
messages: {
unsafeUsage: "Unsafe usage of {{nodeType}}."
}
},
create(context) {
@@ -86,7 +90,7 @@ module.exports = {
function check(node) {
if (isInFinallyBlock(node, node.label)) {
context.report({
message: "Unsafe usage of {{nodeType}}.",
messageId: "unsafeUsage",
data: {
nodeType: node.type
},

View File

@@ -38,7 +38,11 @@ module.exports = {
},
additionalProperties: false
}
]
],
messages: {
unusedExpression: "Expected an assignment or function call and instead saw an expression."
}
},
create(context) {
@@ -127,7 +131,7 @@ module.exports = {
return {
ExpressionStatement(node) {
if (!isValidExpression(node.expression) && !isDirective(node, context.getAncestors())) {
context.report({ node, message: "Expected an assignment or function call and instead saw an expression." });
context.report({ node, messageId: "unusedExpression" });
}
}
};

View File

@@ -11,6 +11,18 @@
const astUtils = require("./utils/ast-utils");
//------------------------------------------------------------------------------
// Typedefs
//------------------------------------------------------------------------------
/**
* Bag of data used for formatting the `unusedVar` lint message.
* @typedef {Object} UnusedVarMessageData
* @property {string} varName The name of the unused var.
* @property {'defined'|'assigned a value'} action Description of the vars state.
* @property {string} additional Any additional info to be appended at the end.
*/
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
@@ -60,7 +72,11 @@ module.exports = {
}
]
}
]
],
messages: {
unusedVar: "'{{varName}}' is {{action}} but never used{{additional}}."
}
},
create(context) {
@@ -101,12 +117,12 @@ module.exports = {
}
/**
* Generate the warning message about the variable being
* defined and unused, including the ignore pattern if configured.
* Generates the message data about the variable being defined and unused,
* including the ignore pattern if configured.
* @param {Variable} unusedVar eslint-scope variable object.
* @returns {string} The warning message to be used with this unused variable.
* @returns {UnusedVarMessageData} The message data to be used with this unused variable.
*/
function getDefinedMessage(unusedVar) {
function getDefinedMessageData(unusedVar) {
const defType = unusedVar.defs && unusedVar.defs[0] && unusedVar.defs[0].type;
let type;
let pattern;
@@ -122,20 +138,29 @@ module.exports = {
pattern = config.varsIgnorePattern.toString();
}
const additional = type ? ` Allowed unused ${type} must match ${pattern}.` : "";
const additional = type ? `. Allowed unused ${type} must match ${pattern}` : "";
return `'{{name}}' is defined but never used.${additional}`;
return {
varName: unusedVar.name,
action: "defined",
additional
};
}
/**
* Generate the warning message about the variable being
* assigned and unused, including the ignore pattern if configured.
* @returns {string} The warning message to be used with this unused variable.
* @param {Variable} unusedVar eslint-scope variable object.
* @returns {UnusedVarMessageData} The message data to be used with this unused variable.
*/
function getAssignedMessage() {
const additional = config.varsIgnorePattern ? ` Allowed unused vars must match ${config.varsIgnorePattern.toString()}.` : "";
function getAssignedMessageData(unusedVar) {
const additional = config.varsIgnorePattern ? `. Allowed unused vars must match ${config.varsIgnorePattern.toString()}` : "";
return `'{{name}}' is assigned a value but never used.${additional}`;
return {
varName: unusedVar.name,
action: "assigned a value",
additional
};
}
//--------------------------------------------------------------------------
@@ -282,7 +307,7 @@ module.exports = {
function getRhsNode(ref, prevRhsNode) {
const id = ref.identifier;
const parent = id.parent;
const granpa = parent.parent;
const grandparent = parent.parent;
const refScope = ref.from.variableScope;
const varScope = ref.resolved.scope.variableScope;
const canBeUsedLater = refScope !== varScope || astUtils.isInLoop(id);
@@ -296,7 +321,7 @@ module.exports = {
}
if (parent.type === "AssignmentExpression" &&
granpa.type === "ExpressionStatement" &&
grandparent.type === "ExpressionStatement" &&
id === parent.left &&
!canBeUsedLater
) {
@@ -342,7 +367,7 @@ module.exports = {
/*
* If it encountered statements, this is a complex pattern.
* Since analyzeing complex patterns is hard, this returns `true` to avoid false positive.
* Since analyzing complex patterns is hard, this returns `true` to avoid false positive.
*/
return true;
}
@@ -389,7 +414,7 @@ module.exports = {
function isReadForItself(ref, rhsNode) {
const id = ref.identifier;
const parent = id.parent;
const granpa = parent.parent;
const grandparent = parent.parent;
return ref.isRead() && (
@@ -397,12 +422,12 @@ module.exports = {
(// in RHS of an assignment for itself. e.g. `a = a + 1`
((
parent.type === "AssignmentExpression" &&
granpa.type === "ExpressionStatement" &&
grandparent.type === "ExpressionStatement" &&
parent.left === id
) ||
(
parent.type === "UpdateExpression" &&
granpa.type === "ExpressionStatement"
grandparent.type === "ExpressionStatement"
) || rhsNode &&
isInside(id, rhsNode) &&
!isInsideOfStorableFunction(id, rhsNode)))
@@ -595,10 +620,10 @@ module.exports = {
if (unusedVar.defs.length > 0) {
context.report({
node: unusedVar.identifiers[0],
message: unusedVar.references.some(ref => ref.isWrite())
? getAssignedMessage()
: getDefinedMessage(unusedVar),
data: unusedVar
messageId: "unusedVar",
data: unusedVar.references.some(ref => ref.isWrite())
? getAssignedMessageData(unusedVar)
: getDefinedMessageData(unusedVar)
});
// If there are no regular declaration, report the first `/*globals*/` comment directive.
@@ -608,8 +633,8 @@ module.exports = {
context.report({
node: programNode,
loc: astUtils.getNameLocationInGlobalDirectiveComment(sourceCode, directiveComment, unusedVar.name),
message: getDefinedMessage(unusedVar),
data: unusedVar
messageId: "unusedVar",
data: getDefinedMessageData(unusedVar)
});
}
}

View File

@@ -58,7 +58,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-useless-call"
},
schema: []
schema: [],
messages: {
unnecessaryCall: "Unnecessary '.{{name}}()'."
}
},
create(context) {
@@ -75,7 +79,7 @@ module.exports = {
const thisArg = node.arguments[0];
if (isValidThisArg(expectedThis, thisArg, sourceCode)) {
context.report({ node, message: "unnecessary '.{{name}}()'.", data: { name: node.callee.property.name } });
context.report({ node, messageId: "unnecessaryCall", data: { name: node.callee.property.name } });
}
}
};

View File

@@ -20,7 +20,12 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-useless-catch"
},
schema: []
schema: [],
messages: {
unnecessaryCatchClause: "Unnecessary catch clause.",
unnecessaryCatch: "Unnecessary try/catch wrapper."
}
},
create(context) {
@@ -37,12 +42,12 @@ module.exports = {
if (node.parent.finalizer) {
context.report({
node,
message: "Unnecessary catch clause."
messageId: "unnecessaryCatchClause"
});
} else {
context.report({
node: node.parent,
message: "Unnecessary try/catch wrapper."
messageId: "unnecessaryCatch"
});
}
}

View File

@@ -15,8 +15,6 @@ const astUtils = require("./utils/ast-utils");
// Rule Definition
//------------------------------------------------------------------------------
const MESSAGE_UNNECESSARY_COMPUTED = "Unnecessarily computed property [{{property}}] found.";
module.exports = {
meta: {
type: "suggestion",
@@ -38,7 +36,11 @@ module.exports = {
},
additionalProperties: false
}],
fixable: "code"
fixable: "code",
messages: {
unnecessarilyComputedProperty: "Unnecessarily computed property [{{property}}] found."
}
},
create(context) {
const sourceCode = context.getSourceCode();
@@ -68,7 +70,7 @@ module.exports = {
if (key.type === "Literal" && (nodeType === "string" || nodeType === "number") && key.value !== allowedKey) {
context.report({
node,
message: MESSAGE_UNNECESSARY_COMPUTED,
messageId: "unnecessarilyComputedProperty",
data: { property: sourceCode.getText(key) },
fix(fixer) {
const leftSquareBracket = sourceCode.getTokenBefore(key, astUtils.isOpeningBracketToken);

View File

@@ -1,5 +1,5 @@
/**
* @fileoverview disallow unncessary concatenation of template strings
* @fileoverview disallow unnecessary concatenation of template strings
* @author Henry Zhu
*/
"use strict";
@@ -75,7 +75,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-useless-concat"
},
schema: []
schema: [],
messages: {
unexpectedConcat: "Unexpected string concatenation of literals."
}
},
create(context) {
@@ -102,7 +106,7 @@ module.exports = {
context.report({
node,
loc: operatorToken.loc.start,
message: "Unexpected string concatenation of literals."
messageId: "unexpectedConcat"
});
}
}

View File

@@ -115,7 +115,7 @@ function isPassingThrough(ctorParams, superArgs) {
* Checks whether the constructor body is a redundant super call.
* @param {Array} body constructor body content.
* @param {Array} ctorParams The params to check against super call.
* @returns {boolean} true if the construtor body is redundant
* @returns {boolean} true if the constructor body is redundant
*/
function isRedundantSuperCall(body, ctorParams) {
return (

View File

@@ -32,7 +32,11 @@ module.exports = {
},
additionalProperties: false
}
]
],
messages: {
unnecessarilyRenamed: "{{type}} {{name}} unnecessarily renamed."
}
},
create(context) {
@@ -59,7 +63,7 @@ module.exports = {
return context.report({
node,
message: "{{type}} {{name}} unnecessarily renamed.",
messageId: "unnecessarilyRenamed",
data: {
name,
type

View File

@@ -32,7 +32,7 @@ function remove(array, element) {
/**
* Checks whether it can remove the given return statement or not.
* @param {ASTNode} node The return statement node to check.
* @returns {boolean} `true` if the node is removeable.
* @returns {boolean} `true` if the node is removable.
*/
function isRemovable(node) {
return astUtils.STATEMENT_LIST_PARENTS.has(node.parent.type);
@@ -73,7 +73,11 @@ module.exports = {
},
fixable: "code",
schema: []
schema: [],
messages: {
unnecessaryReturn: "Unnecessary return statement."
}
},
create(context) {
@@ -208,7 +212,7 @@ module.exports = {
context.report({
node,
loc: node.loc,
message: "Unnecessary return statement.",
messageId: "unnecessaryReturn",
fix(fixer) {
if (isRemovable(node) && !sourceCode.getCommentsInside(node).length) {

View File

@@ -191,7 +191,11 @@ module.exports = {
},
schema: [],
fixable: "code"
fixable: "code",
messages: {
unexpectedVar: "Unexpected var, use let or const instead."
}
},
create(context) {
@@ -307,7 +311,7 @@ module.exports = {
function report(node) {
context.report({
node,
message: "Unexpected var, use let or const instead.",
messageId: "unexpectedVar",
fix(fixer) {
const varToken = sourceCode.getFirstToken(node, { filter: t => t.value === "var" });

View File

@@ -39,7 +39,11 @@ module.exports = {
},
additionalProperties: false
}
]
],
messages: {
unexpectedComment: "Unexpected '{{matchedTerm}}' comment."
}
},
create(context) {
@@ -140,7 +144,7 @@ module.exports = {
matches.forEach(matchedTerm => {
context.report({
node,
message: "Unexpected '{{matchedTerm}}' comment.",
messageId: "unexpectedComment",
data: {
matchedTerm
}

View File

@@ -26,7 +26,11 @@ module.exports = {
},
fixable: "whitespace",
schema: []
schema: [],
messages: {
unexpectedWhitespace: "Unexpected whitespace before property {{propName}}."
}
},
create(context) {
@@ -49,7 +53,7 @@ module.exports = {
context.report({
node,
message: "Unexpected whitespace before property {{propName}}.",
messageId: "unexpectedWhitespace",
data: {
propName: sourceCode.getText(node.property)
},

View File

@@ -20,14 +20,18 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-with"
},
schema: []
schema: [],
messages: {
unexpectedWith: "Unexpected use of 'with' statement."
}
},
create(context) {
return {
WithStatement(node) {
context.report({ node, message: "Unexpected use of 'with' statement." });
context.report({ node, messageId: "unexpectedWith" });
}
};

View File

@@ -40,7 +40,12 @@ module.exports = {
},
additionalProperties: false
}
]
],
messages: {
expectNoLinebreak: "Expected no linebreak before this statement.",
expectLinebreak: "Expected a linebreak before this statement."
}
},
create(context) {
@@ -79,13 +84,13 @@ module.exports = {
if (tokenBefore.loc.end.line === node.loc.start.line && option === "below") {
context.report({
node,
message: "Expected a linebreak before this statement.",
messageId: "expectLinebreak",
fix: fixer => fixer.insertTextBefore(node, "\n")
});
} else if (tokenBefore.loc.end.line !== node.loc.start.line && option === "beside") {
context.report({
node,
message: "Expected no linebreak before this statement.",
messageId: "expectNoLinebreak",
fix(fixer) {
if (sourceCode.getText().slice(tokenBefore.range[1], node.range[0]).trim()) {
return null;

View File

@@ -159,7 +159,14 @@ module.exports = {
}
]
}
]
],
messages: {
unexpectedLinebreakBeforeClosingBrace: "Unexpected line break before this closing brace.",
unexpectedLinebreakAfterOpeningBrace: "Unexpected line break after this opening brace.",
expectedLinebreakBeforeClosingBrace: "Expected a line break before this closing brace.",
expectedLinebreakAfterOpeningBrace: "Expected a line break after this opening brace."
}
},
create(context) {
@@ -215,7 +222,7 @@ module.exports = {
if (needsLineBreaks) {
if (astUtils.isTokenOnSameLine(openBrace, first)) {
context.report({
message: "Expected a line break after this opening brace.",
messageId: "expectedLinebreakAfterOpeningBrace",
node,
loc: openBrace.loc.start,
fix(fixer) {
@@ -229,7 +236,7 @@ module.exports = {
}
if (astUtils.isTokenOnSameLine(last, closeBrace)) {
context.report({
message: "Expected a line break before this closing brace.",
messageId: "expectedLinebreakBeforeClosingBrace",
node,
loc: closeBrace.loc.start,
fix(fixer) {
@@ -251,7 +258,7 @@ module.exports = {
(consistent && hasLineBreakBetweenOpenBraceAndFirst && !hasLineBreakBetweenCloseBraceAndLast)
) {
context.report({
message: "Unexpected line break after this opening brace.",
messageId: "unexpectedLinebreakAfterOpeningBrace",
node,
loc: openBrace.loc.start,
fix(fixer) {
@@ -271,7 +278,7 @@ module.exports = {
(consistent && !hasLineBreakBetweenOpenBraceAndFirst && hasLineBreakBetweenCloseBraceAndLast)
) {
context.report({
message: "Unexpected line break before this closing brace.",
messageId: "unexpectedLinebreakBeforeClosingBrace",
node,
loc: closeBrace.loc.start,
fix(fixer) {

View File

@@ -39,7 +39,14 @@ module.exports = {
},
additionalProperties: false
}
]
],
messages: {
requireSpaceBefore: "A space is required before '{{token}}'.",
requireSpaceAfter: "A space is required after '{{token}}'.",
unexpectedSpaceBefore: "There should be no space before '{{token}}'.",
unexpectedSpaceAfter: "There should be no space after '{{token}}'."
}
},
create(context) {
@@ -79,7 +86,7 @@ module.exports = {
context.report({
node,
loc: { start: token.loc.end, end: nextToken.loc.start },
message: "There should be no space after '{{token}}'.",
messageId: "unexpectedSpaceAfter",
data: {
token: token.value
},
@@ -101,7 +108,7 @@ module.exports = {
context.report({
node,
loc: { start: previousToken.loc.end, end: token.loc.start },
message: "There should be no space before '{{token}}'.",
messageId: "unexpectedSpaceBefore",
data: {
token: token.value
},
@@ -121,7 +128,7 @@ module.exports = {
context.report({
node,
loc: token.loc,
message: "A space is required after '{{token}}'.",
messageId: "requireSpaceAfter",
data: {
token: token.value
},
@@ -141,7 +148,7 @@ module.exports = {
context.report({
node,
loc: token.loc,
message: "A space is required before '{{token}}'.",
messageId: "requireSpaceBefore",
data: {
token: token.value
},

View File

@@ -37,16 +37,21 @@ module.exports = {
}
],
fixable: "whitespace"
fixable: "whitespace",
messages: {
propertiesOnNewlineAll: "Object properties must go on a new line if they aren't all on the same line.",
propertiesOnNewline: "Object properties must go on a new line."
}
},
create(context) {
const allowSameLine = context.options[0] && (
(context.options[0].allowAllPropertiesOnSameLine || 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.";
const messageId = allowSameLine
? "propertiesOnNewlineAll"
: "propertiesOnNewline";
const sourceCode = context.getSourceCode();
@@ -73,7 +78,7 @@ module.exports = {
context.report({
node,
loc: firstTokenOfCurrentProperty.loc.start,
message: errorMessage,
messageId,
fix(fixer) {
const comma = sourceCode.getTokenBefore(firstTokenOfCurrentProperty);
const rangeAfterComma = [comma.range[1], firstTokenOfCurrentProperty.range[0]];

View File

@@ -92,6 +92,16 @@ module.exports = {
maxItems: 2
}
]
},
messages: {
expectedAllPropertiesShorthanded: "Expected shorthand for all properties.",
expectedLiteralMethodLongform: "Expected longform method syntax for string literal keys.",
expectedPropertyShorthand: "Expected property shorthand.",
expectedPropertyLongform: "Expected longform property syntax.",
expectedMethodShorthand: "Expected method shorthand.",
expectedMethodLongform: "Expected longform method syntax.",
unexpectedMix: "Unexpected mix of shorthand and non-shorthand properties."
}
},
@@ -211,7 +221,7 @@ module.exports = {
// We have at least 1 shorthand property
if (shorthandProperties.length > 0) {
context.report({ node, message: "Unexpected mix of shorthand and non-shorthand properties." });
context.report({ node, messageId: "unexpectedMix" });
} else if (checkRedundancy) {
/*
@@ -221,7 +231,7 @@ module.exports = {
const canAlwaysUseShorthand = properties.every(isRedundant);
if (canAlwaysUseShorthand) {
context.report({ node, message: "Expected shorthand for all properties." });
context.report({ node, messageId: "expectedAllPropertiesShorthanded" });
}
}
}
@@ -430,12 +440,12 @@ module.exports = {
// Checks for property/method shorthand.
if (isConciseProperty) {
if (node.method && (APPLY_NEVER || AVOID_QUOTES && isStringLiteral(node.key))) {
const message = APPLY_NEVER ? "Expected longform method syntax." : "Expected longform method syntax for string literal keys.";
const messageId = APPLY_NEVER ? "expectedMethodLongform" : "expectedLiteralMethodLongform";
// { x() {} } should be written as { x: function() {} }
context.report({
node,
message,
messageId,
fix: fixer => makeFunctionLongform(fixer, node)
});
} else if (APPLY_NEVER) {
@@ -443,7 +453,7 @@ module.exports = {
// { x } should be written as { x: x }
context.report({
node,
message: "Expected longform property syntax.",
messageId: "expectedPropertyLongform",
fix: fixer => fixer.insertTextAfter(node.key, `: ${node.key.name}`)
});
}
@@ -464,7 +474,7 @@ module.exports = {
) {
context.report({
node,
message: "Expected method shorthand.",
messageId: "expectedMethodShorthand",
fix: fixer => makeFunctionShorthand(fixer, node)
});
}
@@ -473,7 +483,7 @@ module.exports = {
// {x: x} should be written as {x}
context.report({
node,
message: "Expected property shorthand.",
messageId: "expectedPropertyShorthand",
fix(fixer) {
return fixer.replaceText(node, node.value.name);
}
@@ -486,7 +496,7 @@ module.exports = {
// {"x": x} should be written as {x}
context.report({
node,
message: "Expected property shorthand.",
messageId: "expectedPropertyShorthand",
fix(fixer) {
return fixer.replaceText(node, node.value.name);
}

View File

@@ -25,12 +25,15 @@ module.exports = {
}
],
fixable: "whitespace"
fixable: "whitespace",
messages: {
expectVarOnNewline: "Expected variable declaration to be on a new line."
}
},
create(context) {
const ERROR_MESSAGE = "Expected variable declaration to be on a new line.";
const always = context.options[0] === "always";
//--------------------------------------------------------------------------
@@ -67,7 +70,7 @@ module.exports = {
if (always || prev.init || current.init) {
context.report({
node,
message: ERROR_MESSAGE,
messageId: "expectVarOnNewline",
loc: current.loc.start,
fix: fixer => fixer.insertTextBefore(current, "\n")
});

View File

@@ -60,7 +60,17 @@ module.exports = {
}
]
}
]
],
messages: {
combineUninitialized: "Combine this with the previous '{{type}}' statement with uninitialized variables.",
combineInitialized: "Combine this with the previous '{{type}}' statement with initialized variables.",
splitUninitialized: "Split uninitialized '{{type}}' declarations into multiple statements.",
splitInitialized: "Split initialized '{{type}}' declarations into multiple statements.",
splitRequires: "Split requires to be separated into a single block.",
combine: "Combine this with the previous '{{type}}' statement.",
split: "Split '{{type}}' declarations into multiple statements."
}
},
create(context) {
@@ -361,7 +371,7 @@ module.exports = {
if (options.separateRequires && mixedRequires) {
context.report({
node,
message: "Split requires to be separated into a single block."
messageId: "splitRequires"
});
}
}
@@ -384,7 +394,7 @@ module.exports = {
if (options[type].initialized === MODE_CONSECUTIVE && options[type].uninitialized === MODE_CONSECUTIVE) {
context.report({
node,
message: "Combine this with the previous '{{type}}' statement.",
messageId: "combine",
data: {
type
},
@@ -393,7 +403,7 @@ module.exports = {
} else if (options[type].initialized === MODE_CONSECUTIVE && declarationCounts.initialized > 0 && previousDeclCounts.initialized > 0) {
context.report({
node,
message: "Combine this with the previous '{{type}}' statement with initialized variables.",
messageId: "combineInitialized",
data: {
type
},
@@ -404,7 +414,7 @@ module.exports = {
previousDeclCounts.uninitialized > 0) {
context.report({
node,
message: "Combine this with the previous '{{type}}' statement with uninitialized variables.",
messageId: "combineUninitialized",
data: {
type
},
@@ -419,7 +429,7 @@ module.exports = {
if (options[type].initialized === MODE_ALWAYS && options[type].uninitialized === MODE_ALWAYS) {
context.report({
node,
message: "Combine this with the previous '{{type}}' statement.",
messageId: "combine",
data: {
type
},
@@ -429,7 +439,7 @@ module.exports = {
if (options[type].initialized === MODE_ALWAYS && declarationCounts.initialized > 0) {
context.report({
node,
message: "Combine this with the previous '{{type}}' statement with initialized variables.",
messageId: "combineInitialized",
data: {
type
},
@@ -442,7 +452,7 @@ module.exports = {
}
context.report({
node,
message: "Combine this with the previous '{{type}}' statement with uninitialized variables.",
messageId: "combineUninitialized",
data: {
type
},
@@ -462,7 +472,7 @@ module.exports = {
// both initialized and uninitialized
context.report({
node,
message: "Split '{{type}}' declarations into multiple statements.",
messageId: "split",
data: {
type
},
@@ -473,7 +483,7 @@ module.exports = {
// initialized
context.report({
node,
message: "Split initialized '{{type}}' declarations into multiple statements.",
messageId: "splitInitialized",
data: {
type
},
@@ -484,7 +494,7 @@ module.exports = {
// uninitialized
context.report({
node,
message: "Split uninitialized '{{type}}' declarations into multiple statements.",
messageId: "splitUninitialized",
data: {
type
},

View File

@@ -26,10 +26,10 @@ function isCommutativeOperatorWithShorthand(operator) {
}
/**
* Checks whether an operator is not commuatative and has an operator assignment
* Checks whether an operator is not commutative and has an operator assignment
* shorthand form.
* @param {string} operator Operator to check.
* @returns {boolean} True if the operator is not commuatative and has
* @returns {boolean} True if the operator is not commutative and has
* a shorthand form.
*/
function isNonCommutativeOperatorWithShorthand(operator) {
@@ -219,7 +219,7 @@ module.exports = {
if (
operatorToken.range[1] === firstRightToken.range[0] &&
!astUtils.canTokensBeAdjacent(newOperator, firstRightToken)
!astUtils.canTokensBeAdjacent({ type: "Punctuator", value: newOperator }, firstRightToken)
) {
rightTextPrefix = " "; // foo+=+bar -> foo= foo+ +bar
}

View File

@@ -47,7 +47,14 @@ module.exports = {
}
],
fixable: "code"
fixable: "code",
messages: {
operatorAtBeginning: "'{{operator}}' should be placed at the beginning of the line.",
operatorAtEnd: "'{{operator}}' should be placed at the end of the line.",
badLinebreak: "Bad line breaking before and after '{{operator}}'.",
noLinebreak: "There should be no line break before or after '{{operator}}'."
}
},
create(context) {
@@ -169,7 +176,7 @@ module.exports = {
line: operatorToken.loc.end.line,
column: operatorToken.loc.end.column
},
message: "Bad line breaking before and after '{{operator}}'.",
messageId: "badLinebreak",
data: {
operator
},
@@ -184,7 +191,7 @@ module.exports = {
line: operatorToken.loc.end.line,
column: operatorToken.loc.end.column
},
message: "'{{operator}}' should be placed at the beginning of the line.",
messageId: "operatorAtBeginning",
data: {
operator
},
@@ -199,7 +206,7 @@ module.exports = {
line: operatorToken.loc.end.line,
column: operatorToken.loc.end.column
},
message: "'{{operator}}' should be placed at the end of the line.",
messageId: "operatorAtEnd",
data: {
operator
},
@@ -214,7 +221,7 @@ module.exports = {
line: operatorToken.loc.end.line,
column: operatorToken.loc.end.column
},
message: "There should be no line break before or after '{{operator}}'.",
messageId: "noLinebreak",
data: {
operator
},

View File

@@ -60,7 +60,12 @@ module.exports = {
}
}
}
]
],
messages: {
alwaysPadBlock: "Block must be padded by blank lines.",
neverPadBlock: "Block must not be padded by blank lines."
}
},
create(context) {
@@ -90,9 +95,6 @@ module.exports = {
options.allowSingleLineBlocks = exceptOptions.allowSingleLineBlocks === true;
}
const ALWAYS_MESSAGE = "Block must be padded by blank lines.",
NEVER_MESSAGE = "Block must not be padded by blank lines.";
const sourceCode = context.getSourceCode();
/**
@@ -145,9 +147,9 @@ module.exports = {
}
/**
* Checks if the given token is preceeded by a blank line.
* Checks if the given token is preceded by a blank line.
* @param {Token} token The token to check
* @returns {boolean} Whether or not the token is preceeded by a blank line
* @returns {boolean} Whether or not the token is preceded by a blank line
*/
function getLastBlockToken(token) {
let last = token,
@@ -208,7 +210,7 @@ module.exports = {
fix(fixer) {
return fixer.insertTextAfter(tokenBeforeFirst, "\n");
},
message: ALWAYS_MESSAGE
messageId: "alwaysPadBlock"
});
}
if (!blockHasBottomPadding) {
@@ -218,7 +220,7 @@ module.exports = {
fix(fixer) {
return fixer.insertTextBefore(tokenAfterLast, "\n");
},
message: ALWAYS_MESSAGE
messageId: "alwaysPadBlock"
});
}
} else {
@@ -230,7 +232,7 @@ module.exports = {
fix(fixer) {
return fixer.replaceTextRange([tokenBeforeFirst.range[1], firstBlockToken.range[0] - firstBlockToken.loc.start.column], "\n");
},
message: NEVER_MESSAGE
messageId: "neverPadBlock"
});
}
@@ -239,7 +241,7 @@ module.exports = {
context.report({
node,
loc: { line: tokenAfterLast.loc.end.line, column: tokenAfterLast.loc.end.column - 1 },
message: NEVER_MESSAGE,
messageId: "neverPadBlock",
fix(fixer) {
return fixer.replaceTextRange([lastBlockToken.range[1], tokenAfterLast.range[0] - tokenAfterLast.loc.start.column], "\n");
}

View File

@@ -243,7 +243,7 @@ function verifyForNever(context, _, nextNode, paddingLines) {
context.report({
node: nextNode,
message: "Unexpected blank line before this statement.",
messageId: "unexpectedBlankLine",
fix(fixer) {
if (paddingLines.length >= 2) {
return null;
@@ -282,7 +282,7 @@ function verifyForAlways(context, prevNode, nextNode, paddingLines) {
context.report({
node: nextNode,
message: "Expected blank line before this statement.",
messageId: "expectedBlankLine",
fix(fixer) {
const sourceCode = context.getSourceCode();
let prevToken = getActualLastToken(sourceCode, prevNode);
@@ -468,6 +468,11 @@ module.exports = {
required: ["blankLine", "prev", "next"]
},
additionalItems: false
},
messages: {
unexpectedBlankLine: "Unexpected blank line before this statement.",
expectedBlankLine: "Expected blank line before this statement."
}
},

View File

@@ -56,7 +56,7 @@ function getVariableOfArguments(scope) {
}
/**
* Checkes whether or not a given node is a callback.
* Checks whether or not a given node is a callback.
* @param {ASTNode} node A node to check.
* @returns {Object}
* {boolean} retv.isCallback - `true` if the node is a callback.
@@ -158,7 +158,11 @@ module.exports = {
}
],
fixable: "code"
fixable: "code",
messages: {
preferArrowCallback: "Unexpected function expression."
}
},
create(context) {
@@ -267,7 +271,7 @@ module.exports = {
) {
context.report({
node,
message: "Unexpected function expression.",
messageId: "preferArrowCallback",
fix(fixer) {
if ((!callbackInfo.isLexicalThis && scopeInfo.this) || hasDuplicateParams(node.params)) {

View File

@@ -82,7 +82,11 @@ module.exports = {
},
additionalProperties: false
}
]
],
messages: {
preferDestructuring: "Use {{type}} destructuring."
}
},
create(context) {
@@ -137,7 +141,7 @@ module.exports = {
function report(reportNode, type, fix) {
context.report({
node: reportNode,
message: "Use {{type}} destructuring.",
messageId: "preferDestructuring",
data: { type },
fix
});

View File

@@ -98,7 +98,7 @@ function argNeedsParens(node, sourceCode) {
/**
* Get the parenthesis tokens of a given ObjectExpression node.
* This incldues the braces of the object literal and enclosing parentheses.
* This includes the braces of the object literal and enclosing parentheses.
* @param {ASTNode} node The node to get.
* @param {Token} leftArgumentListParen The opening paren token of the argument list.
* @param {SourceCode} sourceCode The source code object to get tokens.

View File

@@ -31,7 +31,11 @@ module.exports = {
},
additionalProperties: false
}
]
],
messages: {
rejectAnError: "Expected the Promise rejection reason to be an Error."
}
},
create(context) {
@@ -58,7 +62,7 @@ module.exports = {
) {
context.report({
node: callExpression,
message: "Expected the Promise rejection reason to be an Error."
messageId: "rejectAnError"
});
}
}

View File

@@ -49,7 +49,11 @@ module.exports = {
},
additionalProperties: false
}
]
],
messages: {
preferReflect: "Avoid using {{existing}}, instead use {{substitute}}."
}
},
create(context) {
@@ -65,7 +69,7 @@ module.exports = {
preventExtensions: "Object.preventExtensions"
};
const reflectSubsitutes = {
const reflectSubstitutes = {
apply: "Reflect.apply",
call: "Reflect.apply",
defineProperty: "Reflect.defineProperty",
@@ -89,7 +93,7 @@ module.exports = {
function report(node, existing, substitute) {
context.report({
node,
message: "Avoid using {{existing}}, instead use {{substitute}}.",
messageId: "preferReflect",
data: {
existing,
substitute
@@ -101,11 +105,11 @@ module.exports = {
CallExpression(node) {
const methodName = (node.callee.property || {}).name;
const isReflectCall = (node.callee.object || {}).name === "Reflect";
const hasReflectSubsitute = Object.prototype.hasOwnProperty.call(reflectSubsitutes, methodName);
const hasReflectSubsitute = Object.prototype.hasOwnProperty.call(reflectSubstitutes, methodName);
const userConfiguredException = exceptions.indexOf(methodName) !== -1;
if (hasReflectSubsitute && !isReflectCall && !userConfiguredException) {
report(node, existingNames[methodName], reflectSubsitutes[methodName]);
report(node, existingNames[methodName], reflectSubstitutes[methodName]);
}
},
UnaryExpression(node) {

View File

@@ -70,7 +70,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/prefer-rest-params"
},
schema: []
schema: [],
messages: {
preferRestParams: "Use the rest parameters instead of 'arguments'."
}
},
create(context) {
@@ -84,7 +88,7 @@ module.exports = {
context.report({
node: reference.identifier,
loc: reference.identifier.loc,
message: "Use the rest parameters instead of 'arguments'."
messageId: "preferRestParams"
});
}

View File

@@ -59,7 +59,11 @@ module.exports = {
},
schema: [],
fixable: null
fixable: null,
messages: {
preferSpread: "Use the spread operator instead of '.apply()'."
}
},
create(context) {
@@ -78,7 +82,7 @@ module.exports = {
if (isValidThisArg(expectedThis, thisArg, sourceCode)) {
context.report({
node,
message: "Use the spread operator instead of '.apply()'."
messageId: "preferSpread"
});
}
}

View File

@@ -142,7 +142,11 @@ module.exports = {
},
schema: [],
fixable: "code"
fixable: "code",
messages: {
unexpectedStringConcatenation: "Unexpected string concatenation."
}
},
create(context) {
@@ -261,7 +265,7 @@ module.exports = {
if (hasNonStringLiteral(topBinaryExpr)) {
context.report({
node: topBinaryExpr,
message: "Unexpected string concatenation.",
messageId: "unexpectedStringConcatenation",
fix: fixer => fixNonStringBinaryExpression(fixer, node)
});
}

View File

@@ -67,7 +67,16 @@ module.exports = {
]
},
fixable: "code"
fixable: "code",
messages: {
requireQuotesDueToReservedWord: "Properties should be quoted as '{{property}}' is a reserved word.",
inconsistentlyQuotedProperty: "Inconsistently quoted property '{{key}}' found.",
unnecessarilyQuotedProperty: "Unnecessarily quoted property '{{property}}' found.",
unquotedReservedProperty: "Unquoted reserved word '{{property}}' used as key.",
unquotedNumericProperty: "Unquoted number literal '{{property}}' used as key.",
unquotedPropertyFound: "Unquoted property '{{property}}' found.",
redundantQuoting: "Properties shouldn't be quoted as all quotes are redundant."
}
},
create(context) {
@@ -77,10 +86,6 @@ module.exports = {
CHECK_UNNECESSARY = !context.options[1] || context.options[1].unnecessary !== false,
NUMBERS = context.options[1] && context.options[1].numbers,
MESSAGE_UNNECESSARY = "Unnecessarily quoted property '{{property}}' found.",
MESSAGE_UNQUOTED = "Unquoted property '{{property}}' found.",
MESSAGE_NUMERIC = "Unquoted number literal '{{property}}' used as key.",
MESSAGE_RESERVED = "Unquoted reserved word '{{property}}' used as key.",
sourceCode = context.getSourceCode();
@@ -166,7 +171,7 @@ module.exports = {
if (CHECK_UNNECESSARY && areQuotesRedundant(key.value, tokens, NUMBERS)) {
context.report({
node,
message: MESSAGE_UNNECESSARY,
messageId: "unnecessarilyQuotedProperty",
data: { property: key.value },
fix: fixer => fixer.replaceText(key, getUnquotedKey(key))
});
@@ -174,14 +179,14 @@ module.exports = {
} else if (KEYWORDS && key.type === "Identifier" && isKeyword(key.name)) {
context.report({
node,
message: MESSAGE_RESERVED,
messageId: "unquotedReservedProperty",
data: { property: key.name },
fix: fixer => fixer.replaceText(key, getQuotedKey(key))
});
} else if (NUMBERS && key.type === "Literal" && astUtils.isNumericLiteral(key)) {
context.report({
node,
message: MESSAGE_NUMERIC,
messageId: "unquotedNumericProperty",
data: { property: key.value },
fix: fixer => fixer.replaceText(key, getQuotedKey(key))
});
@@ -199,7 +204,7 @@ module.exports = {
if (!node.method && !node.computed && !node.shorthand && !(key.type === "Literal" && typeof key.value === "string")) {
context.report({
node,
message: MESSAGE_UNQUOTED,
messageId: "unquotedPropertyFound",
data: { property: key.name || key.value },
fix: fixer => fixer.replaceText(key, getQuotedKey(key))
});
@@ -254,7 +259,7 @@ module.exports = {
quotedProps.forEach(property => {
context.report({
node: property,
message: "Properties shouldn't be quoted as all quotes are redundant.",
messageId: "redundantQuoting",
fix: fixer => fixer.replaceText(property.key, getUnquotedKey(property.key))
});
});
@@ -262,7 +267,7 @@ module.exports = {
unquotedProps.forEach(property => {
context.report({
node: property,
message: "Properties should be quoted as '{{property}}' is a reserved word.",
messageId: "requireQuotesDueToReservedWord",
data: { property: keywordKeyName },
fix: fixer => fixer.replaceText(property.key, getQuotedKey(property.key))
});
@@ -271,7 +276,7 @@ module.exports = {
unquotedProps.forEach(property => {
context.report({
node: property,
message: "Inconsistently quoted property '{{key}}' found.",
messageId: "inconsistentlyQuotedProperty",
data: { key: property.key.name || property.key.value },
fix: fixer => fixer.replaceText(property.key, getQuotedKey(property.key))
});

View File

@@ -18,6 +18,8 @@ const astUtils = require("./utils/ast-utils");
const MODE_ALWAYS = "always",
MODE_AS_NEEDED = "as-needed";
const validRadixValues = new Set(Array.from({ length: 37 - 2 }, (_, index) => index + 2));
/**
* Checks whether a given variable is shadowed or not.
* @param {eslint-scope.Variable} variable A variable to check.
@@ -47,14 +49,14 @@ function isParseIntMethod(node) {
*
* The following values are invalid.
*
* - A literal except numbers.
* - A literal except integers between 2 and 36.
* - undefined.
* @param {ASTNode} radix A node of radix to check.
* @returns {boolean} `true` if the node is valid.
*/
function isValidRadix(radix) {
return !(
(radix.type === "Literal" && typeof radix.value !== "number") ||
(radix.type === "Literal" && !validRadixValues.has(radix.value)) ||
(radix.type === "Identifier" && radix.name === "undefined")
);
}
@@ -87,7 +89,14 @@ module.exports = {
{
enum: ["always", "as-needed"]
}
]
],
messages: {
missingParameters: "Missing parameters.",
redundantRadix: "Redundant radix parameter.",
missingRadix: "Missing radix parameter.",
invalidRadix: "Invalid radix parameter, must be an integer between 2 and 36."
}
},
create(context) {
@@ -106,7 +115,7 @@ module.exports = {
case 0:
context.report({
node,
message: "Missing parameters."
messageId: "missingParameters"
});
break;
@@ -114,7 +123,7 @@ module.exports = {
if (mode === MODE_ALWAYS) {
context.report({
node,
message: "Missing radix parameter."
messageId: "missingRadix"
});
}
break;
@@ -123,12 +132,12 @@ module.exports = {
if (mode === MODE_AS_NEEDED && isDefaultRadix(args[1])) {
context.report({
node,
message: "Redundant radix parameter."
messageId: "redundantRadix"
});
} else if (!isValidRadix(args[1])) {
context.report({
node,
message: "Invalid radix parameter."
messageId: "invalidRadix"
});
}
break;
@@ -142,7 +151,7 @@ module.exports = {
// Check `parseInt()`
variable = astUtils.getVariableByName(scope, "parseInt");
if (!isShadowed(variable)) {
if (variable && !isShadowed(variable)) {
variable.references.forEach(reference => {
const node = reference.identifier;
@@ -154,7 +163,7 @@ module.exports = {
// Check `Number.parseInt()`
variable = astUtils.getVariableByName(scope, "Number");
if (!isShadowed(variable)) {
if (variable && !isShadowed(variable)) {
variable.references.forEach(reference => {
const node = reference.identifier.parent;

View File

@@ -223,7 +223,7 @@ module.exports = {
/*
* Register the variable to verify after ESLint traversed the `writeExpr` node
* if this reference is an assignment to a variable which is referred from other clausure.
* if this reference is an assignment to a variable which is referred from other closure.
*/
if (writeExpr &&
writeExpr.parent.right === writeExpr && // ← exclude variable declarations.

View File

@@ -52,7 +52,11 @@ module.exports = {
],
deprecated: true,
replacedBy: []
replacedBy: [],
messages: {
missingJSDocComment: "Missing JSDoc comment."
}
},
create(context) {
@@ -72,7 +76,7 @@ module.exports = {
* @returns {void}
*/
function report(node) {
context.report({ node, message: "Missing JSDoc comment." });
context.report({ node, messageId: "missingJSDocComment" });
}
/**

View File

@@ -20,7 +20,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/require-yield"
},
schema: []
schema: [],
messages: {
missingYield: "This generator function does not have 'yield'."
}
},
create(context) {
@@ -51,7 +55,7 @@ module.exports = {
const countYield = stack.pop();
if (countYield === 0 && node.body.body.length > 0) {
context.report({ node, message: "This generator function does not have 'yield'." });
context.report({ node, messageId: "missingYield" });
}
}

View File

@@ -26,7 +26,12 @@ module.exports = {
{
enum: ["always", "never"]
}
]
],
messages: {
unexpectedWhitespace: "Unexpected whitespace after {{type}} operator.",
expectedWhitespace: "Expected whitespace after {{type}} operator."
}
},
create(context) {
@@ -78,7 +83,7 @@ module.exports = {
line: operator.loc.end.line,
column: operator.loc.end.column
},
message: "Expected whitespace after {{type}} operator.",
messageId: "expectedWhitespace",
data: {
type
},
@@ -93,7 +98,7 @@ module.exports = {
line: operator.loc.end.line,
column: operator.loc.end.column
},
message: "Unexpected whitespace after {{type}} operator.",
messageId: "unexpectedWhitespace",
data: {
type
},

View File

@@ -39,7 +39,14 @@ module.exports = {
},
additionalProperties: false
}
]
],
messages: {
unexpectedWhitespaceBefore: "Unexpected whitespace before semicolon.",
unexpectedWhitespaceAfter: "Unexpected whitespace after semicolon.",
missingWhitespaceBefore: "Missing whitespace before semicolon.",
missingWhitespaceAfter: "Missing whitespace after semicolon."
}
},
create(context) {
@@ -124,7 +131,7 @@ module.exports = {
context.report({
node,
loc: location,
message: "Unexpected whitespace before semicolon.",
messageId: "unexpectedWhitespaceBefore",
fix(fixer) {
const tokenBefore = sourceCode.getTokenBefore(token);
@@ -137,7 +144,7 @@ module.exports = {
context.report({
node,
loc: location,
message: "Missing whitespace before semicolon.",
messageId: "missingWhitespaceBefore",
fix(fixer) {
return fixer.insertTextBefore(token, " ");
}
@@ -151,7 +158,7 @@ module.exports = {
context.report({
node,
loc: location,
message: "Unexpected whitespace after semicolon.",
messageId: "unexpectedWhitespaceAfter",
fix(fixer) {
const tokenAfter = sourceCode.getTokenAfter(token);
@@ -164,7 +171,7 @@ module.exports = {
context.report({
node,
loc: location,
message: "Missing whitespace after semicolon.",
messageId: "missingWhitespaceAfter",
fix(fixer) {
return fixer.insertTextAfter(token, " ");
}

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