diff --git a/.eslintrc.js b/.eslintrc.js index 59d585b9d355bd..ba94036b0f50bc 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -85,6 +85,7 @@ module.exports = { 'comma-style': 'error', 'computed-property-spacing': 'error', 'constructor-super': 'error', + 'default-case-last': 'error', 'dot-location': ['error', 'property'], 'dot-notation': 'error', 'eol-last': 'error', @@ -273,6 +274,7 @@ module.exports = { functions: false, variables: false, }], + 'no-useless-backreference': 'error', 'no-useless-call': 'error', 'no-useless-catch': 'error', 'no-useless-concat': 'error', diff --git a/tools/node_modules/eslint/README.md b/tools/node_modules/eslint/README.md index 0cde09fc602b17..b75051e6ecd53b 100644 --- a/tools/node_modules/eslint/README.md +++ b/tools/node_modules/eslint/README.md @@ -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) +
+[![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 @@ -39,7 +42,7 @@ ESLint is a tool for identifying and reporting on patterns found in ECMAScript/J ## Installation and Usage -Prerequisites: [Node.js](https://nodejs.org/) (`^8.10.0`, `^10.13.0`, or `>=11.10.1`) built with SSL support. (If you are using an official Node.js distribution, SSL is always built in.) +Prerequisites: [Node.js](https://nodejs.org/) (`^10.12.0`, or `>=12.0.0`) built with SSL support. (If you are using an official Node.js distribution, SSL is always built in.) You can install ESLint using npm: @@ -185,16 +188,6 @@ The people who manage releases, review feature requests, and meet regularly to e Nicholas C. Zakas - -
-Kevin Partington -
- - -
-Ilya Volodin -
-
Brandon Mills @@ -209,11 +202,6 @@ Toru Nagashima
Kai Cataldo
- - -
-Teddy Katz -
@@ -236,16 +224,16 @@ The people who review and implement new features. The people who review and fix bugs and help triage issues.
- -
-Gyandeep Singh -
-

Pig Fang
+ +
+YeonJuan +
+

Milos Djermanovic @@ -262,17 +250,11 @@ The following companies, organizations, and individuals support ESLint's ongoing

Gold Sponsors

-

Shopify Salesforce Badoo Airbnb Facebook Open Source

Silver Sponsors

+

Shopify Salesforce MagicLab Airbnb Facebook Open Source

Silver Sponsors

AMP Project

Bronze Sponsors

-

UI UX Design Agencies Top Web Design Agencies Bugsnag Stability Monitoring Crosswordsolver Codacy Mixpanel VPS Server Free Icons by Icons8 EduBirdie clay Discord ThemeIsle TekHattan Marfeel Fire Stick Tricks JSHeroes

+

Nettikasinot.org BonusFinder Deutschland Top Web Design Agencies Bugsnag Stability Monitoring Crosswordsolver Mixpanel VPS Server Free Icons by Icons8 UI UX Design Agencies clay Discord ThemeIsle TekHattan Marfeel Fire Stick Tricks JSHeroes

## 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 diff --git a/tools/node_modules/eslint/conf/category-list.json b/tools/node_modules/eslint/conf/category-list.json index 5427667b09e332..6609734950a443 100644 --- a/tools/node_modules/eslint/conf/category-list.json +++ b/tools/node_modules/eslint/conf/category-list.json @@ -10,12 +10,12 @@ ], "deprecated": { "name": "Deprecated", - "description": "These rules have been deprecated in accordance with the [deprecation policy](/docs/user-guide/rule-deprecation), and replaced by newer rules:", + "description": "These rules have been deprecated in accordance with the deprecation policy, and replaced by newer rules:", "rules": [] }, "removed": { "name": "Removed", - "description": "These rules from older versions of ESLint (before the [deprecation policy](/docs/user-guide/rule-deprecation) existed) have been replaced by newer rules:", + "description": "These rules from older versions of ESLint (before the deprecation policy existed) have been replaced by newer rules:", "rules": [ { "removed": "generator-star", "replacedBy": ["generator-star-spacing"] }, { "removed": "global-strict", "replacedBy": ["strict"] }, diff --git a/tools/node_modules/eslint/conf/default-cli-options.js b/tools/node_modules/eslint/conf/default-cli-options.js index 0f7b377fb362ec..e09a829d17cee2 100644 --- a/tools/node_modules/eslint/conf/default-cli-options.js +++ b/tools/node_modules/eslint/conf/default-cli-options.js @@ -12,7 +12,7 @@ module.exports = { useEslintrc: true, envs: [], globals: [], - extensions: [".js"], + extensions: null, ignore: true, ignorePath: void 0, cache: false, diff --git a/tools/node_modules/eslint/conf/environments.js b/tools/node_modules/eslint/conf/environments.js index 10e6fdaa70fca5..ee5ee1b4e5b2ab 100644 --- a/tools/node_modules/eslint/conf/environments.js +++ b/tools/node_modules/eslint/conf/environments.js @@ -15,7 +15,7 @@ const globals = require("globals"); //------------------------------------------------------------------------------ /** - * Get the object that has differentce. + * Get the object that has difference. * @param {Record} current The newer object. * @param {Record} prev The older object. * @returns {Record} The difference object. diff --git a/tools/node_modules/eslint/conf/eslint-recommended.js b/tools/node_modules/eslint/conf/eslint-recommended.js index e915ec449040e9..2137685fb7c63e 100644 --- a/tools/node_modules/eslint/conf/eslint-recommended.js +++ b/tools/node_modules/eslint/conf/eslint-recommended.js @@ -26,6 +26,7 @@ module.exports = { "no-delete-var": "error", "no-dupe-args": "error", "no-dupe-class-members": "error", + "no-dupe-else-if": "error", "no-dupe-keys": "error", "no-duplicate-case": "error", "no-empty": "error", @@ -37,6 +38,7 @@ module.exports = { "no-fallthrough": "error", "no-func-assign": "error", "no-global-assign": "error", + "no-import-assign": "error", "no-inner-declarations": "error", "no-invalid-regexp": "error", "no-irregular-whitespace": "error", @@ -49,6 +51,7 @@ module.exports = { "no-redeclare": "error", "no-regex-spaces": "error", "no-self-assign": "error", + "no-setter-return": "error", "no-shadow-restricted-names": "error", "no-sparse-arrays": "error", "no-this-before-super": "error", diff --git a/tools/node_modules/eslint/lib/cli-engine/cascading-config-array-factory.js b/tools/node_modules/eslint/lib/cli-engine/cascading-config-array-factory.js index 52703a873bb67e..f91dea4c448276 100644 --- a/tools/node_modules/eslint/lib/cli-engine/cascading-config-array-factory.js +++ b/tools/node_modules/eslint/lib/cli-engine/cascading-config-array-factory.js @@ -26,6 +26,7 @@ const os = require("os"); const path = require("path"); const { validateConfigArray } = require("../shared/config-validator"); +const { emitDeprecationWarning } = require("../shared/deprecation-warnings"); const { ConfigArrayFactory } = require("./config-array-factory"); const { ConfigArray, ConfigDependency, IgnorePattern } = require("./config-array"); const loadRules = require("./load-rules"); @@ -105,6 +106,7 @@ function createBaseConfigArray({ */ if (rulePaths && rulePaths.length > 0) { baseConfigArray.push({ + type: "config", name: "--rulesdir", filePath: "", plugins: { @@ -290,10 +292,11 @@ class CascadingConfigArrayFactory { /** * Load and normalize config files from the ancestor directories. * @param {string} directoryPath The path to a leaf directory. + * @param {boolean} configsExistInSubdirs `true` if configurations exist in subdirectories. * @returns {ConfigArray} The loaded config. * @private */ - _loadConfigInAncestors(directoryPath) { + _loadConfigInAncestors(directoryPath, configsExistInSubdirs = false) { const { baseConfigArray, configArrayFactory, @@ -320,6 +323,16 @@ class CascadingConfigArrayFactory { // Consider this is root. if (directoryPath === homePath && cwd !== homePath) { debug("Stop traversing because of considered root."); + if (configsExistInSubdirs) { + const filePath = ConfigArrayFactory.getPathToConfigFileInDirectory(directoryPath); + + if (filePath) { + emitDeprecationWarning( + filePath, + "ESLINT_PERSONAL_CONFIG_SUPPRESS" + ); + } + } return this._cacheConfig(directoryPath, baseConfigArray); } @@ -344,7 +357,10 @@ class CascadingConfigArrayFactory { // Load from the ancestors and merge it. const parentPath = path.dirname(directoryPath); const parentConfigArray = parentPath && parentPath !== directoryPath - ? this._loadConfigInAncestors(parentPath) + ? this._loadConfigInAncestors( + parentPath, + configsExistInSubdirs || configArray.length > 0 + ) : baseConfigArray; if (configArray.length > 0) { @@ -400,12 +416,29 @@ class CascadingConfigArrayFactory { configArray.every(c => !c.filePath) && cliConfigArray.every(c => !c.filePath) // `--config` option can be a file. ) { - debug("Loading the config file of the home directory."); + const homePath = os.homedir(); + + debug("Loading the config file of the home directory:", homePath); - finalConfigArray = configArrayFactory.loadInDirectory( - os.homedir(), - { name: "PersonalConfig", parent: finalConfigArray } + const personalConfigArray = configArrayFactory.loadInDirectory( + homePath, + { name: "PersonalConfig" } ); + + if ( + personalConfigArray.length > 0 && + !directoryPath.startsWith(homePath) + ) { + const lastElement = + personalConfigArray[personalConfigArray.length - 1]; + + emitDeprecationWarning( + lastElement.filePath, + "ESLINT_PERSONAL_CONFIG_LOAD" + ); + } + + finalConfigArray = finalConfigArray.concat(personalConfigArray); } // Apply CLI options. diff --git a/tools/node_modules/eslint/lib/cli-engine/cli-engine.js b/tools/node_modules/eslint/lib/cli-engine/cli-engine.js index 22336a91de2909..9d2ef8cbcdef04 100644 --- a/tools/node_modules/eslint/lib/cli-engine/cli-engine.js +++ b/tools/node_modules/eslint/lib/cli-engine/cli-engine.js @@ -57,7 +57,7 @@ const validFixTypes = new Set(["problem", "suggestion", "layout"]); * @property {string} configFile The configuration file to use. * @property {string} cwd The value to use for the current working directory. * @property {string[]} envs An array of environments to load. - * @property {string[]} extensions An array of file extensions to check. + * @property {string[]|null} extensions An array of file extensions to check. * @property {boolean|Function} fix Execute in autofix mode. If a function, should return a boolean. * @property {string[]} fixTypes Array of rule types to apply fixes for. * @property {string[]} globals An array of global variables to declare. @@ -201,7 +201,7 @@ function calculateStatsPerRun(results) { * @param {boolean} config.fix If `true` then it does fix. * @param {boolean} config.allowInlineConfig If `true` then it uses directive comments. * @param {boolean} config.reportUnusedDisableDirectives If `true` then it reports unused `eslint-disable` comments. - * @param {RegExp} config.extensionRegExp The `RegExp` object that tests if a file path has the allowed file extensions. + * @param {FileEnumerator} config.fileEnumerator The file enumerator to check if a path is a target or not. * @param {Linter} config.linter The linter instance to verify. * @returns {LintResult} The result of linting. * @private @@ -214,7 +214,7 @@ function verifyText({ fix, allowInlineConfig, reportUnusedDisableDirectives, - extensionRegExp, + fileEnumerator, linter }) { const filePath = providedFilePath || ""; @@ -238,13 +238,11 @@ function verifyText({ /** * Check if the linter should adopt a given code block or not. - * Currently, the linter adopts code blocks if the name matches `--ext` option. - * In the future, `overrides` in the configuration would affect the adoption (https://github.com/eslint/rfcs/pull/20). * @param {string} blockFilename The virtual filename of a code block. * @returns {boolean} `true` if the linter should adopt the code block. */ filterCodeBlock(blockFilename) { - return extensionRegExp.test(blockFilename); + return fileEnumerator.isTargetPath(blockFilename); } } ); @@ -280,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 '!'\") 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."; } @@ -704,7 +699,7 @@ class CLIEngine { return patterns.filter(Boolean); } - const extensions = options.extensions.map(ext => ext.replace(/^\./u, "")); + const extensions = (options.extensions || [".js"]).map(ext => ext.replace(/^\./u, "")); const dirSuffix = `/**/*.{${extensions.join(",")}}`; return patterns.filter(Boolean).map(pathname => { @@ -803,7 +798,7 @@ class CLIEngine { fix, allowInlineConfig, reportUnusedDisableDirectives, - extensionRegExp: fileEnumerator.extensionRegExp, + fileEnumerator, linter }); @@ -891,7 +886,7 @@ class CLIEngine { fix, allowInlineConfig, reportUnusedDisableDirectives, - extensionRegExp: fileEnumerator.extensionRegExp, + fileEnumerator, linter })); } diff --git a/tools/node_modules/eslint/lib/cli-engine/config-array-factory.js b/tools/node_modules/eslint/lib/cli-engine/config-array-factory.js index 76c4ccd70212cd..997a7e15318dfd 100644 --- a/tools/node_modules/eslint/lib/cli-engine/config-array-factory.js +++ b/tools/node_modules/eslint/lib/cli-engine/config-array-factory.js @@ -436,6 +436,29 @@ class ConfigArrayFactory { ); } + /** + * Check if a config file on a given directory exists or not. + * @param {string} directoryPath The path to a directory. + * @returns {string | null} The path to the found config file. If not found then null. + */ + static getPathToConfigFileInDirectory(directoryPath) { + for (const filename of configFilenames) { + const filePath = path.join(directoryPath, filename); + + if (fs.existsSync(filePath)) { + if (filename === "package.json") { + try { + loadPackageJSONConfigFile(filePath); + return filePath; + } catch (error) { /* ignore */ } + } else { + return filePath; + } + } + } + return null; + } + /** * Load `.eslintignore` file. * @param {string} filePath The path to a `.eslintignore` file to load. @@ -542,7 +565,7 @@ class ConfigArrayFactory { */ *_normalizeESLintIgnoreData(ignorePatterns, filePath, name) { const elements = this._normalizeObjectConfigData( - { ignorePatterns }, + { type: "ignore", ignorePatterns }, filePath, name ); @@ -644,6 +667,7 @@ class ConfigArrayFactory { root, rules, settings, + type = "config", overrides: overrideList = [] }, filePath, @@ -675,6 +699,7 @@ class ConfigArrayFactory { yield { // Debug information. + type, name, filePath, @@ -1024,6 +1049,7 @@ class ConfigArrayFactory { if (processorId.startsWith(".")) { yield* this._normalizeObjectConfigData( { + type: "implicit-processor", files: [`*${processorId}`], processor: `${pluginId}/${processorId}` }, diff --git a/tools/node_modules/eslint/lib/cli-engine/config-array/config-array.js b/tools/node_modules/eslint/lib/cli-engine/config-array/config-array.js index 4fae8deaca1b69..b3f7c1e7350033 100644 --- a/tools/node_modules/eslint/lib/cli-engine/config-array/config-array.js +++ b/tools/node_modules/eslint/lib/cli-engine/config-array/config-array.js @@ -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` @@ -454,6 +454,25 @@ class ConfigArray extends Array { return cache.get(cacheKey); } + + /** + * Check if a given path is an additional lint target. + * @param {string} filePath The absolute path to the target file. + * @returns {boolean} `true` if the file is an additional lint target. + */ + isAdditionalTargetPath(filePath) { + for (const { criteria, type } of this) { + if ( + type === "config" && + criteria && + !criteria.endsWithWildcard && + criteria.test(filePath) + ) { + return true; + } + } + return false; + } } const exportObject = { diff --git a/tools/node_modules/eslint/lib/cli-engine/config-array/ignore-pattern.js b/tools/node_modules/eslint/lib/cli-engine/config-array/ignore-pattern.js index 6140194433e861..92690b9f8ae342 100644 --- a/tools/node_modules/eslint/lib/cli-engine/config-array/ignore-pattern.js +++ b/tools/node_modules/eslint/lib/cli-engine/config-array/ignore-pattern.js @@ -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 diff --git a/tools/node_modules/eslint/lib/cli-engine/config-array/override-tester.js b/tools/node_modules/eslint/lib/cli-engine/config-array/override-tester.js index 67c8a6ed8a0cbb..e7ba1202f1cb08 100644 --- a/tools/node_modules/eslint/lib/cli-engine/config-array/override-tester.js +++ b/tools/node_modules/eslint/lib/cli-engine/config-array/override-tester.js @@ -96,14 +96,22 @@ class OverrideTester { static create(files, excludedFiles, basePath) { const includePatterns = normalizePatterns(files); const excludePatterns = normalizePatterns(excludedFiles); - const allPatterns = includePatterns.concat(excludePatterns); + let endsWithWildcard = false; - if (allPatterns.length === 0) { + if (includePatterns.length === 0) { return null; } // Rejects absolute paths or relative paths to parents. - for (const pattern of allPatterns) { + for (const pattern of includePatterns) { + if (path.isAbsolute(pattern) || pattern.includes("..")) { + throw new Error(`Invalid override pattern (expected relative path not containing '..'): ${pattern}`); + } + if (pattern.endsWith("*")) { + endsWithWildcard = true; + } + } + for (const pattern of excludePatterns) { if (path.isAbsolute(pattern) || pattern.includes("..")) { throw new Error(`Invalid override pattern (expected relative path not containing '..'): ${pattern}`); } @@ -112,7 +120,11 @@ class OverrideTester { const includes = toMatcher(includePatterns); const excludes = toMatcher(excludePatterns); - return new OverrideTester([{ includes, excludes }], basePath); + return new OverrideTester( + [{ includes, excludes }], + basePath, + endsWithWildcard + ); } /** @@ -125,28 +137,44 @@ class OverrideTester { */ static and(a, b) { if (!b) { - return a && new OverrideTester(a.patterns, a.basePath); + return a && new OverrideTester( + a.patterns, + a.basePath, + a.endsWithWildcard + ); } if (!a) { - return new OverrideTester(b.patterns, b.basePath); + return new OverrideTester( + b.patterns, + b.basePath, + b.endsWithWildcard + ); } assert.strictEqual(a.basePath, b.basePath); - return new OverrideTester(a.patterns.concat(b.patterns), a.basePath); + return new OverrideTester( + a.patterns.concat(b.patterns), + a.basePath, + a.endsWithWildcard || b.endsWithWildcard + ); } /** * Initialize this instance. * @param {Pattern[]} patterns The matchers. * @param {string} basePath The base path. + * @param {boolean} endsWithWildcard If `true` then a pattern ends with `*`. */ - constructor(patterns, basePath) { + constructor(patterns, basePath, endsWithWildcard = false) { /** @type {Pattern[]} */ this.patterns = patterns; /** @type {string} */ this.basePath = basePath; + + /** @type {boolean} */ + this.endsWithWildcard = endsWithWildcard; } /** diff --git a/tools/node_modules/eslint/lib/cli-engine/file-enumerator.js b/tools/node_modules/eslint/lib/cli-engine/file-enumerator.js index c67e01aef9b1c8..7c433d32f44b1c 100644 --- a/tools/node_modules/eslint/lib/cli-engine/file-enumerator.js +++ b/tools/node_modules/eslint/lib/cli-engine/file-enumerator.js @@ -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 @@ -88,7 +88,7 @@ const IGNORED = 2; * @typedef {Object} FileEnumeratorInternalSlots * @property {CascadingConfigArrayFactory} configArrayFactory The factory for config arrays. * @property {string} cwd The base directory to start lookup. - * @property {RegExp} extensionRegExp The RegExp to test if a string ends with specific file extensions. + * @property {RegExp|null} extensionRegExp The RegExp to test if a string ends with specific file extensions. * @property {boolean} globInputPaths Set to false to skip glob resolution of input file paths to lint (default: true). If false, each input file paths is assumed to be a non-glob path to an existing file. * @property {boolean} ignoreFlag The flag to check ignored files. * @property {(filePath:string, dot:boolean) => boolean} defaultIgnores The default predicate function to ignore files. @@ -127,12 +127,12 @@ function statSafeSync(filePath) { /** * Get filenames in a given path to a directory. * @param {string} directoryPath The path to target directory. - * @returns {string[]} The filenames. + * @returns {import("fs").Dirent[]} The filenames. * @private */ function readdirSafeSync(directoryPath) { try { - return fs.readdirSync(directoryPath); + return fs.readdirSync(directoryPath, { withFileTypes: true }); } catch (error) { /* istanbul ignore next */ if (error.code !== "ENOENT") { @@ -142,6 +142,27 @@ function readdirSafeSync(directoryPath) { } } +/** + * Create a `RegExp` object to detect extensions. + * @param {string[] | null} extensions The extensions to create. + * @returns {RegExp | null} The created `RegExp` object or null. + */ +function createExtensionRegExp(extensions) { + if (extensions) { + const normalizedExts = extensions.map(ext => escapeRegExp( + ext.startsWith(".") + ? ext.slice(1) + : ext + )); + + return new RegExp( + `.\\.(?:${normalizedExts.join("|")})$`, + "u" + ); + } + return null; +} + /** * The error type when no files match a glob. */ @@ -188,7 +209,7 @@ class FileEnumerator { constructor({ cwd = process.cwd(), configArrayFactory = new CascadingConfigArrayFactory({ cwd }), - extensions = [".js"], + extensions = null, globInputPaths = true, errorOnUnmatchedPattern = true, ignore = true @@ -197,17 +218,7 @@ class FileEnumerator { configArrayFactory, cwd, defaultIgnores: IgnorePattern.createDefaultIgnore(cwd), - extensionRegExp: new RegExp( - `.\\.(?:${extensions - .map(ext => escapeRegExp( - ext.startsWith(".") - ? ext.slice(1) - : ext - )) - .join("|") - })$`, - "u" - ), + extensionRegExp: createExtensionRegExp(extensions), globInputPaths, errorOnUnmatchedPattern, ignoreFlag: ignore @@ -215,11 +226,36 @@ class FileEnumerator { } /** - * The `RegExp` object that tests if a file path has the allowed file extensions. - * @type {RegExp} + * Check if a given file is target or not. + * @param {string} filePath The path to a candidate file. + * @param {ConfigArray} [providedConfig] Optional. The configuration for the file. + * @returns {boolean} `true` if the file is a target. */ - get extensionRegExp() { - return internalSlotsMap.get(this).extensionRegExp; + isTargetPath(filePath, providedConfig) { + const { + configArrayFactory, + extensionRegExp + } = internalSlotsMap.get(this); + + // If `--ext` option is present, use it. + if (extensionRegExp) { + return extensionRegExp.test(filePath); + } + + // `.js` file is target by default. + if (filePath.endsWith(".js")) { + return true; + } + + // use `overrides[].files` to check additional targets. + const config = + providedConfig || + configArrayFactory.getConfigArrayForFile( + filePath, + { ignoreNotFoundError: true } + ); + + return config.isAdditionalTargetPath(filePath); } /** @@ -247,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) { @@ -380,18 +416,17 @@ class FileEnumerator { */ *_iterateFilesRecursive(directoryPath, options) { debug(`Enter the directory: ${directoryPath}`); - const { configArrayFactory, extensionRegExp } = internalSlotsMap.get(this); + const { configArrayFactory } = internalSlotsMap.get(this); /** @type {ConfigArray|null} */ let config = null; // Enumerate the files of this directory. - for (const filename of readdirSafeSync(directoryPath)) { - const filePath = path.join(directoryPath, filename); - const stat = statSafeSync(filePath); // TODO: Use `withFileTypes` in the future. + for (const entry of readdirSafeSync(directoryPath)) { + const filePath = path.join(directoryPath, entry.name); // Check if the file is matched. - if (stat && stat.isFile()) { + if (entry.isFile()) { if (!config) { config = configArrayFactory.getConfigArrayForFile( filePath, @@ -404,29 +439,30 @@ class FileEnumerator { { ignoreNotFoundError: true } ); } - const ignored = this._isIgnoredFile(filePath, { ...options, config }); - const flag = ignored ? IGNORED_SILENTLY : NONE; const matched = options.selector // Started with a glob pattern; choose by the pattern. ? options.selector.match(filePath) // Started with a directory path; choose by file extensions. - : extensionRegExp.test(filePath); + : this.isTargetPath(filePath, config); if (matched) { - debug(`Yield: ${filename}${ignored ? " but ignored" : ""}`); + const ignored = this._isIgnoredFile(filePath, { ...options, config }); + const flag = ignored ? IGNORED_SILENTLY : NONE; + + debug(`Yield: ${entry.name}${ignored ? " but ignored" : ""}`); yield { config: configArrayFactory.getConfigArrayForFile(filePath), filePath, flag }; } else { - debug(`Didn't match: ${filename}`); + debug(`Didn't match: ${entry.name}`); } // Dive into the sub directory. - } else if (options.recursive && stat && stat.isDirectory()) { + } else if (options.recursive && entry.isDirectory()) { if (!config) { config = configArrayFactory.getConfigArrayForFile( filePath, diff --git a/tools/node_modules/eslint/lib/cli-engine/formatters/junit.js b/tools/node_modules/eslint/lib/cli-engine/formatters/junit.js index c32425883f7cac..a994b4b1980eea 100644 --- a/tools/node_modules/eslint/lib/cli-engine/formatters/junit.js +++ b/tools/node_modules/eslint/lib/cli-engine/formatters/junit.js @@ -32,7 +32,7 @@ function getMessageType(message) { * @private */ function pathWithoutExt(filePath) { - return path.posix.join(path.posix.dirname(filePath), path.basename(filePath, path.extname(filePath))); + return path.join(path.dirname(filePath), path.basename(filePath, path.extname(filePath))); } //------------------------------------------------------------------------------ diff --git a/tools/node_modules/eslint/lib/cli.js b/tools/node_modules/eslint/lib/cli.js index 944b4b79353b3d..815ce68c22fe2e 100644 --- a/tools/node_modules/eslint/lib/cli.js +++ b/tools/node_modules/eslint/lib/cli.js @@ -17,7 +17,6 @@ const fs = require("fs"), path = require("path"), - mkdirp = require("mkdirp"), { CLIEngine } = require("./cli-engine"), options = require("./options"), log = require("./shared/logging"), @@ -115,7 +114,7 @@ function printResults(engine, results, format, outputFile) { } try { - mkdirp.sync(path.dirname(filePath)); + fs.mkdirSync(path.dirname(filePath), { recursive: true }); fs.writeFileSync(filePath, output); } catch (ex) { log.error("There was a problem writing the output file:\n%s", ex); diff --git a/tools/node_modules/eslint/lib/init/npm-utils.js b/tools/node_modules/eslint/lib/init/npm-utils.js index 28c198fc8ada67..555ea2b2b28cb2 100644 --- a/tools/node_modules/eslint/lib/init/npm-utils.js +++ b/tools/node_modules/eslint/lib/init/npm-utils.js @@ -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. */ diff --git a/tools/node_modules/eslint/lib/linter/code-path-analysis/code-path-analyzer.js b/tools/node_modules/eslint/lib/linter/code-path-analysis/code-path-analyzer.js index 6822ae2be0a6cd..8a623e33ea0681 100644 --- a/tools/node_modules/eslint/lib/linter/code-path-analysis/code-path-analyzer.js +++ b/tools/node_modules/eslint/lib/linter/code-path-analysis/code-path-analyzer.js @@ -518,6 +518,7 @@ function processCodePathToExit(analyzer, node) { case "ImportExpression": case "MemberExpression": case "NewExpression": + case "YieldExpression": state.makeFirstThrowablePathInTryBlock(); break; diff --git a/tools/node_modules/eslint/lib/linter/code-path-analysis/debug-helpers.js b/tools/node_modules/eslint/lib/linter/code-path-analysis/debug-helpers.js index 35a4cb2dacb1ca..bde4e0a38ad24b 100644 --- a/tools/node_modules/eslint/lib/linter/code-path-analysis/debug-helpers.js +++ b/tools/node_modules/eslint/lib/linter/code-path-analysis/debug-helpers.js @@ -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. diff --git a/tools/node_modules/eslint/lib/linter/code-path-analysis/fork-context.js b/tools/node_modules/eslint/lib/linter/code-path-analysis/fork-context.js index eb1d2de5a7db5b..2e872b5c0dbf5a 100644 --- a/tools/node_modules/eslint/lib/linter/code-path-analysis/fork-context.js +++ b/tools/node_modules/eslint/lib/linter/code-path-analysis/fork-context.js @@ -211,7 +211,7 @@ class ForkContext { } /** - * Clears all secments in this context. + * Clears all segments in this context. * @returns {void} */ clear() { diff --git a/tools/node_modules/eslint/lib/linter/linter.js b/tools/node_modules/eslint/lib/linter/linter.js index 6d88cb5aa1245f..1d021d1e82e7fb 100644 --- a/tools/node_modules/eslint/lib/linter/linter.js +++ b/tools/node_modules/eslint/lib/linter/linter.js @@ -267,6 +267,15 @@ function createDisableDirectives(options) { return result; } +/** + * Remove the ignored part from a given directive comment and trim it. + * @param {string} value The comment text to strip. + * @returns {string} The stripped text. + */ +function stripDirectiveComment(value) { + return value.split(/\s-{2,}\s/u)[0].trim(); +} + /** * Parses comments in file to extract file-specific config of rules, globals * and environments and merges them with global config; also code blocks @@ -286,7 +295,7 @@ function getDirectiveComments(filename, ast, ruleMapper, warnInlineConfig) { const disableDirectives = []; ast.comments.filter(token => token.type !== "Shebang").forEach(comment => { - const trimmedCommentText = comment.value.trim(); + const trimmedCommentText = stripDirectiveComment(comment.value); const match = /^(eslint(?:-env|-enable|-disable(?:(?:-next)?-line)?)?|exported|globals?)(?:\s|$)/u.exec(trimmedCommentText); if (!match) { @@ -444,8 +453,11 @@ function findEslintEnv(text) { eslintEnvPattern.lastIndex = 0; - while ((match = eslintEnvPattern.exec(text))) { - retv = Object.assign(retv || {}, commentParser.parseListConfig(match[1])); + while ((match = eslintEnvPattern.exec(text)) !== null) { + retv = Object.assign( + retv || {}, + commentParser.parseListConfig(stripDirectiveComment(match[1])) + ); } return retv; @@ -1260,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) { diff --git a/tools/node_modules/eslint/lib/rule-tester/rule-tester.js b/tools/node_modules/eslint/lib/rule-tester/rule-tester.js index 44e01dadf09b5d..5180f87a316f85 100644 --- a/tools/node_modules/eslint/lib/rule-tester/rule-tester.js +++ b/tools/node_modules/eslint/lib/rule-tester/rule-tester.js @@ -50,6 +50,52 @@ const const ajv = require("../shared/ajv")({ strictDefaults: true }); + +//------------------------------------------------------------------------------ +// Typedefs +//------------------------------------------------------------------------------ + +/** + * A test case that is expected to pass lint. + * @typedef {Object} ValidTestCase + * @property {string} code Code for the test case. + * @property {any[]} [options] Options for the test case. + * @property {{ [name: string]: any }} [settings] Settings for the test case. + * @property {string} [filename] The fake filename for the test case. Useful for rules that make assertion about filenames. + * @property {string} [parser] The absolute path for the parser. + * @property {{ [name: string]: any }} [parserOptions] Options for the parser. + * @property {{ [name: string]: "readonly" | "writable" | "off" }} [globals] The additional global variables. + * @property {{ [name: string]: boolean }} [env] Environments for the test case. + */ + +/** + * A test case that is expected to fail lint. + * @typedef {Object} InvalidTestCase + * @property {string} code Code for the test case. + * @property {number | Array} errors Expected errors. + * @property {string | null} [output] The expected code after autofixes are applied. If set to `null`, the test runner will assert that no autofix is suggested. + * @property {any[]} [options] Options for the test case. + * @property {{ [name: string]: any }} [settings] Settings for the test case. + * @property {string} [filename] The fake filename for the test case. Useful for rules that make assertion about filenames. + * @property {string} [parser] The absolute path for the parser. + * @property {{ [name: string]: any }} [parserOptions] Options for the parser. + * @property {{ [name: string]: "readonly" | "writable" | "off" }} [globals] The additional global variables. + * @property {{ [name: string]: boolean }} [env] Environments for the test case. + */ + +/** + * A description of a reported error used in a rule tester test. + * @typedef {Object} TestCaseError + * @property {string | RegExp} [message] Message. + * @property {string} [messageId] Message ID. + * @property {string} [type] The type of the reported AST node. + * @property {{ [name: string]: string }} [data] The data used to fill the message template. + * @property {number} [line] The 1-based line number of the reported start location. + * @property {number} [column] The 1-based column number of the reported start location. + * @property {number} [endLine] The 1-based line number of the reported end location. + * @property {number} [endColumn] The 1-based column number of the reported end location. + */ + //------------------------------------------------------------------------------ // Private Members //------------------------------------------------------------------------------ @@ -73,6 +119,32 @@ const RuleTesterParameters = [ "output" ]; +/* + * All allowed property names in error objects. + */ +const errorObjectParameters = new Set([ + "message", + "messageId", + "data", + "type", + "line", + "column", + "endLine", + "endColumn", + "suggestions" +]); +const friendlyErrorObjectParameterList = `[${[...errorObjectParameters].map(key => `'${key}'`).join(", ")}]`; + +/* + * All allowed property names in suggestion objects. + */ +const suggestionObjectParameters = new Set([ + "desc", + "messageId", + "output" +]); +const friendlySuggestionObjectParameterList = `[${[...suggestionObjectParameters].map(key => `'${key}'`).join(", ")}]`; + const hasOwnProperty = Function.call.bind(Object.hasOwnProperty); /** @@ -128,7 +200,7 @@ function freezeDeeply(x) { */ function sanitize(text) { return text.replace( - /[\u0000-\u0009|\u000b-\u001a]/gu, // eslint-disable-line no-control-regex + /[\u0000-\u0009\u000b-\u001a]/gu, // eslint-disable-line no-control-regex c => `\\u${c.codePointAt(0).toString(16).padStart(4, "0")}` ); } @@ -273,7 +345,10 @@ class RuleTester { * Adds a new rule test to execute. * @param {string} ruleName The name of the rule to run. * @param {Function} rule The rule to test. - * @param {Object} test The collection of tests to run. + * @param {{ + * valid: (ValidTestCase | string)[], + * invalid: InvalidTestCase[] + * }} test The collection of tests to run. * @returns {void} */ run(ruleName, rule, test) { @@ -524,13 +599,21 @@ class RuleTester { // Just an error message. assertMessageMatches(message.message, error); - } else if (typeof error === "object") { + } else if (typeof error === "object" && error !== null) { /* * Error object. * This may have a message, messageId, data, node type, line, and/or * column. */ + + Object.keys(error).forEach(propertyName => { + assert.ok( + errorObjectParameters.has(propertyName), + `Invalid error property name '${propertyName}'. Expected one of ${friendlyErrorObjectParameterList}.` + ); + }); + if (hasOwnProperty(error, "message")) { assert.ok(!hasOwnProperty(error, "messageId"), "Error should not specify both 'message' and a 'messageId'."); assert.ok(!hasOwnProperty(error, "data"), "Error should not specify both 'data' and 'message'."); @@ -605,6 +688,17 @@ class RuleTester { assert.strictEqual(message.suggestions.length, error.suggestions.length, `Error should have ${error.suggestions.length} suggestions. Instead found ${message.suggestions.length} suggestions`); error.suggestions.forEach((expectedSuggestion, index) => { + assert.ok( + typeof expectedSuggestion === "object" && expectedSuggestion !== null, + "Test suggestion in 'suggestions' array must be an object." + ); + Object.keys(expectedSuggestion).forEach(propertyName => { + assert.ok( + suggestionObjectParameters.has(propertyName), + `Invalid suggestion property name '${propertyName}'. Expected one of ${friendlySuggestionObjectParameterList}.` + ); + }); + const actualSuggestion = message.suggestions[index]; /** diff --git a/tools/node_modules/eslint/lib/rules/accessor-pairs.js b/tools/node_modules/eslint/lib/rules/accessor-pairs.js index 3a32db6eac7214..02548258ca2e28 100644 --- a/tools/node_modules/eslint/lib/rules/accessor-pairs.js +++ b/tools/node_modules/eslint/lib/rules/accessor-pairs.js @@ -171,7 +171,7 @@ module.exports = { }, enforceForClassMembers: { type: "boolean", - default: false + default: true } }, additionalProperties: false @@ -190,7 +190,7 @@ module.exports = { const config = context.options[0] || {}; const checkGetWithoutSet = config.getWithoutSet === true; const checkSetWithoutGet = config.setWithoutGet !== false; - const enforceForClassMembers = config.enforceForClassMembers === true; + const enforceForClassMembers = config.enforceForClassMembers !== false; const sourceCode = context.getSourceCode(); /** diff --git a/tools/node_modules/eslint/lib/rules/array-callback-return.js b/tools/node_modules/eslint/lib/rules/array-callback-return.js index d632a3f30c28a3..eb38965024f05d 100644 --- a/tools/node_modules/eslint/lib/rules/array-callback-return.js +++ b/tools/node_modules/eslint/lib/rules/array-callback-return.js @@ -18,7 +18,7 @@ const astUtils = require("./utils/ast-utils"); //------------------------------------------------------------------------------ const TARGET_NODE_TYPE = /^(?:Arrow)?FunctionExpression$/u; -const TARGET_METHODS = /^(?:every|filter|find(?:Index)?|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. diff --git a/tools/node_modules/eslint/lib/rules/array-element-newline.js b/tools/node_modules/eslint/lib/rules/array-element-newline.js index 1da67667bee849..b7a967865b92a1 100644 --- a/tools/node_modules/eslint/lib/rules/array-element-newline.js +++ b/tools/node_modules/eslint/lib/rules/array-element-newline.js @@ -24,28 +24,52 @@ module.exports = { fixable: "whitespace", - schema: [ - { - oneOf: [ - { - enum: ["always", "never", "consistent"] - }, - { - type: "object", - properties: { - multiline: { - type: "boolean" + schema: { + definitions: { + basicConfig: { + oneOf: [ + { + enum: ["always", "never", "consistent"] + }, + { + type: "object", + properties: { + multiline: { + type: "boolean" + }, + minItems: { + type: ["integer", "null"], + minimum: 0 + } }, - minItems: { - type: ["integer", "null"], - minimum: 0 - } + additionalProperties: false + } + ] + } + }, + items: [ + { + oneOf: [ + { + $ref: "#/definitions/basicConfig" }, - additionalProperties: false - } - ] - } - ], + { + type: "object", + properties: { + ArrayExpression: { + $ref: "#/definitions/basicConfig" + }, + ArrayPattern: { + $ref: "#/definitions/basicConfig" + } + }, + additionalProperties: false, + minProperties: 1 + } + ] + } + ] + }, messages: { unexpectedLineBreak: "There should be no linebreak here.", @@ -93,6 +117,20 @@ module.exports = { * @returns {{ArrayExpression: {multiline: boolean, minItems: number}, ArrayPattern: {multiline: boolean, minItems: number}}} Normalized option object. */ function normalizeOptions(options) { + if (options && (options.ArrayExpression || options.ArrayPattern)) { + let expressionOptions, patternOptions; + + if (options.ArrayExpression) { + expressionOptions = normalizeOptionValue(options.ArrayExpression); + } + + if (options.ArrayPattern) { + patternOptions = normalizeOptionValue(options.ArrayPattern); + } + + return { ArrayExpression: expressionOptions, ArrayPattern: patternOptions }; + } + const value = normalizeOptionValue(options); return { ArrayExpression: value, ArrayPattern: value }; @@ -177,6 +215,10 @@ module.exports = { const normalizedOptions = normalizeOptions(context.options[0]); const options = normalizedOptions[node.type]; + if (!options) { + return; + } + let elementBreak = false; /* diff --git a/tools/node_modules/eslint/lib/rules/arrow-body-style.js b/tools/node_modules/eslint/lib/rules/arrow-body-style.js index 8d3b400037a6d5..9d5c77d8573d6a 100644 --- a/tools/node_modules/eslint/lib/rules/arrow-body-style.js +++ b/tools/node_modules/eslint/lib/rules/arrow-body-style.js @@ -91,7 +91,7 @@ module.exports = { * @returns {Token} The found closing parenthesis token. */ function findClosingParen(token) { - let node = sourceCode.getNodeByRangeIndex(token.range[1]); + let node = sourceCode.getNodeByRangeIndex(token.range[0]); while (!astUtils.isParenthesised(sourceCode, node)) { node = node.parent; @@ -206,24 +206,35 @@ module.exports = { fix(fixer) { const fixes = []; const arrowToken = sourceCode.getTokenBefore(arrowBody, astUtils.isArrowToken); - const firstBodyToken = sourceCode.getTokenAfter(arrowToken); - const lastBodyToken = sourceCode.getLastToken(node); + const [firstTokenAfterArrow, secondTokenAfterArrow] = sourceCode.getTokensAfter(arrowToken, { count: 2 }); + const lastToken = sourceCode.getLastToken(node); const isParenthesisedObjectLiteral = - astUtils.isOpeningParenToken(firstBodyToken) && - astUtils.isOpeningBraceToken(sourceCode.getTokenAfter(firstBodyToken)); - - // Wrap the value by a block and a return statement. - fixes.push( - fixer.insertTextBefore(firstBodyToken, "{return "), - fixer.insertTextAfter(lastBodyToken, "}") - ); + astUtils.isOpeningParenToken(firstTokenAfterArrow) && + astUtils.isOpeningBraceToken(secondTokenAfterArrow); // If the value is object literal, remove parentheses which were forced by syntax. if (isParenthesisedObjectLiteral) { - fixes.push( - fixer.remove(firstBodyToken), - fixer.remove(findClosingParen(firstBodyToken)) - ); + const openingParenToken = firstTokenAfterArrow; + const openingBraceToken = secondTokenAfterArrow; + + if (astUtils.isTokenOnSameLine(openingParenToken, openingBraceToken)) { + fixes.push(fixer.replaceText(openingParenToken, "{return ")); + } else { + + // Avoid ASI + fixes.push( + fixer.replaceText(openingParenToken, "{"), + fixer.insertTextBefore(openingBraceToken, "return ") + ); + } + + // Closing paren for the object doesn't have to be lastToken, e.g.: () => ({}).foo() + fixes.push(fixer.remove(findClosingParen(openingBraceToken))); + fixes.push(fixer.insertTextAfter(lastToken, "}")); + + } else { + fixes.push(fixer.insertTextBefore(firstTokenAfterArrow, "{return ")); + fixes.push(fixer.insertTextAfter(lastToken, "}")); } return fixes; diff --git a/tools/node_modules/eslint/lib/rules/complexity.js b/tools/node_modules/eslint/lib/rules/complexity.js index 91180e989540ce..7fc8bf9bc2ea8c 100644 --- a/tools/node_modules/eslint/lib/rules/complexity.js +++ b/tools/node_modules/eslint/lib/rules/complexity.js @@ -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 */ diff --git a/tools/node_modules/eslint/lib/rules/computed-property-spacing.js b/tools/node_modules/eslint/lib/rules/computed-property-spacing.js index a0bd7f48ced66b..53fdb8f4e41f95 100644 --- a/tools/node_modules/eslint/lib/rules/computed-property-spacing.js +++ b/tools/node_modules/eslint/lib/rules/computed-property-spacing.js @@ -32,7 +32,7 @@ module.exports = { properties: { enforceForClassMembers: { type: "boolean", - default: false + default: true } }, additionalProperties: false @@ -51,7 +51,7 @@ module.exports = { create(context) { const sourceCode = context.getSourceCode(); const propertyNameMustBeSpaced = context.options[0] === "always"; // default is "never" - const enforceForClassMembers = context.options[1] && context.options[1].enforceForClassMembers; + const enforceForClassMembers = !context.options[1] || context.options[1].enforceForClassMembers; //-------------------------------------------------------------------------- // Helpers @@ -67,7 +67,7 @@ module.exports = { function reportNoBeginningSpace(node, token, tokenAfter) { context.report({ node, - loc: token.loc.start, + loc: { start: token.loc.end, end: tokenAfter.loc.start }, messageId: "unexpectedSpaceAfter", data: { tokenValue: token.value @@ -88,7 +88,7 @@ module.exports = { function reportNoEndingSpace(node, token, tokenBefore) { context.report({ node, - loc: token.loc.start, + loc: { start: tokenBefore.loc.end, end: token.loc.start }, messageId: "unexpectedSpaceBefore", data: { tokenValue: token.value @@ -108,7 +108,7 @@ module.exports = { function reportRequiredBeginningSpace(node, token) { context.report({ node, - loc: token.loc.start, + loc: token.loc, messageId: "missingSpaceAfter", data: { tokenValue: token.value @@ -128,7 +128,7 @@ module.exports = { function reportRequiredEndingSpace(node, token) { context.report({ node, - loc: token.loc.start, + loc: token.loc, messageId: "missingSpaceBefore", data: { tokenValue: token.value diff --git a/tools/node_modules/eslint/lib/rules/consistent-this.js b/tools/node_modules/eslint/lib/rules/consistent-this.js index 16f53b5374cd24..e5bc9678daef3c 100644 --- a/tools/node_modules/eslint/lib/rules/consistent-this.js +++ b/tools/node_modules/eslint/lib/rules/consistent-this.js @@ -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() { diff --git a/tools/node_modules/eslint/lib/rules/curly.js b/tools/node_modules/eslint/lib/rules/curly.js index ee2fe4dceb82bf..29f00c0ad0b617 100644 --- a/tools/node_modules/eslint/lib/rules/curly.js +++ b/tools/node_modules/eslint/lib/rules/curly.js @@ -141,33 +141,14 @@ module.exports = { } /** - * Checks a given IfStatement node requires braces of the consequent chunk. - * This returns `true` when below: - * - * 1. The given node has the `alternate` node. - * 2. There is a `IfStatement` which doesn't have `alternate` node in the - * trailing statement chain of the `consequent` node. - * @param {ASTNode} node A IfStatement node to check. - * @returns {boolean} `true` if the node requires braces of the consequent chunk. + * Determines whether the given node has an `else` keyword token as the first token after. + * @param {ASTNode} node The node to check. + * @returns {boolean} `true` if the node is followed by an `else` keyword token. */ - function requiresBraceOfConsequent(node) { - if (node.alternate && node.consequent.type === "BlockStatement") { - if (node.consequent.body.length >= 2) { - return true; - } - - for ( - let currentNode = node.consequent.body[0]; - currentNode; - currentNode = astUtils.getTrailingStatement(currentNode) - ) { - if (currentNode.type === "IfStatement" && !currentNode.alternate) { - return true; - } - } - } + function isFollowedByElseKeyword(node) { + const nextToken = sourceCode.getTokenAfter(node); - return false; + return Boolean(nextToken) && isElseKeywordToken(nextToken); } /** @@ -224,6 +205,110 @@ module.exports = { return false; } + /** + * Determines whether the code represented by the given node contains an `if` statement + * that would become associated with an `else` keyword directly appended to that code. + * + * Examples where it returns `true`: + * + * if (a) + * foo(); + * + * if (a) { + * foo(); + * } + * + * if (a) + * foo(); + * else if (b) + * bar(); + * + * while (a) + * if (b) + * if(c) + * foo(); + * else + * bar(); + * + * Examples where it returns `false`: + * + * if (a) + * foo(); + * else + * bar(); + * + * while (a) { + * if (b) + * if(c) + * foo(); + * else + * bar(); + * } + * + * while (a) + * if (b) { + * if(c) + * foo(); + * } + * else + * bar(); + * @param {ASTNode} node Node representing the code to check. + * @returns {boolean} `true` if an `if` statement within the code would become associated with an `else` appended to that code. + */ + function hasUnsafeIf(node) { + switch (node.type) { + case "IfStatement": + if (!node.alternate) { + return true; + } + return hasUnsafeIf(node.alternate); + case "ForStatement": + case "ForInStatement": + case "ForOfStatement": + case "LabeledStatement": + case "WithStatement": + case "WhileStatement": + return hasUnsafeIf(node.body); + default: + return false; + } + } + + /** + * Determines whether the existing curly braces around the single statement are necessary to preserve the semantics of the code. + * The braces, which make the given block body, are necessary in either of the following situations: + * + * 1. The statement is a lexical declaration. + * 2. Without the braces, an `if` within the statement would become associated with an `else` after the closing brace: + * + * if (a) { + * if (b) + * foo(); + * } + * else + * bar(); + * + * if (a) + * while (b) + * while (c) { + * while (d) + * if (e) + * while(f) + * foo(); + * } + * else + * bar(); + * @param {ASTNode} node `BlockStatement` body with exactly one statement directly inside. The statement can have its own nested statements. + * @returns {boolean} `true` if the braces are necessary - removing them (replacing the given `BlockStatement` body with its single statement content) + * would change the semantics of the code or produce a syntax error. + */ + function areBracesNecessary(node) { + const statement = node.body[0]; + + return isLexicalDeclaration(statement) || + hasUnsafeIf(statement) && isFollowedByElseKeyword(node); + } + /** * Prepares to check the body of a node to see if it's a block statement. * @param {ASTNode} node The node to report if there's a problem. @@ -242,30 +327,29 @@ module.exports = { const hasBlock = (body.type === "BlockStatement"); let expected = null; - if (node.type === "IfStatement" && node.consequent === body && requiresBraceOfConsequent(node)) { + if (hasBlock && (body.body.length !== 1 || areBracesNecessary(body))) { expected = true; } else if (multiOnly) { - if (hasBlock && body.body.length === 1 && !isLexicalDeclaration(body.body[0])) { - expected = false; - } + expected = false; } else if (multiLine) { if (!isCollapsedOneLiner(body)) { expected = true; } + + // otherwise, the body is allowed to have braces or not to have braces + } else if (multiOrNest) { - if (hasBlock && body.body.length === 1 && isOneLiner(body.body[0])) { - const leadingComments = sourceCode.getCommentsBefore(body.body[0]); - const isLexDef = isLexicalDeclaration(body.body[0]); - - if (isLexDef) { - expected = true; - } else { - expected = leadingComments.length > 0; - } - } else if (!isOneLiner(body)) { - expected = true; + if (hasBlock) { + const statement = body.body[0]; + const leadingCommentsInBlock = sourceCode.getCommentsBefore(statement); + + expected = !isOneLiner(statement) || leadingCommentsInBlock.length > 0; + } else { + expected = !isOneLiner(body); } } else { + + // default "all" expected = true; } diff --git a/tools/node_modules/eslint/lib/rules/default-case-last.js b/tools/node_modules/eslint/lib/rules/default-case-last.js new file mode 100644 index 00000000000000..80c5d6bda73958 --- /dev/null +++ b/tools/node_modules/eslint/lib/rules/default-case-last.js @@ -0,0 +1,44 @@ +/** + * @fileoverview Rule to enforce default clauses in switch statements to be last + * @author Milos Djermanovic + */ + +"use strict"; + +//------------------------------------------------------------------------------ +// Rule Definition +//------------------------------------------------------------------------------ + +module.exports = { + meta: { + type: "suggestion", + + docs: { + description: "enforce default clauses in switch statements to be last", + category: "Best Practices", + recommended: false, + url: "https://eslint.org/docs/rules/default-case-last" + }, + + schema: [], + + messages: { + notLast: "Default clause should be the last clause." + } + }, + + create(context) { + return { + SwitchStatement(node) { + const cases = node.cases, + indexOfDefault = cases.findIndex(c => c.test === null); + + if (indexOfDefault !== -1 && indexOfDefault !== cases.length - 1) { + const defaultClause = cases[indexOfDefault]; + + context.report({ node: defaultClause, messageId: "notLast" }); + } + } + }; + } +}; diff --git a/tools/node_modules/eslint/lib/rules/func-names.js b/tools/node_modules/eslint/lib/rules/func-names.js index 1341d03630823f..ecfedb9e0e99c7 100644 --- a/tools/node_modules/eslint/lib/rules/func-names.js +++ b/tools/node_modules/eslint/lib/rules/func-names.js @@ -119,8 +119,7 @@ module.exports = { (parent.type === "VariableDeclarator" && parent.id.type === "Identifier" && parent.init === node) || (parent.type === "Property" && parent.value === node) || (parent.type === "AssignmentExpression" && parent.left.type === "Identifier" && parent.right === node) || - (parent.type === "ExportDefaultDeclaration" && parent.declaration === node) || - (parent.type === "AssignmentPattern" && parent.right === node); + (parent.type === "AssignmentPattern" && parent.left.type === "Identifier" && parent.right === node); } /** @@ -151,33 +150,41 @@ module.exports = { }); } - return { - "FunctionExpression:exit"(node) { + /** + * The listener for function nodes. + * @param {ASTNode} node function node + * @returns {void} + */ + function handleFunction(node) { - // Skip recursive functions. - const nameVar = context.getDeclaredVariables(node)[0]; + // Skip recursive functions. + const nameVar = context.getDeclaredVariables(node)[0]; - if (isFunctionName(nameVar) && nameVar.references.length > 0) { - return; - } + if (isFunctionName(nameVar) && nameVar.references.length > 0) { + return; + } - const hasName = Boolean(node.id && node.id.name); - const config = getConfigForNode(node); - - if (config === "never") { - if (hasName) { - reportUnexpectedNamedFunction(node); - } - } else if (config === "as-needed") { - if (!hasName && !hasInferredName(node)) { - reportUnexpectedUnnamedFunction(node); - } - } else { - if (!hasName && !isObjectOrClassMethod(node)) { - reportUnexpectedUnnamedFunction(node); - } + const hasName = Boolean(node.id && node.id.name); + const config = getConfigForNode(node); + + if (config === "never") { + if (hasName && node.type !== "FunctionDeclaration") { + reportUnexpectedNamedFunction(node); + } + } else if (config === "as-needed") { + if (!hasName && !hasInferredName(node)) { + reportUnexpectedUnnamedFunction(node); + } + } else { + if (!hasName && !isObjectOrClassMethod(node)) { + reportUnexpectedUnnamedFunction(node); } } + } + + return { + "FunctionExpression:exit": handleFunction, + "ExportDefaultDeclaration > FunctionDeclaration": handleFunction }; } }; diff --git a/tools/node_modules/eslint/lib/rules/id-blacklist.js b/tools/node_modules/eslint/lib/rules/id-blacklist.js index 53be62e68a3626..ddff9363aee8a8 100644 --- a/tools/node_modules/eslint/lib/rules/id-blacklist.js +++ b/tools/node_modules/eslint/lib/rules/id-blacklist.js @@ -41,6 +41,7 @@ module.exports = { //-------------------------------------------------------------------------- const blacklist = context.options; + const reportedNodes = new Set(); /** @@ -54,16 +55,69 @@ 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 + ) + ); + } + + /** + * Checks whether the given node is a renamed identifier node in an ObjectPattern destructuring. + * + * Examples: + * const { a : b } = foo; // node `a` is renamed node. + * @param {ASTNode} node `Identifier` node to check. + * @returns {boolean} `true` if the node is a renamed node in an ObjectPattern destructuring. + */ + function isRenamedInDestructuring(node) { + const parent = node.parent; + + return ( + ( + !parent.computed && + parent.type === "Property" && + parent.parent.type === "ObjectPattern" && + parent.value !== node && + parent.key === 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) { - return effectiveParent.type !== "CallExpression" && - effectiveParent.type !== "NewExpression" && - isInvalid(name); + function shouldReport(node) { + const parent = node.parent; + + return ( + parent.type !== "CallExpression" && + parent.type !== "NewExpression" && + !isRenamedImport(node) && + !isRenamedInDestructuring(node) && + isInvalid(node.name) + ); } /** @@ -73,50 +127,63 @@ 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); } - // Report AssignmentExpressions only if they are the left side of the assignment + // Report AssignmentExpressions only if they are the left side of the assignment } else if (effectiveParent.type === "AssignmentExpression" && (effectiveParent.right.type !== "MemberExpression" || - effectiveParent.left.type === "MemberExpression" && - effectiveParent.left.property.name === node.name)) { + effectiveParent.left.type === "MemberExpression" && + 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 the last identifier in an ObjectPattern destructuring. + } else if ( + ( + effectiveParent.type === "Property" && + effectiveParent.value === node.parent && + effectiveParent.parent.type === "ObjectPattern" + ) || + effectiveParent.type === "RestElement" || + effectiveParent.type === "ArrayPattern" || + ( + effectiveParent.type === "AssignmentPattern" && + effectiveParent.left === node.parent + ) + ) { + if (isInvalid(name)) { + report(node); + } } - // Report anything that is a match and not a CallExpression - } else if (shouldReport(effectiveParent, name)) { + } else if (shouldReport(node)) { report(node); } } diff --git a/tools/node_modules/eslint/lib/rules/id-length.js b/tools/node_modules/eslint/lib/rules/id-length.js index c8586ea3481895..a68873ac06289b 100644 --- a/tools/node_modules/eslint/lib/rules/id-length.js +++ b/tools/node_modules/eslint/lib/rules/id-length.js @@ -63,6 +63,7 @@ module.exports = { return obj; }, {}); + const reportedNode = new Set(); const SUPPORTED_EXPRESSIONS = { MemberExpression: properties && function(parent) { @@ -82,8 +83,15 @@ module.exports = { VariableDeclarator(parent, node) { return parent.id === node; }, - Property: properties && function(parent, node) { - return parent.key === node; + Property(parent, node) { + + if (parent.parent.type === "ObjectPattern") { + return ( + parent.value !== parent.key && parent.value === node || + parent.value === parent.key && parent.key === node && properties + ); + } + return properties && !parent.computed && parent.key === node; }, ImportDefaultSpecifier: true, RestElement: true, @@ -92,7 +100,8 @@ module.exports = { ClassDeclaration: true, FunctionDeclaration: true, MethodDefinition: true, - CatchClause: true + CatchClause: true, + ArrayPattern: true }; return { @@ -109,7 +118,8 @@ module.exports = { const isValidExpression = SUPPORTED_EXPRESSIONS[parent.type]; - if (isValidExpression && (isValidExpression === true || isValidExpression(parent, node))) { + if (isValidExpression && !reportedNode.has(node) && (isValidExpression === true || isValidExpression(parent, node))) { + reportedNode.add(node); context.report({ node, messageId: isShort ? "tooShort" : "tooLong", diff --git a/tools/node_modules/eslint/lib/rules/indent-legacy.js b/tools/node_modules/eslint/lib/rules/indent-legacy.js index f1c024c368475d..50010d3f7acb16 100644 --- a/tools/node_modules/eslint/lib/rules/indent-legacy.js +++ b/tools/node_modules/eslint/lib/rules/indent-legacy.js @@ -696,20 +696,6 @@ module.exports = { return startLine === endLine; } - /** - * Check to see if the first element inside an array is an object and on the same line as the node - * If the node is not an array then it will return false. - * @param {ASTNode} node node to check - * @returns {boolean} success/failure - */ - function isFirstArrayElementOnSameLine(node) { - if (node.type === "ArrayExpression" && node.elements[0]) { - return node.elements[0].loc.start.line === node.loc.start.line && node.elements[0].type === "ObjectExpression"; - } - return false; - - } - /** * Check indent for array block content or object block content * @param {ASTNode} node node to examine @@ -776,8 +762,6 @@ module.exports = { nodeIndent += indentSize; } } - } else if (!parentVarNode && !isFirstArrayElementOnSameLine(parent) && parent.type !== "MemberExpression" && parent.type !== "ExpressionStatement" && parent.type !== "AssignmentExpression" && parent.type !== "Property") { - nodeIndent += indentSize; } checkFirstNodeLineIndent(node, nodeIndent); diff --git a/tools/node_modules/eslint/lib/rules/indent.js b/tools/node_modules/eslint/lib/rules/indent.js index 694cf7d9e6ed4f..d576fde0382461 100644 --- a/tools/node_modules/eslint/lib/rules/indent.js +++ b/tools/node_modules/eslint/lib/rules/indent.js @@ -540,8 +540,15 @@ module.exports = { ] }, outerIIFEBody: { - type: "integer", - minimum: 0 + oneOf: [ + { + type: "integer", + minimum: 0 + }, + { + enum: ["off"] + } + ] }, MemberExpression: { oneOf: [ @@ -590,6 +597,10 @@ module.exports = { type: "boolean", default: false }, + offsetTernaryExpressions: { + type: "boolean", + default: false + }, ignoredNodes: { type: "array", items: { @@ -922,7 +933,11 @@ module.exports = { parameterParens.add(openingParen); parameterParens.add(closingParen); - offsets.setDesiredOffset(openingParen, sourceCode.getTokenBefore(openingParen), 0); + + const offsetAfterToken = node.callee.type === "TaggedTemplateExpression" ? sourceCode.getFirstToken(node.callee.quasi) : openingParen; + const offsetToken = sourceCode.getTokenBefore(offsetAfterToken); + + offsets.setDesiredOffset(openingParen, offsetToken, 0); addElementListIndent(node.arguments, openingParen, closingParen, options.CallExpression.arguments); } @@ -1088,7 +1103,6 @@ module.exports = { }, "BlockStatement, ClassBody"(node) { - let blockIndentLevel; if (node.parent && isOuterIIFE(node.parent)) { @@ -1108,6 +1122,7 @@ module.exports = { if (!astUtils.STATEMENT_LIST_PARENTS.has(node.parent.type)) { offsets.setDesiredOffset(sourceCode.getFirstToken(node), sourceCode.getFirstToken(node.parent), 0); } + addElementListIndent(node.body, sourceCode.getFirstToken(node), sourceCode.getLastToken(node), blockIndentLevel); }, @@ -1142,7 +1157,8 @@ module.exports = { offsets.setDesiredOffset(questionMarkToken, firstToken, 1); offsets.setDesiredOffset(colonToken, firstToken, 1); - offsets.setDesiredOffset(firstConsequentToken, firstToken, 1); + offsets.setDesiredOffset(firstConsequentToken, firstToken, + options.offsetTernaryExpressions ? 2 : 1); /* * The alternate and the consequent should usually have the same indentation. @@ -1167,7 +1183,9 @@ module.exports = { * If `baz` were aligned with `bar` rather than being offset by 1 from `foo`, `baz` would end up * having no expected indentation. */ - offsets.setDesiredOffset(firstAlternateToken, firstToken, 1); + offsets.setDesiredOffset(firstAlternateToken, firstToken, + firstAlternateToken.type === "Punctuator" && + options.offsetTernaryExpressions ? 2 : 1); } } }, diff --git a/tools/node_modules/eslint/lib/rules/index.js b/tools/node_modules/eslint/lib/rules/index.js index d3fbe412080360..7f563eb2ebfb96 100644 --- a/tools/node_modules/eslint/lib/rules/index.js +++ b/tools/node_modules/eslint/lib/rules/index.js @@ -37,6 +37,7 @@ module.exports = new LazyLoadingRuleMap(Object.entries({ "constructor-super": () => require("./constructor-super"), curly: () => require("./curly"), "default-case": () => require("./default-case"), + "default-case-last": () => require("./default-case-last"), "default-param-last": () => require("./default-param-last"), "dot-location": () => require("./dot-location"), "dot-notation": () => require("./dot-notation"), @@ -178,6 +179,7 @@ module.exports = new LazyLoadingRuleMap(Object.entries({ "no-prototype-builtins": () => require("./no-prototype-builtins"), "no-redeclare": () => require("./no-redeclare"), "no-regex-spaces": () => require("./no-regex-spaces"), + "no-restricted-exports": () => require("./no-restricted-exports"), "no-restricted-globals": () => require("./no-restricted-globals"), "no-restricted-imports": () => require("./no-restricted-imports"), "no-restricted-modules": () => require("./no-restricted-modules"), @@ -215,6 +217,7 @@ module.exports = new LazyLoadingRuleMap(Object.entries({ "no-unused-labels": () => require("./no-unused-labels"), "no-unused-vars": () => require("./no-unused-vars"), "no-use-before-define": () => require("./no-use-before-define"), + "no-useless-backreference": () => require("./no-useless-backreference"), "no-useless-call": () => require("./no-useless-call"), "no-useless-catch": () => require("./no-useless-catch"), "no-useless-computed-key": () => require("./no-useless-computed-key"), diff --git a/tools/node_modules/eslint/lib/rules/key-spacing.js b/tools/node_modules/eslint/lib/rules/key-spacing.js index 6d1b9121c78c5f..c405043794c7d1 100644 --- a/tools/node_modules/eslint/lib/rules/key-spacing.js +++ b/tools/node_modules/eslint/lib/rules/key-spacing.js @@ -414,8 +414,7 @@ module.exports = { if (property.computed) { return sourceCode.getText().slice(key.range[0], key.range[1]); } - - return property.key.name || property.key.value; + return astUtils.getStaticPropertyName(property); } /** diff --git a/tools/node_modules/eslint/lib/rules/linebreak-style.js b/tools/node_modules/eslint/lib/rules/linebreak-style.js index 97d552ea07c966..078eaf2cd268d2 100644 --- a/tools/node_modules/eslint/lib/rules/linebreak-style.js +++ b/tools/node_modules/eslint/lib/rules/linebreak-style.js @@ -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", diff --git a/tools/node_modules/eslint/lib/rules/max-len.js b/tools/node_modules/eslint/lib/rules/max-len.js index b29099ed4c4f09..995e0c52026385 100644 --- a/tools/node_modules/eslint/lib/rules/max-len.js +++ b/tools/node_modules/eslint/lib/rules/max-len.js @@ -183,12 +183,27 @@ module.exports = { (end.line > lineNumber || (end.line === lineNumber && end.column === line.length)); } + /** + * Check if a node is a JSXEmptyExpression contained in a single line JSXExpressionContainer. + * @param {ASTNode} node A node to check. + * @returns {boolean} True if the node is a JSXEmptyExpression contained in a single line JSXExpressionContainer. + */ + function isJSXEmptyExpressionInSingleLineContainer(node) { + if (!node || !node.parent || node.type !== "JSXEmptyExpression" || node.parent.type !== "JSXExpressionContainer") { + return false; + } + + const parent = node.parent; + + return parent.loc.start.line === parent.loc.end.line; + } + /** * Gets the line after the comment and any remaining trailing whitespace is * 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) { @@ -252,6 +267,33 @@ module.exports = { return acc; } + /** + * Returns an array of all comments in the source code. + * If the element in the array is a JSXEmptyExpression contained with a single line JSXExpressionContainer, + * the element is changed with JSXExpressionContainer node. + * @returns {ASTNode[]} An array of comment nodes + */ + function getAllComments() { + const comments = []; + + sourceCode.getAllComments() + .forEach(commentNode => { + const containingNode = sourceCode.getNodeByRangeIndex(commentNode.range[0]); + + if (isJSXEmptyExpressionInSingleLineContainer(containingNode)) { + + // push a unique node only + if (comments[comments.length - 1] !== containingNode.parent) { + comments.push(containingNode.parent); + } + } else { + comments.push(commentNode); + } + }); + + return comments; + } + /** * Check the program for max length * @param {ASTNode} node Node to examine @@ -264,7 +306,7 @@ module.exports = { const lines = sourceCode.lines, // list of comments to ignore - comments = ignoreComments || maxCommentLength || ignoreTrailingComments ? sourceCode.getAllComments() : []; + comments = ignoreComments || maxCommentLength || ignoreTrailingComments ? getAllComments() : []; // we iterate over comments in parallel with the lines let commentsIndex = 0; diff --git a/tools/node_modules/eslint/lib/rules/max-lines-per-function.js b/tools/node_modules/eslint/lib/rules/max-lines-per-function.js index 0cfc1f8da9e65e..03539fae470078 100644 --- a/tools/node_modules/eslint/lib/rules/max-lines-per-function.js +++ b/tools/node_modules/eslint/lib/rules/max-lines-per-function.js @@ -54,9 +54,6 @@ const OPTIONS_OR_INTEGER_SCHEMA = { function getCommentLineNumbers(comments) { const map = new Map(); - if (!comments) { - return map; - } comments.forEach(comment => { for (let i = comment.loc.start.line; i <= comment.loc.end.line; i++) { map.set(i, comment); diff --git a/tools/node_modules/eslint/lib/rules/multiline-comment-style.js b/tools/node_modules/eslint/lib/rules/multiline-comment-style.js index fb50e1522ea11d..9524818b8bd74d 100644 --- a/tools/node_modules/eslint/lib/rules/multiline-comment-style.js +++ b/tools/node_modules/eslint/lib/rules/multiline-comment-style.js @@ -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; } diff --git a/tools/node_modules/eslint/lib/rules/new-cap.js b/tools/node_modules/eslint/lib/rules/new-cap.js index cee979310ea7cc..7cce968c5aed0e 100644 --- a/tools/node_modules/eslint/lib/rules/new-cap.js +++ b/tools/node_modules/eslint/lib/rules/new-cap.js @@ -9,6 +9,8 @@ // Requirements //------------------------------------------------------------------------------ +const astUtils = require("./utils/ast-utils"); + //------------------------------------------------------------------------------ // Helpers //------------------------------------------------------------------------------ @@ -160,13 +162,7 @@ module.exports = { let name = ""; if (node.callee.type === "MemberExpression") { - const property = node.callee.property; - - if (property.type === "Literal" && (typeof property.value === "string")) { - name = property.value; - } else if (property.type === "Identifier" && !node.callee.computed) { - name = property.name; - } + name = astUtils.getStaticPropertyName(node.callee) || ""; } else { name = node.callee.name; } diff --git a/tools/node_modules/eslint/lib/rules/no-confusing-arrow.js b/tools/node_modules/eslint/lib/rules/no-confusing-arrow.js index b9a0e6ed0a70b5..9009b64fa1559a 100644 --- a/tools/node_modules/eslint/lib/rules/no-confusing-arrow.js +++ b/tools/node_modules/eslint/lib/rules/no-confusing-arrow.js @@ -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 */ @@ -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)})`); } }); diff --git a/tools/node_modules/eslint/lib/rules/no-constant-condition.js b/tools/node_modules/eslint/lib/rules/no-constant-condition.js index d6d04174298cff..5e5838641028fe 100644 --- a/tools/node_modules/eslint/lib/rules/no-constant-condition.js +++ b/tools/node_modules/eslint/lib/rules/no-constant-condition.js @@ -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") { diff --git a/tools/node_modules/eslint/lib/rules/no-control-regex.js b/tools/node_modules/eslint/lib/rules/no-control-regex.js index 24e6b197be0b44..b39f731c3cdf29 100644 --- a/tools/node_modules/eslint/lib/rules/no-control-regex.js +++ b/tools/node_modules/eslint/lib/rules/no-control-regex.js @@ -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 */ diff --git a/tools/node_modules/eslint/lib/rules/no-dupe-class-members.js b/tools/node_modules/eslint/lib/rules/no-dupe-class-members.js index 6041e9e371ce5e..b12939d57bc884 100644 --- a/tools/node_modules/eslint/lib/rules/no-dupe-class-members.js +++ b/tools/node_modules/eslint/lib/rules/no-dupe-class-members.js @@ -5,6 +5,8 @@ "use strict"; +const astUtils = require("./utils/ast-utils"); + //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ @@ -53,21 +55,6 @@ module.exports = { return stateMap[key][isStatic ? "static" : "nonStatic"]; } - /** - * Gets the name text of a given node. - * @param {ASTNode} node A node to get the name. - * @returns {string} The name text of the node. - */ - function getName(node) { - switch (node.type) { - case "Identifier": return node.name; - case "Literal": return String(node.value); - - /* istanbul ignore next: syntax error */ - default: return ""; - } - } - return { // Initializes the stack of state of member declarations. @@ -87,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 = getName(node.key); const state = getState(name, node.static); let isDuplicate = false; diff --git a/tools/node_modules/eslint/lib/rules/no-dupe-else-if.js b/tools/node_modules/eslint/lib/rules/no-dupe-else-if.js index a165e16607d2f0..cbeb437da1e7ec 100644 --- a/tools/node_modules/eslint/lib/rules/no-dupe-else-if.js +++ b/tools/node_modules/eslint/lib/rules/no-dupe-else-if.js @@ -53,7 +53,7 @@ module.exports = { docs: { description: "disallow duplicate conditions in if-else-if chains", category: "Possible Errors", - recommended: false, + recommended: true, url: "https://eslint.org/docs/rules/no-dupe-else-if" }, diff --git a/tools/node_modules/eslint/lib/rules/no-eval.js b/tools/node_modules/eslint/lib/rules/no-eval.js index 9e56fb00b9fc5b..a293b04aa37de2 100644 --- a/tools/node_modules/eslint/lib/rules/no-eval.js +++ b/tools/node_modules/eslint/lib/rules/no-eval.js @@ -158,7 +158,7 @@ module.exports = { context.report({ node: reportNode, - loc: locationNode.loc.start, + loc: locationNode.loc, messageId: "unexpected" }); } diff --git a/tools/node_modules/eslint/lib/rules/no-extra-boolean-cast.js b/tools/node_modules/eslint/lib/rules/no-extra-boolean-cast.js index 336f601d1652de..8ccd0bce9060b1 100644 --- a/tools/node_modules/eslint/lib/rules/no-extra-boolean-cast.js +++ b/tools/node_modules/eslint/lib/rules/no-extra-boolean-cast.js @@ -26,7 +26,16 @@ module.exports = { url: "https://eslint.org/docs/rules/no-extra-boolean-cast" }, - schema: [], + schema: [{ + type: "object", + properties: { + enforceForLogicalOperands: { + type: "boolean", + default: false + } + }, + additionalProperties: false + }], fixable: "code", messages: { @@ -47,23 +56,67 @@ module.exports = { "ForStatement" ]; + /** + * Check if a node is a Boolean function or constructor. + * @param {ASTNode} node the node + * @returns {boolean} If the node is Boolean function or constructor + */ + function isBooleanFunctionOrConstructorCall(node) { + + // Boolean() and new Boolean() + return (node.type === "CallExpression" || node.type === "NewExpression") && + node.callee.type === "Identifier" && + node.callee.name === "Boolean"; + } + + /** + * Checks whether the node is a logical expression and that the option is enabled + * @param {ASTNode} node the node + * @returns {boolean} if the node is a logical expression and option is enabled + */ + function isLogicalContext(node) { + return node.type === "LogicalExpression" && + (node.operator === "||" || node.operator === "&&") && + (context.options.length && context.options[0].enforceForLogicalOperands === true); + + } + + /** * Check if a node is in a context where its value would be coerced to a boolean at runtime. * @param {ASTNode} node The node - * @param {ASTNode} parent Its parent * @returns {boolean} If it is in a boolean context */ - function isInBooleanContext(node, parent) { + function isInBooleanContext(node) { return ( - (BOOLEAN_NODE_TYPES.indexOf(parent.type) !== -1 && - node === parent.test) || + (isBooleanFunctionOrConstructorCall(node.parent) && + node === node.parent.arguments[0]) || + + (BOOLEAN_NODE_TYPES.indexOf(node.parent.type) !== -1 && + node === node.parent.test) || // ! - (parent.type === "UnaryExpression" && - parent.operator === "!") + (node.parent.type === "UnaryExpression" && + node.parent.operator === "!") + ); + } + + /** + * Checks whether the node is a context that should report an error + * Acts recursively if it is in a logical context + * @param {ASTNode} node the node + * @returns {boolean} If the node is in one of the flagged contexts + */ + function isInFlaggedContext(node) { + return isInBooleanContext(node) || + (isLogicalContext(node.parent) && + + // For nested logical statements + isInFlaggedContext(node.parent) ); } + /** * Check if a node has comments inside. * @param {ASTNode} node The node to check. @@ -75,24 +128,18 @@ module.exports = { return { UnaryExpression(node) { - const ancestors = context.getAncestors(), - parent = ancestors.pop(), - grandparent = ancestors.pop(); + const parent = node.parent; + // Exit early if it's guaranteed not to match if (node.operator !== "!" || - parent.type !== "UnaryExpression" || - parent.operator !== "!") { + parent.type !== "UnaryExpression" || + parent.operator !== "!") { return; } - if (isInBooleanContext(parent, grandparent) || - // Boolean() and new Boolean() - ((grandparent.type === "CallExpression" || grandparent.type === "NewExpression") && - grandparent.callee.type === "Identifier" && - grandparent.callee.name === "Boolean") - ) { + if (isInFlaggedContext(parent)) { context.report({ node: parent, messageId: "unexpectedNegation", @@ -110,6 +157,10 @@ module.exports = { prefix = " "; } + if (astUtils.getPrecedence(node.argument) < astUtils.getPrecedence(parent.parent)) { + return fixer.replaceText(parent, `(${sourceCode.getText(node.argument)})`); + } + return fixer.replaceText(parent, prefix + sourceCode.getText(node.argument)); } }); @@ -122,7 +173,7 @@ module.exports = { return; } - if (isInBooleanContext(node, parent)) { + if (isInFlaggedContext(node)) { context.report({ node, messageId: "unexpectedCall", diff --git a/tools/node_modules/eslint/lib/rules/no-extra-parens.js b/tools/node_modules/eslint/lib/rules/no-extra-parens.js index f96e572bfeef54..a5488c3c1c6aa4 100644 --- a/tools/node_modules/eslint/lib/rules/no-extra-parens.js +++ b/tools/node_modules/eslint/lib/rules/no-extra-parens.js @@ -169,6 +169,28 @@ module.exports = { return ruleApplies(node) && isParenthesisedTwice(node); } + /** + * Determines if a node that is expected to be parenthesised is surrounded by + * (potentially) invalid extra parentheses with considering precedence level of the node. + * If the preference level of the node is not higher or equal to precedence lower limit, it also checks + * whether the node is surrounded by parentheses twice or not. + * @param {ASTNode} node The node to be checked. + * @param {number} precedenceLowerLimit The lower limit of precedence. + * @returns {boolean} True if the node is has an unexpected extra pair of parentheses. + * @private + */ + function hasExcessParensWithPrecedence(node, precedenceLowerLimit) { + if (ruleApplies(node) && isParenthesised(node)) { + if ( + precedence(node) >= precedenceLowerLimit || + isParenthesisedTwice(node) + ) { + return true; + } + } + return false; + } + /** * Determines if a node test expression is allowed to have a parenthesised assignment * @param {ASTNode} node The node to be checked. @@ -320,6 +342,17 @@ module.exports = { return node.type === "CallExpression" && node.callee.type === "FunctionExpression"; } + /** + * Determines if the given node can be the assignment target in destructuring or the LHS of an assignment. + * This is to avoid an autofix that could change behavior because parsers mistakenly allow invalid syntax, + * such as `(a = b) = c` and `[(a = b) = c] = []`. Ideally, this function shouldn't be necessary. + * @param {ASTNode} [node] The node to check + * @returns {boolean} `true` if the given node can be a valid assignment target + */ + function canBeAssignmentTarget(node) { + return node && (node.type === "Identifier" || node.type === "MemberExpression"); + } + /** * Report the node * @param {ASTNode} node node to evaluate @@ -370,17 +403,13 @@ module.exports = { } /** - * Evaluate Unary update + * Evaluate a argument of the node. * @param {ASTNode} node node to evaluate * @returns {void} * @private */ - function checkUnaryUpdate(node) { - if (node.type === "UnaryExpression" && node.argument.type === "BinaryExpression" && node.argument.operator === "**") { - return; - } - - if (hasExcessParens(node.argument) && precedence(node.argument) >= precedence(node)) { + function checkArgumentWithPrecedence(node) { + if (hasExcessParensWithPrecedence(node.argument, precedence(node))) { report(node.argument); } } @@ -411,25 +440,24 @@ module.exports = { function checkCallNew(node) { const callee = node.callee; - if (hasExcessParens(callee) && precedence(callee) >= precedence(node)) { + if (hasExcessParensWithPrecedence(callee, precedence(node))) { const hasNewParensException = callee.type === "NewExpression" && !isNewExpressionWithParens(callee); if ( hasDoubleExcessParens(callee) || !isIIFE(node) && !hasNewParensException && !( - /* - * Allow extra parens around a new expression if - * there are intervening parentheses. - */ - (callee.type === "MemberExpression" && doesMemberExpressionContainCallExpression(callee)) + // Allow extra parens around a new expression if they are intervening parentheses. + node.type === "NewExpression" && + callee.type === "MemberExpression" && + doesMemberExpressionContainCallExpression(callee) ) ) { report(node.callee); } } node.arguments - .filter(arg => hasExcessParens(arg) && precedence(arg) >= PRECEDENCE_OF_ASSIGNMENT_EXPR) + .filter(arg => hasExcessParensWithPrecedence(arg, PRECEDENCE_OF_ASSIGNMENT_EXPR)) .forEach(report); } @@ -444,15 +472,26 @@ module.exports = { const leftPrecedence = precedence(node.left); const rightPrecedence = precedence(node.right); const isExponentiation = node.operator === "**"; - const shouldSkipLeft = (NESTED_BINARY && (node.left.type === "BinaryExpression" || node.left.type === "LogicalExpression")) || - node.left.type === "UnaryExpression" && isExponentiation; + const shouldSkipLeft = NESTED_BINARY && (node.left.type === "BinaryExpression" || node.left.type === "LogicalExpression"); const shouldSkipRight = NESTED_BINARY && (node.right.type === "BinaryExpression" || node.right.type === "LogicalExpression"); - if (!shouldSkipLeft && hasExcessParens(node.left) && (leftPrecedence > prec || (leftPrecedence === prec && !isExponentiation))) { - report(node.left); + if (!shouldSkipLeft && hasExcessParens(node.left)) { + if ( + !(node.left.type === "UnaryExpression" && isExponentiation) && + (leftPrecedence > prec || (leftPrecedence === prec && !isExponentiation)) || + isParenthesisedTwice(node.left) + ) { + report(node.left); + } } - if (!shouldSkipRight && hasExcessParens(node.right) && (rightPrecedence > prec || (rightPrecedence === prec && isExponentiation))) { - report(node.right); + + if (!shouldSkipRight && hasExcessParens(node.right)) { + if ( + (rightPrecedence > prec || (rightPrecedence === prec && isExponentiation)) || + isParenthesisedTwice(node.right) + ) { + report(node.right); + } } } @@ -485,11 +524,7 @@ module.exports = { * @returns {void} */ function checkSpreadOperator(node) { - const hasExtraParens = precedence(node.argument) >= PRECEDENCE_OF_ASSIGNMENT_EXPR - ? hasExcessParens(node.argument) - : hasDoubleExcessParens(node.argument); - - if (hasExtraParens) { + if (hasExcessParensWithPrecedence(node.argument, PRECEDENCE_OF_ASSIGNMENT_EXPR)) { report(node.argument); } } @@ -651,7 +686,13 @@ module.exports = { return { ArrayExpression(node) { node.elements - .filter(e => e && hasExcessParens(e) && precedence(e) >= PRECEDENCE_OF_ASSIGNMENT_EXPR) + .filter(e => e && hasExcessParensWithPrecedence(e, PRECEDENCE_OF_ASSIGNMENT_EXPR)) + .forEach(report); + }, + + ArrayPattern(node) { + node.elements + .filter(e => canBeAssignmentTarget(e) && hasExcessParens(e)) .forEach(report); }, @@ -661,8 +702,7 @@ module.exports = { } if (node.body.type === "ConditionalExpression" && - IGNORE_ARROW_CONDITIONALS && - !isParenthesisedTwice(node.body) + IGNORE_ARROW_CONDITIONALS ) { return; } @@ -674,18 +714,18 @@ module.exports = { if (astUtils.isOpeningParenToken(tokenBeforeFirst) && astUtils.isOpeningBraceToken(firstBodyToken)) { tokensToIgnore.add(firstBodyToken); } - if (hasExcessParens(node.body) && precedence(node.body) >= PRECEDENCE_OF_ASSIGNMENT_EXPR) { + if (hasExcessParensWithPrecedence(node.body, PRECEDENCE_OF_ASSIGNMENT_EXPR)) { report(node.body); } } }, AssignmentExpression(node) { - if (isReturnAssignException(node)) { - return; + if (canBeAssignmentTarget(node.left) && hasExcessParens(node.left)) { + report(node.left); } - if (hasExcessParens(node.right) && precedence(node.right) >= precedence(node)) { + if (!isReturnAssignException(node) && hasExcessParensWithPrecedence(node.right, precedence(node))) { report(node.right); } }, @@ -702,8 +742,8 @@ module.exports = { ClassBody(node) { node.body - .filter(member => member.type === "MethodDefinition" && member.computed && - member.key && hasExcessParens(member.key) && precedence(member.key) >= PRECEDENCE_OF_ASSIGNMENT_EXPR) + .filter(member => member.type === "MethodDefinition" && member.computed && member.key) + .filter(member => hasExcessParensWithPrecedence(member.key, PRECEDENCE_OF_ASSIGNMENT_EXPR)) .forEach(member => report(member.key)); }, @@ -711,16 +751,18 @@ module.exports = { if (isReturnAssignException(node)) { return; } - - if (hasExcessParens(node.test) && precedence(node.test) >= precedence({ type: "LogicalExpression", operator: "||" })) { + if ( + !isCondAssignException(node) && + hasExcessParensWithPrecedence(node.test, precedence({ type: "LogicalExpression", operator: "||" })) + ) { report(node.test); } - if (hasExcessParens(node.consequent) && precedence(node.consequent) >= PRECEDENCE_OF_ASSIGNMENT_EXPR) { + if (hasExcessParensWithPrecedence(node.consequent, PRECEDENCE_OF_ASSIGNMENT_EXPR)) { report(node.consequent); } - if (hasExcessParens(node.alternate) && precedence(node.alternate) >= PRECEDENCE_OF_ASSIGNMENT_EXPR) { + if (hasExcessParensWithPrecedence(node.alternate, PRECEDENCE_OF_ASSIGNMENT_EXPR)) { report(node.alternate); } }, @@ -757,9 +799,19 @@ module.exports = { tokensToIgnore.add(firstLeftToken); } } - if (!(node.type === "ForOfStatement" && node.right.type === "SequenceExpression") && hasExcessParens(node.right)) { + + if (node.type === "ForOfStatement") { + const hasExtraParens = node.right.type === "SequenceExpression" + ? hasDoubleExcessParens(node.right) + : hasExcessParens(node.right); + + if (hasExtraParens) { + report(node.right); + } + } else if (hasExcessParens(node.right)) { report(node.right); } + if (hasExcessParens(node.left)) { report(node.left); } @@ -910,11 +962,17 @@ module.exports = { NewExpression: checkCallNew, ObjectExpression(node) { + node.properties + .filter(property => property.value && hasExcessParensWithPrecedence(property.value, PRECEDENCE_OF_ASSIGNMENT_EXPR)) + .forEach(property => report(property.value)); + }, + + ObjectPattern(node) { node.properties .filter(property => { const value = property.value; - return value && hasExcessParens(value) && precedence(value) >= PRECEDENCE_OF_ASSIGNMENT_EXPR; + return canBeAssignmentTarget(value) && hasExcessParens(value); }).forEach(property => report(property.value)); }, @@ -922,12 +980,20 @@ module.exports = { if (node.computed) { const { key } = node; - if (key && hasExcessParens(key) && precedence(key) >= PRECEDENCE_OF_ASSIGNMENT_EXPR) { + if (key && hasExcessParensWithPrecedence(key, PRECEDENCE_OF_ASSIGNMENT_EXPR)) { report(key); } } }, + RestElement(node) { + const argument = node.argument; + + if (canBeAssignmentTarget(argument) && hasExcessParens(argument)) { + report(argument); + } + }, + ReturnStatement(node) { const returnToken = sourceCode.getFirstToken(node); @@ -945,8 +1011,10 @@ module.exports = { }, SequenceExpression(node) { + const precedenceOfNode = precedence(node); + node.expressions - .filter(e => hasExcessParens(e) && precedence(e) >= precedence(node)) + .filter(e => hasExcessParensWithPrecedence(e, precedenceOfNode)) .forEach(report); }, @@ -970,16 +1038,17 @@ module.exports = { } }, - UnaryExpression: checkUnaryUpdate, - UpdateExpression: checkUnaryUpdate, - AwaitExpression: checkUnaryUpdate, + UnaryExpression: checkArgumentWithPrecedence, + UpdateExpression: checkArgumentWithPrecedence, + AwaitExpression: checkArgumentWithPrecedence, VariableDeclarator(node) { - if (node.init && hasExcessParens(node.init) && - precedence(node.init) >= PRECEDENCE_OF_ASSIGNMENT_EXPR && + if ( + node.init && hasExcessParensWithPrecedence(node.init, PRECEDENCE_OF_ASSIGNMENT_EXPR) && - // RegExp literal is allowed to have parens (#1589) - !(node.init.type === "Literal" && node.init.regex)) { + // RegExp literal is allowed to have parens (#1589) + !(node.init.type === "Literal" && node.init.regex) + ) { report(node.init); } }, @@ -1022,9 +1091,13 @@ module.exports = { }, AssignmentPattern(node) { - const { right } = node; + const { left, right } = node; + + if (canBeAssignmentTarget(left) && hasExcessParens(left)) { + report(left); + } - if (right && hasExcessParens(right) && precedence(right) >= PRECEDENCE_OF_ASSIGNMENT_EXPR) { + if (right && hasExcessParensWithPrecedence(right, PRECEDENCE_OF_ASSIGNMENT_EXPR)) { report(right); } } diff --git a/tools/node_modules/eslint/lib/rules/no-func-assign.js b/tools/node_modules/eslint/lib/rules/no-func-assign.js index 66756e62bef5b2..33d0ad9ecd1433 100644 --- a/tools/node_modules/eslint/lib/rules/no-func-assign.js +++ b/tools/node_modules/eslint/lib/rules/no-func-assign.js @@ -22,7 +22,11 @@ module.exports = { url: "https://eslint.org/docs/rules/no-func-assign" }, - schema: [] + schema: [], + + messages: { + isAFunction: "'{{name}}' is a function." + } }, create(context) { @@ -34,7 +38,13 @@ module.exports = { */ function checkReference(references) { astUtils.getModifyingReferences(references).forEach(reference => { - context.report({ node: reference.identifier, message: "'{{name}}' is a function.", data: { name: reference.identifier.name } }); + context.report({ + node: reference.identifier, + messageId: "isAFunction", + data: { + name: reference.identifier.name + } + }); }); } diff --git a/tools/node_modules/eslint/lib/rules/no-global-assign.js b/tools/node_modules/eslint/lib/rules/no-global-assign.js index 4ab0c706446256..ea854c4aa8cd9b 100644 --- a/tools/node_modules/eslint/lib/rules/no-global-assign.js +++ b/tools/node_modules/eslint/lib/rules/no-global-assign.js @@ -32,7 +32,11 @@ module.exports = { }, additionalProperties: false } - ] + ], + + messages: { + globalShouldNotBeModified: "Read-only global '{{name}}' should not be modified." + } }, create(context) { @@ -60,8 +64,10 @@ module.exports = { ) { context.report({ node: identifier, - message: "Read-only global '{{name}}' should not be modified.", - data: identifier + messageId: "globalShouldNotBeModified", + data: { + name: identifier.name + } }); } } diff --git a/tools/node_modules/eslint/lib/rules/no-implicit-coercion.js b/tools/node_modules/eslint/lib/rules/no-implicit-coercion.js index c80f9813020be5..6d5ee61e96bd5b 100644 --- a/tools/node_modules/eslint/lib/rules/no-implicit-coercion.js +++ b/tools/node_modules/eslint/lib/rules/no-implicit-coercion.js @@ -187,7 +187,11 @@ module.exports = { } }, additionalProperties: false - }] + }], + + messages: { + useRecommendation: "use `{{recommendation}}` instead." + } }, create(context) { @@ -204,7 +208,7 @@ module.exports = { function report(node, recommendation, shouldFix) { context.report({ node, - message: "use `{{recommendation}}` instead.", + messageId: "useRecommendation", data: { recommendation }, diff --git a/tools/node_modules/eslint/lib/rules/no-implied-eval.js b/tools/node_modules/eslint/lib/rules/no-implied-eval.js index e0764d8223db0a..46bb5d4f76e5f7 100644 --- a/tools/node_modules/eslint/lib/rules/no-implied-eval.js +++ b/tools/node_modules/eslint/lib/rules/no-implied-eval.js @@ -20,7 +20,11 @@ module.exports = { url: "https://eslint.org/docs/rules/no-implied-eval" }, - schema: [] + schema: [], + + messages: { + impliedEval: "Implied eval. Consider passing a function instead of a string." + } }, create(context) { @@ -107,7 +111,10 @@ module.exports = { // remove the entire substack, to avoid duplicate reports const substack = impliedEvalAncestorsStack.pop(); - context.report({ node: substack[0], message: "Implied eval. Consider passing a function instead of a string." }); + context.report({ + node: substack[0], + messageId: "impliedEval" + }); } } diff --git a/tools/node_modules/eslint/lib/rules/no-import-assign.js b/tools/node_modules/eslint/lib/rules/no-import-assign.js index 0865cf9a97704d..32e445ff68b3ef 100644 --- a/tools/node_modules/eslint/lib/rules/no-import-assign.js +++ b/tools/node_modules/eslint/lib/rules/no-import-assign.js @@ -180,7 +180,7 @@ module.exports = { docs: { description: "disallow assigning to imported bindings", category: "Possible Errors", - recommended: false, + recommended: true, url: "https://eslint.org/docs/rules/no-import-assign" }, diff --git a/tools/node_modules/eslint/lib/rules/no-inline-comments.js b/tools/node_modules/eslint/lib/rules/no-inline-comments.js index bd226ecc35fde1..41b0f1e664c776 100644 --- a/tools/node_modules/eslint/lib/rules/no-inline-comments.js +++ b/tools/node_modules/eslint/lib/rules/no-inline-comments.js @@ -21,7 +21,11 @@ module.exports = { url: "https://eslint.org/docs/rules/no-inline-comments" }, - schema: [] + schema: [], + + messages: { + unexpectedInlineComment: "Unexpected comment inline with code." + } }, create(context) { @@ -64,7 +68,10 @@ module.exports = { return; } - context.report({ node, message: "Unexpected comment inline with code." }); + context.report({ + node, + messageId: "unexpectedInlineComment" + }); } //-------------------------------------------------------------------------- diff --git a/tools/node_modules/eslint/lib/rules/no-inner-declarations.js b/tools/node_modules/eslint/lib/rules/no-inner-declarations.js index 60508d3e864eda..e1c29e0a3b4f3f 100644 --- a/tools/node_modules/eslint/lib/rules/no-inner-declarations.js +++ b/tools/node_modules/eslint/lib/rules/no-inner-declarations.js @@ -24,7 +24,11 @@ module.exports = { { enum: ["functions", "both"] } - ] + ], + + messages: { + moveDeclToRoot: "Move {{type}} declaration to {{body}} root." + } }, create(context) { @@ -68,7 +72,7 @@ module.exports = { if (!valid) { context.report({ node, - message: "Move {{type}} declaration to {{body}} root.", + messageId: "moveDeclToRoot", data: { type: (node.type === "FunctionDeclaration" ? "function" : "variable"), body: (body.type === "Program" ? "program" : "function body") diff --git a/tools/node_modules/eslint/lib/rules/no-invalid-regexp.js b/tools/node_modules/eslint/lib/rules/no-invalid-regexp.js index 852efbbb935b90..c09e36fd017697 100644 --- a/tools/node_modules/eslint/lib/rules/no-invalid-regexp.js +++ b/tools/node_modules/eslint/lib/rules/no-invalid-regexp.js @@ -39,7 +39,11 @@ module.exports = { } }, additionalProperties: false - }] + }], + + messages: { + regexMessage: "{{message}}." + } }, create(context) { @@ -116,7 +120,7 @@ module.exports = { if (message) { context.report({ node, - message: "{{message}}.", + messageId: "regexMessage", data: { message } }); } diff --git a/tools/node_modules/eslint/lib/rules/no-invalid-this.js b/tools/node_modules/eslint/lib/rules/no-invalid-this.js index 5398fc3b5f842c..a79c586d719852 100644 --- a/tools/node_modules/eslint/lib/rules/no-invalid-this.js +++ b/tools/node_modules/eslint/lib/rules/no-invalid-this.js @@ -37,7 +37,11 @@ module.exports = { }, additionalProperties: false } - ] + ], + + messages: { + unexpectedThis: "Unexpected 'this'." + } }, create(context) { @@ -130,7 +134,10 @@ module.exports = { const current = stack.getCurrent(); if (current && !current.valid) { - context.report({ node, message: "Unexpected 'this'." }); + context.report({ + node, + messageId: "unexpectedThis" + }); } } }; diff --git a/tools/node_modules/eslint/lib/rules/no-irregular-whitespace.js b/tools/node_modules/eslint/lib/rules/no-irregular-whitespace.js index f339fa6c8f34c9..21842331f21ff0 100644 --- a/tools/node_modules/eslint/lib/rules/no-irregular-whitespace.js +++ b/tools/node_modules/eslint/lib/rules/no-irregular-whitespace.js @@ -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 */ @@ -59,7 +59,11 @@ module.exports = { }, additionalProperties: false } - ] + ], + + messages: { + noIrregularWhitespace: "Irregular whitespace not allowed." + } }, create(context) { @@ -161,7 +165,11 @@ module.exports = { column: match.index }; - errors.push({ node, message: "Irregular whitespace not allowed.", loc: location }); + errors.push({ + node, + messageId: "noIrregularWhitespace", + loc: location + }); } }); } @@ -186,7 +194,11 @@ module.exports = { column: sourceLines[lineIndex].length }; - errors.push({ node, message: "Irregular whitespace not allowed.", loc: location }); + errors.push({ + node, + messageId: "noIrregularWhitespace", + loc: location + }); lastLineIndex = lineIndex; } } diff --git a/tools/node_modules/eslint/lib/rules/no-iterator.js b/tools/node_modules/eslint/lib/rules/no-iterator.js index 82319a3fb1dfb6..9ba1e7aefdbc3b 100644 --- a/tools/node_modules/eslint/lib/rules/no-iterator.js +++ b/tools/node_modules/eslint/lib/rules/no-iterator.js @@ -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-iterator" }, - schema: [] + schema: [], + + messages: { + noIterator: "Reserved name '__iterator__'." + } }, create(context) { @@ -29,10 +39,11 @@ 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__")) { - context.report({ node, message: "Reserved name '__iterator__'." }); + if (getStaticPropertyName(node) === "__iterator__") { + context.report({ + node, + messageId: "noIterator" + }); } } }; diff --git a/tools/node_modules/eslint/lib/rules/no-label-var.js b/tools/node_modules/eslint/lib/rules/no-label-var.js index a9fd042a390225..570db03285cf97 100644 --- a/tools/node_modules/eslint/lib/rules/no-label-var.js +++ b/tools/node_modules/eslint/lib/rules/no-label-var.js @@ -26,7 +26,11 @@ module.exports = { url: "https://eslint.org/docs/rules/no-label-var" }, - schema: [] + schema: [], + + messages: { + identifierClashWithLabel: "Found identifier with same name as label." + } }, create(context) { @@ -62,7 +66,10 @@ module.exports = { * with the innermost scope. */ if (findIdentifier(scope, node.label.name)) { - context.report({ node, message: "Found identifier with same name as label." }); + context.report({ + node, + messageId: "identifierClashWithLabel" + }); } } diff --git a/tools/node_modules/eslint/lib/rules/no-labels.js b/tools/node_modules/eslint/lib/rules/no-labels.js index 52f4b0f5168b71..85760d80dbedd7 100644 --- a/tools/node_modules/eslint/lib/rules/no-labels.js +++ b/tools/node_modules/eslint/lib/rules/no-labels.js @@ -40,7 +40,13 @@ module.exports = { }, additionalProperties: false } - ] + ], + + messages: { + unexpectedLabel: "Unexpected labeled statement.", + unexpectedLabelInBreak: "Unexpected label in break statement.", + unexpectedLabelInContinue: "Unexpected label in continue statement." + } }, create(context) { @@ -113,7 +119,7 @@ module.exports = { if (!isAllowed(scopeInfo.kind)) { context.report({ node, - message: "Unexpected labeled statement." + messageId: "unexpectedLabel" }); } @@ -124,7 +130,7 @@ module.exports = { if (node.label && !isAllowed(getKind(node.label.name))) { context.report({ node, - message: "Unexpected label in break statement." + messageId: "unexpectedLabelInBreak" }); } }, @@ -133,7 +139,7 @@ module.exports = { if (node.label && !isAllowed(getKind(node.label.name))) { context.report({ node, - message: "Unexpected label in continue statement." + messageId: "unexpectedLabelInContinue" }); } } diff --git a/tools/node_modules/eslint/lib/rules/no-lone-blocks.js b/tools/node_modules/eslint/lib/rules/no-lone-blocks.js index 37561b0f9a3055..d7069887b8e460 100644 --- a/tools/node_modules/eslint/lib/rules/no-lone-blocks.js +++ b/tools/node_modules/eslint/lib/rules/no-lone-blocks.js @@ -20,7 +20,12 @@ module.exports = { url: "https://eslint.org/docs/rules/no-lone-blocks" }, - schema: [] + schema: [], + + messages: { + redundantBlock: "Block is redundant.", + redundantNestedBlock: "Nested block is redundant." + } }, create(context) { @@ -35,9 +40,12 @@ module.exports = { * @returns {void} */ function report(node) { - const message = node.parent.type === "BlockStatement" ? "Nested block is redundant." : "Block is redundant."; + const messageId = node.parent.type === "BlockStatement" ? "redundantNestedBlock" : "redundantBlock"; - context.report({ node, message }); + context.report({ + node, + messageId + }); } /** diff --git a/tools/node_modules/eslint/lib/rules/no-lonely-if.js b/tools/node_modules/eslint/lib/rules/no-lonely-if.js index b62d176a264210..6552adc5752852 100644 --- a/tools/node_modules/eslint/lib/rules/no-lonely-if.js +++ b/tools/node_modules/eslint/lib/rules/no-lonely-if.js @@ -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"; @@ -20,7 +20,11 @@ module.exports = { }, schema: [], - fixable: "code" + fixable: "code", + + messages: { + unexpectedLonelyIf: "Unexpected if as the only statement in an else block." + } }, create(context) { @@ -38,7 +42,7 @@ module.exports = { parent === grandparent.alternate) { context.report({ node, - message: "Unexpected if as the only statement in an else block.", + messageId: "unexpectedLonelyIf", fix(fixer) { const openingElseCurly = sourceCode.getFirstToken(parent); const closingElseCurly = sourceCode.getLastToken(parent); diff --git a/tools/node_modules/eslint/lib/rules/no-magic-numbers.js b/tools/node_modules/eslint/lib/rules/no-magic-numbers.js index 0909e3166d952e..5dd6feaab0dbff 100644 --- a/tools/node_modules/eslint/lib/rules/no-magic-numbers.js +++ b/tools/node_modules/eslint/lib/rules/no-magic-numbers.js @@ -5,10 +5,24 @@ "use strict"; +const { isNumericLiteral } = require("./utils/ast-utils"); + //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ +/** + * Convert the value to bigint if it's a string. Otherwise return the value as-is. + * @param {bigint|number|string} x The value to normalize. + * @returns {bigint|number} The normalized value. + */ +function normalizeIgnoreValue(x) { + if (typeof x === "string") { + return BigInt(x.slice(0, -1)); + } + return x; +} + module.exports = { meta: { type: "suggestion", @@ -34,7 +48,10 @@ module.exports = { ignore: { type: "array", items: { - type: "number" + anyOf: [ + { type: "number" }, + { type: "string", pattern: "^[+-]?(?:0|[1-9][0-9]*)n$" } + ] }, uniqueItems: true }, @@ -56,18 +73,9 @@ module.exports = { const config = context.options[0] || {}, detectObjects = !!config.detectObjects, enforceConst = !!config.enforceConst, - ignore = config.ignore || [], + ignore = (config.ignore || []).map(normalizeIgnoreValue), ignoreArrayIndexes = !!config.ignoreArrayIndexes; - /** - * Returns whether the node is number literal - * @param {Node} node the node literal being evaluated - * @returns {boolean} true if the node is a number literal - */ - function isNumber(node) { - return typeof node.value === "number"; - } - /** * Returns whether the number should be ignored * @param {number} num the number @@ -102,18 +110,21 @@ 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 { Literal(node) { const okTypes = detectObjects ? [] : ["ObjectExpression", "Property", "AssignmentExpression"]; - if (!isNumber(node)) { + if (!isNumericLiteral(node)) { return; } @@ -137,7 +148,7 @@ module.exports = { if (shouldIgnoreNumber(value) || shouldIgnoreParseInt(parent, fullNumberNode) || - shouldIgnoreArrayIndexes(parent) || + shouldIgnoreArrayIndexes(fullNumberNode) || shouldIgnoreJSXNumbers(parent)) { return; } diff --git a/tools/node_modules/eslint/lib/rules/no-mixed-operators.js b/tools/node_modules/eslint/lib/rules/no-mixed-operators.js index 80fac79affdb0e..37e8906e827a4c 100644 --- a/tools/node_modules/eslint/lib/rules/no-mixed-operators.js +++ b/tools/node_modules/eslint/lib/rules/no-mixed-operators.js @@ -112,7 +112,11 @@ module.exports = { }, additionalProperties: false } - ] + ], + + messages: { + unexpectedMixedOperator: "Unexpected mix of '{{leftOperator}}' and '{{rightOperator}}'." + } }, create(context) { @@ -188,8 +192,6 @@ module.exports = { const parent = node.parent; const left = (getChildNode(parent) === node) ? node : parent; const right = (getChildNode(parent) !== node) ? node : parent; - const message = - "Unexpected mix of '{{leftOperator}}' and '{{rightOperator}}'."; const data = { leftOperator: left.operator || "?:", rightOperator: right.operator || "?:" @@ -198,13 +200,13 @@ module.exports = { context.report({ node: left, loc: getOperatorToken(left).loc, - message, + messageId: "unexpectedMixedOperator", data }); context.report({ node: right, loc: getOperatorToken(right).loc, - message, + messageId: "unexpectedMixedOperator", data }); } diff --git a/tools/node_modules/eslint/lib/rules/no-mixed-requires.js b/tools/node_modules/eslint/lib/rules/no-mixed-requires.js index fda8a11d9e2e74..8e988e32c24f84 100644 --- a/tools/node_modules/eslint/lib/rules/no-mixed-requires.js +++ b/tools/node_modules/eslint/lib/rules/no-mixed-requires.js @@ -40,7 +40,12 @@ module.exports = { } ] } - ] + ], + + messages: { + noMixRequire: "Do not mix 'require' and other declarations.", + noMixCoreModuleFileComputed: "Do not mix core, module, file and computed requires." + } }, create(context) { @@ -211,9 +216,15 @@ module.exports = { VariableDeclaration(node) { if (isMixed(node.declarations)) { - context.report({ node, message: "Do not mix 'require' and other declarations." }); + context.report({ + node, + messageId: "noMixRequire" + }); } else if (grouping && !isGrouped(node.declarations)) { - context.report({ node, message: "Do not mix core, module, file and computed requires." }); + context.report({ + node, + messageId: "noMixCoreModuleFileComputed" + }); } } }; diff --git a/tools/node_modules/eslint/lib/rules/no-mixed-spaces-and-tabs.js b/tools/node_modules/eslint/lib/rules/no-mixed-spaces-and-tabs.js index 7b1e2c4a2a760c..16c2bd4122e851 100644 --- a/tools/node_modules/eslint/lib/rules/no-mixed-spaces-and-tabs.js +++ b/tools/node_modules/eslint/lib/rules/no-mixed-spaces-and-tabs.js @@ -23,14 +23,17 @@ module.exports = { { enum: ["smart-tabs", true, false] } - ] + ], + + messages: { + mixedSpacesAndTabs: "Mixed spaces and tabs." + } }, create(context) { const sourceCode = context.getSourceCode(); let smartTabs; - const ignoredLocs = []; switch (context.options[0]) { case true: // Support old syntax, maybe add deprecation warning here @@ -41,47 +44,23 @@ module.exports = { smartTabs = false; } - /** - * Determines if a given line and column are before a location. - * @param {Location} loc The location object from an AST node. - * @param {int} line The line to check. - * @param {int} column The column to check. - * @returns {boolean} True if the line and column are before the location, false if not. - * @private - */ - function beforeLoc(loc, line, column) { - if (line < loc.start.line) { - return true; - } - return line === loc.start.line && column < loc.start.column; - } - - /** - * Determines if a given line and column are after a location. - * @param {Location} loc The location object from an AST node. - * @param {int} line The line to check. - * @param {int} column The column to check. - * @returns {boolean} True if the line and column are after the location, false if not. - * @private - */ - function afterLoc(loc, line, column) { - if (line > loc.end.line) { - return true; - } - return line === loc.end.line && column > loc.end.column; - } - //-------------------------------------------------------------------------- // Public //-------------------------------------------------------------------------- return { - TemplateElement(node) { - ignoredLocs.push(node.loc); - }, - "Program:exit"(node) { + const lines = sourceCode.lines, + comments = sourceCode.getAllComments(), + ignoredCommentLines = new Set(); + + // Add all lines except the first ones. + comments.forEach(comment => { + for (let i = comment.loc.start.line + 1; i <= comment.loc.end.line; i++) { + ignoredCommentLines.add(i); + } + }); /* * At least one space followed by a tab @@ -89,24 +68,6 @@ module.exports = { * characters begin. */ let regex = /^(?=[\t ]*(\t | \t))/u; - const lines = sourceCode.lines, - comments = sourceCode.getAllComments(); - - comments.forEach(comment => { - ignoredLocs.push(comment.loc); - }); - - ignoredLocs.sort((first, second) => { - if (beforeLoc(first, second.start.line, second.start.column)) { - return 1; - } - - if (beforeLoc(second, first.start.line, second.start.column)) { - return -1; - } - - return 0; - }); if (smartTabs) { @@ -122,25 +83,23 @@ module.exports = { if (match) { const lineNumber = i + 1, - column = match.index + 1; - - for (let j = 0; j < ignoredLocs.length; j++) { - if (beforeLoc(ignoredLocs[j], lineNumber, column)) { - continue; + column = match.index + 1, + loc = { line: lineNumber, column }; + + if (!ignoredCommentLines.has(lineNumber)) { + const containingNode = sourceCode.getNodeByRangeIndex(sourceCode.getIndexFromLoc(loc)); + + if (!(containingNode && ["Literal", "TemplateElement"].includes(containingNode.type))) { + context.report({ + node, + loc, + messageId: "mixedSpacesAndTabs" + }); } - if (afterLoc(ignoredLocs[j], lineNumber, column)) { - continue; - } - - return; } - - context.report({ node, loc: { line: lineNumber, column }, message: "Mixed spaces and tabs." }); } }); } - }; - } }; diff --git a/tools/node_modules/eslint/lib/rules/no-multi-assign.js b/tools/node_modules/eslint/lib/rules/no-multi-assign.js index 8524a1a571ef9e..ab6430c19ef070 100644 --- a/tools/node_modules/eslint/lib/rules/no-multi-assign.js +++ b/tools/node_modules/eslint/lib/rules/no-multi-assign.js @@ -21,7 +21,11 @@ module.exports = { url: "https://eslint.org/docs/rules/no-multi-assign" }, - schema: [] + schema: [], + + messages: { + unexpectedChain: "Unexpected chained assignment." + } }, create(context) { @@ -35,7 +39,7 @@ module.exports = { if (["AssignmentExpression", "VariableDeclarator"].indexOf(node.parent.type) !== -1) { context.report({ node, - message: "Unexpected chained assignment." + messageId: "unexpectedChain" }); } } diff --git a/tools/node_modules/eslint/lib/rules/no-multi-spaces.js b/tools/node_modules/eslint/lib/rules/no-multi-spaces.js index 403d04da9dd9ec..d43ed736337945 100644 --- a/tools/node_modules/eslint/lib/rules/no-multi-spaces.js +++ b/tools/node_modules/eslint/lib/rules/no-multi-spaces.js @@ -44,7 +44,11 @@ module.exports = { }, additionalProperties: false } - ] + ], + + messages: { + multipleSpaces: "Multiple spaces found before '{{displayValue}}'." + } }, create(context) { @@ -122,7 +126,7 @@ module.exports = { context.report({ node: rightToken, loc: { start: leftToken.loc.end, end: rightToken.loc.start }, - message: "Multiple spaces found before '{{displayValue}}'.", + messageId: "multipleSpaces", data: { displayValue }, fix: fixer => fixer.replaceTextRange([leftToken.range[1], rightToken.range[0]], " ") }); diff --git a/tools/node_modules/eslint/lib/rules/no-multi-str.js b/tools/node_modules/eslint/lib/rules/no-multi-str.js index f6832f3341777f..7cf1ae367942fe 100644 --- a/tools/node_modules/eslint/lib/rules/no-multi-str.js +++ b/tools/node_modules/eslint/lib/rules/no-multi-str.js @@ -26,7 +26,11 @@ module.exports = { url: "https://eslint.org/docs/rules/no-multi-str" }, - schema: [] + schema: [], + + messages: { + multilineString: "Multiline support is limited to browsers supporting ES5 only." + } }, create(context) { @@ -49,7 +53,10 @@ module.exports = { Literal(node) { if (astUtils.LINEBREAK_MATCHER.test(node.raw) && !isJSXElement(node.parent)) { - context.report({ node, message: "Multiline support is limited to browsers supporting ES5 only." }); + context.report({ + node, + messageId: "multilineString" + }); } } }; diff --git a/tools/node_modules/eslint/lib/rules/no-multiple-empty-lines.js b/tools/node_modules/eslint/lib/rules/no-multiple-empty-lines.js index 41e6be3a289584..9cccef3088a56e 100644 --- a/tools/node_modules/eslint/lib/rules/no-multiple-empty-lines.js +++ b/tools/node_modules/eslint/lib/rules/no-multiple-empty-lines.js @@ -42,7 +42,13 @@ module.exports = { required: ["max"], additionalProperties: false } - ] + ], + + messages: { + blankBeginningOfFile: "Too many blank lines at the beginning of file. Max of {{max}} allowed.", + blankEndOfFile: "Too many blank lines at the end of file. Max of {{max}} allowed.", + consecutiveBlank: "More than {{max}} blank {{pluralizedLines}} not allowed." + } }, create(context) { @@ -94,25 +100,31 @@ module.exports = { // Given two line numbers of non-empty lines, report the lines between if the difference is too large. .reduce((lastLineNumber, lineNumber) => { - let message, maxAllowed; + let messageId, maxAllowed; if (lastLineNumber === 0) { - message = "Too many blank lines at the beginning of file. Max of {{max}} allowed."; + messageId = "blankBeginningOfFile"; maxAllowed = maxBOF; } else if (lineNumber === allLines.length + 1) { - message = "Too many blank lines at the end of file. Max of {{max}} allowed."; + messageId = "blankEndOfFile"; maxAllowed = maxEOF; } else { - message = "More than {{max}} blank {{pluralizedLines}} not allowed."; + messageId = "consecutiveBlank"; maxAllowed = max; } if (lineNumber - lastLineNumber - 1 > maxAllowed) { context.report({ node, - loc: { start: { line: lastLineNumber + maxAllowed + 1, column: 0 }, end: { line: lineNumber, column: 0 } }, - message, - data: { max: maxAllowed, pluralizedLines: maxAllowed === 1 ? "line" : "lines" }, + loc: { + start: { line: lastLineNumber + maxAllowed + 1, column: 0 }, + end: { line: lineNumber, column: 0 } + }, + messageId, + data: { + max: maxAllowed, + pluralizedLines: maxAllowed === 1 ? "line" : "lines" + }, fix(fixer) { const rangeStart = sourceCode.getIndexFromLoc({ line: lastLineNumber + 1, column: 0 }); diff --git a/tools/node_modules/eslint/lib/rules/no-native-reassign.js b/tools/node_modules/eslint/lib/rules/no-native-reassign.js index eb233c80b1cca0..833e3b7ce409b3 100644 --- a/tools/node_modules/eslint/lib/rules/no-native-reassign.js +++ b/tools/node_modules/eslint/lib/rules/no-native-reassign.js @@ -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 }); } diff --git a/tools/node_modules/eslint/lib/rules/no-negated-condition.js b/tools/node_modules/eslint/lib/rules/no-negated-condition.js index e55a8287487de3..8a9eba881df04c 100644 --- a/tools/node_modules/eslint/lib/rules/no-negated-condition.js +++ b/tools/node_modules/eslint/lib/rules/no-negated-condition.js @@ -19,7 +19,11 @@ module.exports = { url: "https://eslint.org/docs/rules/no-negated-condition" }, - schema: [] + schema: [], + + messages: { + unexpectedNegated: "Unexpected negated condition." + } }, create(context) { @@ -72,12 +76,18 @@ module.exports = { } if (isNegatedIf(node)) { - context.report({ node, message: "Unexpected negated condition." }); + context.report({ + node, + messageId: "unexpectedNegated" + }); } }, ConditionalExpression(node) { if (isNegatedIf(node)) { - context.report({ node, message: "Unexpected negated condition." }); + context.report({ + node, + messageId: "unexpectedNegated" + }); } } }; diff --git a/tools/node_modules/eslint/lib/rules/no-negated-in-lhs.js b/tools/node_modules/eslint/lib/rules/no-negated-in-lhs.js index 0084ad1570bb00..1229cedd1190dc 100644 --- a/tools/node_modules/eslint/lib/rules/no-negated-in-lhs.js +++ b/tools/node_modules/eslint/lib/rules/no-negated-in-lhs.js @@ -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" }); } } }; diff --git a/tools/node_modules/eslint/lib/rules/no-nested-ternary.js b/tools/node_modules/eslint/lib/rules/no-nested-ternary.js index 87a11e87962a8f..383bb238887d2a 100644 --- a/tools/node_modules/eslint/lib/rules/no-nested-ternary.js +++ b/tools/node_modules/eslint/lib/rules/no-nested-ternary.js @@ -20,7 +20,11 @@ module.exports = { url: "https://eslint.org/docs/rules/no-nested-ternary" }, - schema: [] + schema: [], + + messages: { + noNestedTernary: "Do not nest ternary expressions." + } }, create(context) { @@ -29,7 +33,10 @@ module.exports = { ConditionalExpression(node) { if (node.alternate.type === "ConditionalExpression" || node.consequent.type === "ConditionalExpression") { - context.report({ node, message: "Do not nest ternary expressions." }); + context.report({ + node, + messageId: "noNestedTernary" + }); } } }; diff --git a/tools/node_modules/eslint/lib/rules/no-new-func.js b/tools/node_modules/eslint/lib/rules/no-new-func.js index 23e92f7bf3030c..d1360e9dee036d 100644 --- a/tools/node_modules/eslint/lib/rules/no-new-func.js +++ b/tools/node_modules/eslint/lib/rules/no-new-func.js @@ -20,7 +20,11 @@ module.exports = { url: "https://eslint.org/docs/rules/no-new-func" }, - schema: [] + schema: [], + + messages: { + noFunctionConstructor: "The Function constructor is eval." + } }, create(context) { @@ -36,7 +40,10 @@ module.exports = { * @private */ function report(node) { - context.report({ node, message: "The Function constructor is eval." }); + context.report({ + node, + messageId: "noFunctionConstructor" + }); } return { diff --git a/tools/node_modules/eslint/lib/rules/no-new-object.js b/tools/node_modules/eslint/lib/rules/no-new-object.js index f5cc28664f4e1c..f3e99c9bd13502 100644 --- a/tools/node_modules/eslint/lib/rules/no-new-object.js +++ b/tools/node_modules/eslint/lib/rules/no-new-object.js @@ -20,7 +20,11 @@ module.exports = { url: "https://eslint.org/docs/rules/no-new-object" }, - schema: [] + schema: [], + + messages: { + preferLiteral: "The object literal notation {} is preferrable." + } }, create(context) { @@ -29,7 +33,10 @@ module.exports = { NewExpression(node) { if (node.callee.name === "Object") { - context.report({ node, message: "The object literal notation {} is preferrable." }); + context.report({ + node, + messageId: "preferLiteral" + }); } } }; diff --git a/tools/node_modules/eslint/lib/rules/no-new-require.js b/tools/node_modules/eslint/lib/rules/no-new-require.js index 1eae0659430fbd..df12a424e3527e 100644 --- a/tools/node_modules/eslint/lib/rules/no-new-require.js +++ b/tools/node_modules/eslint/lib/rules/no-new-require.js @@ -20,7 +20,11 @@ module.exports = { url: "https://eslint.org/docs/rules/no-new-require" }, - schema: [] + schema: [], + + messages: { + noNewRequire: "Unexpected use of new with require." + } }, create(context) { @@ -29,7 +33,10 @@ module.exports = { NewExpression(node) { if (node.callee.type === "Identifier" && node.callee.name === "require") { - context.report({ node, message: "Unexpected use of new with require." }); + context.report({ + node, + messageId: "noNewRequire" + }); } } }; diff --git a/tools/node_modules/eslint/lib/rules/no-new-symbol.js b/tools/node_modules/eslint/lib/rules/no-new-symbol.js index ccf757ed6a0cee..cb7e4f0fc88d69 100644 --- a/tools/node_modules/eslint/lib/rules/no-new-symbol.js +++ b/tools/node_modules/eslint/lib/rules/no-new-symbol.js @@ -20,7 +20,11 @@ module.exports = { url: "https://eslint.org/docs/rules/no-new-symbol" }, - schema: [] + schema: [], + + messages: { + noNewSymbol: "`Symbol` cannot be called as a constructor." + } }, create(context) { @@ -35,7 +39,10 @@ module.exports = { const node = ref.identifier; if (node.parent && node.parent.type === "NewExpression") { - context.report({ node, message: "`Symbol` cannot be called as a constructor." }); + context.report({ + node, + messageId: "noNewSymbol" + }); } }); } diff --git a/tools/node_modules/eslint/lib/rules/no-new-wrappers.js b/tools/node_modules/eslint/lib/rules/no-new-wrappers.js index ae2aeec0341243..0a2861fa5f7799 100644 --- a/tools/node_modules/eslint/lib/rules/no-new-wrappers.js +++ b/tools/node_modules/eslint/lib/rules/no-new-wrappers.js @@ -20,7 +20,11 @@ module.exports = { url: "https://eslint.org/docs/rules/no-new-wrappers" }, - schema: [] + schema: [], + + messages: { + noConstructor: "Do not use {{fn}} as a constructor." + } }, create(context) { @@ -31,7 +35,11 @@ module.exports = { const wrapperObjects = ["String", "Number", "Boolean", "Math", "JSON"]; if (wrapperObjects.indexOf(node.callee.name) > -1) { - context.report({ node, message: "Do not use {{fn}} as a constructor.", data: { fn: node.callee.name } }); + context.report({ + node, + messageId: "noConstructor", + data: { fn: node.callee.name } + }); } } }; diff --git a/tools/node_modules/eslint/lib/rules/no-new.js b/tools/node_modules/eslint/lib/rules/no-new.js index 2e0702597eade3..aa8a4e26876609 100644 --- a/tools/node_modules/eslint/lib/rules/no-new.js +++ b/tools/node_modules/eslint/lib/rules/no-new.js @@ -21,14 +21,21 @@ module.exports = { url: "https://eslint.org/docs/rules/no-new" }, - schema: [] + schema: [], + + messages: { + noNewStatement: "Do not use 'new' for side effects." + } }, create(context) { return { "ExpressionStatement > NewExpression"(node) { - context.report({ node: node.parent, message: "Do not use 'new' for side effects." }); + context.report({ + node: node.parent, + messageId: "noNewStatement" + }); } }; diff --git a/tools/node_modules/eslint/lib/rules/no-obj-calls.js b/tools/node_modules/eslint/lib/rules/no-obj-calls.js index 5102d5594949ba..9ff666b03281ca 100644 --- a/tools/node_modules/eslint/lib/rules/no-obj-calls.js +++ b/tools/node_modules/eslint/lib/rules/no-obj-calls.js @@ -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 }; } diff --git a/tools/node_modules/eslint/lib/rules/no-octal.js b/tools/node_modules/eslint/lib/rules/no-octal.js index 5ee69f0309ee03..e9940befafa889 100644 --- a/tools/node_modules/eslint/lib/rules/no-octal.js +++ b/tools/node_modules/eslint/lib/rules/no-octal.js @@ -20,7 +20,11 @@ module.exports = { url: "https://eslint.org/docs/rules/no-octal" }, - schema: [] + schema: [], + + messages: { + noOcatal: "Octal literals should not be used." + } }, create(context) { @@ -29,7 +33,10 @@ module.exports = { Literal(node) { if (typeof node.value === "number" && /^0[0-9]/u.test(node.raw)) { - context.report({ node, message: "Octal literals should not be used." }); + context.report({ + node, + messageId: "noOcatal" + }); } } }; diff --git a/tools/node_modules/eslint/lib/rules/no-param-reassign.js b/tools/node_modules/eslint/lib/rules/no-param-reassign.js index d65eb34762aaf2..6874af44f389b7 100644 --- a/tools/node_modules/eslint/lib/rules/no-param-reassign.js +++ b/tools/node_modules/eslint/lib/rules/no-param-reassign.js @@ -58,7 +58,12 @@ module.exports = { } ] } - ] + ], + + messages: { + assignmentToFunctionParam: "Assignment to function parameter '{{name}}'.", + assignmentToFunctionParamProp: "Assignment to property of function parameter '{{name}}'." + } }, create(context) { @@ -177,9 +182,17 @@ module.exports = { (index === 0 || references[index - 1].identifier !== identifier) ) { if (reference.isWrite()) { - context.report({ node: identifier, message: "Assignment to function parameter '{{name}}'.", data: { name: identifier.name } }); + context.report({ + node: identifier, + messageId: "assignmentToFunctionParam", + data: { name: identifier.name } + }); } else if (props && isModifyingProp(reference) && !isIgnoredPropertyAssignment(identifier.name)) { - context.report({ node: identifier, message: "Assignment to property of function parameter '{{name}}'.", data: { name: identifier.name } }); + context.report({ + node: identifier, + messageId: "assignmentToFunctionParamProp", + data: { name: identifier.name } + }); } } } diff --git a/tools/node_modules/eslint/lib/rules/no-path-concat.js b/tools/node_modules/eslint/lib/rules/no-path-concat.js index abe0d5247db719..9fa8b852fe8358 100644 --- a/tools/node_modules/eslint/lib/rules/no-path-concat.js +++ b/tools/node_modules/eslint/lib/rules/no-path-concat.js @@ -19,7 +19,11 @@ module.exports = { url: "https://eslint.org/docs/rules/no-path-concat" }, - schema: [] + schema: [], + + messages: { + usePathFunctions: "Use path.join() or path.resolve() instead of + to create paths." + } }, create(context) { @@ -42,7 +46,10 @@ module.exports = { (right.type === "Identifier" && MATCHER.test(right.name))) ) { - context.report({ node, message: "Use path.join() or path.resolve() instead of + to create paths." }); + context.report({ + node, + messageId: "usePathFunctions" + }); } } diff --git a/tools/node_modules/eslint/lib/rules/no-plusplus.js b/tools/node_modules/eslint/lib/rules/no-plusplus.js index 1d122dcd31f086..f55303863d25ca 100644 --- a/tools/node_modules/eslint/lib/rules/no-plusplus.js +++ b/tools/node_modules/eslint/lib/rules/no-plusplus.js @@ -32,7 +32,11 @@ module.exports = { }, additionalProperties: false } - ] + ], + + messages: { + unexpectedUnaryOp: "Unary operator '{{operator}}' used." + } }, create(context) { @@ -52,7 +56,7 @@ module.exports = { } context.report({ node, - message: "Unary operator '{{operator}}' used.", + messageId: "unexpectedUnaryOp", data: { operator: node.operator } diff --git a/tools/node_modules/eslint/lib/rules/no-process-env.js b/tools/node_modules/eslint/lib/rules/no-process-env.js index a66d9709b09b4f..0f8d7f8a339d0e 100644 --- a/tools/node_modules/eslint/lib/rules/no-process-env.js +++ b/tools/node_modules/eslint/lib/rules/no-process-env.js @@ -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" }); } } diff --git a/tools/node_modules/eslint/lib/rules/no-process-exit.js b/tools/node_modules/eslint/lib/rules/no-process-exit.js index fcfc6b2af59d0e..29871660cc6ee1 100644 --- a/tools/node_modules/eslint/lib/rules/no-process-exit.js +++ b/tools/node_modules/eslint/lib/rules/no-process-exit.js @@ -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" }); } }; diff --git a/tools/node_modules/eslint/lib/rules/no-proto.js b/tools/node_modules/eslint/lib/rules/no-proto.js index 80b9650941696d..82ce02fa4e3b9e 100644 --- a/tools/node_modules/eslint/lib/rules/no-proto.js +++ b/tools/node_modules/eslint/lib/rules/no-proto.js @@ -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" }); } } }; diff --git a/tools/node_modules/eslint/lib/rules/no-prototype-builtins.js b/tools/node_modules/eslint/lib/rules/no-prototype-builtins.js index 87a760156e3693..5bed2539a6486b 100644 --- a/tools/node_modules/eslint/lib/rules/no-prototype-builtins.js +++ b/tools/node_modules/eslint/lib/rules/no-prototype-builtins.js @@ -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 diff --git a/tools/node_modules/eslint/lib/rules/no-regex-spaces.js b/tools/node_modules/eslint/lib/rules/no-regex-spaces.js index 7581e9271fdf14..afb26d70259f1b 100644 --- a/tools/node_modules/eslint/lib/rules/no-regex-spaces.js +++ b/tools/node_modules/eslint/lib/rules/no-regex-spaces.js @@ -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; } } diff --git a/tools/node_modules/eslint/lib/rules/no-restricted-exports.js b/tools/node_modules/eslint/lib/rules/no-restricted-exports.js new file mode 100644 index 00000000000000..5b5c7d9bffb99c --- /dev/null +++ b/tools/node_modules/eslint/lib/rules/no-restricted-exports.js @@ -0,0 +1,84 @@ +/** + * @fileoverview Rule to disallow specified names in exports + * @author Milos Djermanovic + */ + +"use strict"; + +//------------------------------------------------------------------------------ +// Rule Definition +//------------------------------------------------------------------------------ + +module.exports = { + meta: { + type: "suggestion", + + docs: { + description: "disallow specified names in exports", + category: "ECMAScript 6", + recommended: false, + url: "https://eslint.org/docs/rules/no-restricted-exports" + }, + + schema: [{ + type: "object", + properties: { + restrictedNamedExports: { + type: "array", + items: { + type: "string" + }, + uniqueItems: true + } + }, + additionalProperties: false + }], + + messages: { + restrictedNamed: "'{{name}}' is restricted from being used as an exported name." + } + }, + + create(context) { + + const restrictedNames = new Set(context.options[0] && context.options[0].restrictedNamedExports); + + /** + * Checks and reports given exported identifier. + * @param {ASTNode} node exported `Identifer` node to check. + * @returns {void} + */ + function checkExportedName(node) { + const name = node.name; + + if (restrictedNames.has(name)) { + context.report({ + node, + messageId: "restrictedNamed", + data: { name } + }); + } + } + + return { + ExportNamedDeclaration(node) { + const declaration = node.declaration; + + if (declaration) { + if (declaration.type === "FunctionDeclaration" || declaration.type === "ClassDeclaration") { + checkExportedName(declaration.id); + } else if (declaration.type === "VariableDeclaration") { + context.getDeclaredVariables(declaration) + .map(v => v.defs.find(d => d.parent === declaration)) + .map(d => d.name) // Identifier nodes + .forEach(checkExportedName); + } + } else { + node.specifiers + .map(s => s.exported) + .forEach(checkExportedName); + } + } + }; + } +}; diff --git a/tools/node_modules/eslint/lib/rules/no-restricted-globals.js b/tools/node_modules/eslint/lib/rules/no-restricted-globals.js index 1a2629a8ec95e8..2c932a7307c0b2 100644 --- a/tools/node_modules/eslint/lib/rules/no-restricted-globals.js +++ b/tools/node_modules/eslint/lib/rules/no-restricted-globals.js @@ -4,13 +4,6 @@ */ "use strict"; -//------------------------------------------------------------------------------ -// Helpers -//------------------------------------------------------------------------------ - -const DEFAULT_MESSAGE_TEMPLATE = "Unexpected use of '{{name}}'.", - CUSTOM_MESSAGE_TEMPLATE = "Unexpected use of '{{name}}'. {{customMessage}}"; - //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ @@ -46,6 +39,12 @@ module.exports = { }, uniqueItems: true, minItems: 0 + }, + + messages: { + defaultMessage: "Unexpected use of '{{name}}'.", + // eslint-disable-next-line eslint-plugin/report-message-format + customMessage: "Unexpected use of '{{name}}'. {{customMessage}}" } }, @@ -75,13 +74,13 @@ module.exports = { function reportReference(reference) { const name = reference.identifier.name, customMessage = restrictedGlobalMessages[name], - message = customMessage - ? CUSTOM_MESSAGE_TEMPLATE - : DEFAULT_MESSAGE_TEMPLATE; + messageId = customMessage + ? "customMessage" + : "defaultMessage"; context.report({ node: reference.identifier, - message, + messageId, data: { name, customMessage diff --git a/tools/node_modules/eslint/lib/rules/no-restricted-imports.js b/tools/node_modules/eslint/lib/rules/no-restricted-imports.js index ec0696f99a2de0..c205dad8bdb79d 100644 --- a/tools/node_modules/eslint/lib/rules/no-restricted-imports.js +++ b/tools/node_modules/eslint/lib/rules/no-restricted-imports.js @@ -64,7 +64,11 @@ module.exports = { everything: "* import is invalid because '{{importNames}}' from '{{importSource}}' is restricted.", // eslint-disable-next-line eslint-plugin/report-message-format - everythingWithCustomMessage: "* import is invalid because '{{importNames}}' from '{{importSource}}' is restricted. {{customMessage}}" + everythingWithCustomMessage: "* import is invalid because '{{importNames}}' from '{{importSource}}' is restricted. {{customMessage}}", + + importName: "'{{importName}}' import from '{{importSource}}' is restricted.", + // eslint-disable-next-line eslint-plugin/report-message-format + importNameWithCustomMessage: "'{{importName}}' import from '{{importSource}}' is restricted. {{customMessage}}" }, schema: { @@ -87,6 +91,7 @@ module.exports = { }, create(context) { + const sourceCode = context.getSourceCode(); const options = Array.isArray(context.options) ? context.options : []; const isPathAndPatternsObject = typeof options[0] === "object" && @@ -95,6 +100,11 @@ module.exports = { const restrictedPaths = (isPathAndPatternsObject ? options[0].paths : context.options) || []; const restrictedPatterns = (isPathAndPatternsObject ? options[0].patterns : []) || []; + // if no imports are restricted we don"t need to check + if (Object.keys(restrictedPaths).length === 0 && restrictedPatterns.length === 0) { + return {}; + } + const restrictedPathMessages = restrictedPaths.reduce((memo, importSource) => { if (typeof importSource === "string") { memo[importSource] = { message: null }; @@ -107,40 +117,68 @@ module.exports = { return memo; }, {}); - // if no imports are restricted we don"t need to check - if (Object.keys(restrictedPaths).length === 0 && restrictedPatterns.length === 0) { - return {}; - } - const restrictedPatternsMatcher = ignore().add(restrictedPatterns); - /** - * Checks to see if "*" is being used to import everything. - * @param {Set.} importNames Set of import names that are being imported - * @returns {boolean} whether everything is imported or not - */ - function isEverythingImported(importNames) { - return importNames.has("*"); - } - /** * Report a restricted path. + * @param {string} importSource path of the import + * @param {Map} importNames Map of import names that are being imported * @param {node} node representing the restricted path reference * @returns {void} * @private */ - function reportPath(node) { - const importSource = node.source.value.trim(); - const customMessage = restrictedPathMessages[importSource] && restrictedPathMessages[importSource].message; + function checkRestrictedPathAndReport(importSource, importNames, node) { + if (!Object.prototype.hasOwnProperty.call(restrictedPathMessages, importSource)) { + return; + } - context.report({ - node, - messageId: customMessage ? "pathWithCustomMessage" : "path", - data: { - importSource, - customMessage + const customMessage = restrictedPathMessages[importSource].message; + const restrictedImportNames = restrictedPathMessages[importSource].importNames; + + if (restrictedImportNames) { + if (importNames.has("*")) { + const specifierData = importNames.get("*")[0]; + + context.report({ + node, + messageId: customMessage ? "everythingWithCustomMessage" : "everything", + loc: specifierData.loc, + data: { + importSource, + importNames: restrictedImportNames, + customMessage + } + }); } - }); + + restrictedImportNames.forEach(importName => { + if (importNames.has(importName)) { + const specifiers = importNames.get(importName); + + specifiers.forEach(specifier => { + context.report({ + node, + messageId: customMessage ? "importNameWithCustomMessage" : "importName", + loc: specifier.loc, + data: { + importSource, + customMessage, + importName + } + }); + }); + } + }); + } else { + context.report({ + node, + messageId: customMessage ? "pathWithCustomMessage" : "path", + data: { + importSource, + customMessage + } + }); + } } /** @@ -161,75 +199,6 @@ module.exports = { }); } - /** - * Report a restricted path specifically when using the '*' import. - * @param {string} importSource path of the import - * @param {node} node representing the restricted path reference - * @returns {void} - * @private - */ - function reportPathForEverythingImported(importSource, node) { - const importNames = restrictedPathMessages[importSource].importNames; - const customMessage = restrictedPathMessages[importSource] && restrictedPathMessages[importSource].message; - - context.report({ - node, - messageId: customMessage ? "everythingWithCustomMessage" : "everything", - data: { - importSource, - importNames, - customMessage - } - }); - } - - /** - * Check if the given importSource is restricted because '*' is being imported. - * @param {string} importSource path of the import - * @param {Set.} importNames Set of import names that are being imported - * @returns {boolean} whether the path is restricted - * @private - */ - function isRestrictedForEverythingImported(importSource, importNames) { - return Object.prototype.hasOwnProperty.call(restrictedPathMessages, importSource) && - restrictedPathMessages[importSource].importNames && - isEverythingImported(importNames); - } - - /** - * Check if the given importNames are restricted given a list of restrictedImportNames. - * @param {Set.} importNames Set of import names that are being imported - * @param {string[]} restrictedImportNames array of import names that are restricted for this import - * @returns {boolean} whether the objectName is restricted - * @private - */ - function isRestrictedObject(importNames, restrictedImportNames) { - return restrictedImportNames.some(restrictedObjectName => ( - importNames.has(restrictedObjectName) - )); - } - - /** - * Check if the given importSource is a restricted path. - * @param {string} importSource path of the import - * @param {Set.} importNames Set of import names that are being imported - * @returns {boolean} whether the variable is a restricted path or not - * @private - */ - function isRestrictedPath(importSource, importNames) { - let isRestricted = false; - - if (Object.prototype.hasOwnProperty.call(restrictedPathMessages, importSource)) { - if (restrictedPathMessages[importSource].importNames) { - isRestricted = isRestrictedObject(importNames, restrictedPathMessages[importSource].importNames); - } else { - isRestricted = true; - } - } - - return isRestricted; - } - /** * Check if the given importSource is restricted by a pattern. * @param {string} importSource path of the import @@ -248,26 +217,39 @@ module.exports = { */ function checkNode(node) { const importSource = node.source.value.trim(); - const importNames = node.specifiers ? node.specifiers.reduce((set, specifier) => { - if (specifier.type === "ImportDefaultSpecifier") { - set.add("default"); - } else if (specifier.type === "ImportNamespaceSpecifier") { - set.add("*"); - } else if (specifier.imported) { - set.add(specifier.imported.name); - } else if (specifier.local) { - set.add(specifier.local.name); - } - return set; - }, new Set()) : new Set(); + const importNames = new Map(); + + if (node.type === "ExportAllDeclaration") { + const starToken = sourceCode.getFirstToken(node, 1); + + importNames.set("*", [{ loc: starToken.loc }]); + } else if (node.specifiers) { + for (const specifier of node.specifiers) { + let name; + const specifierData = { loc: specifier.loc }; + + if (specifier.type === "ImportDefaultSpecifier") { + name = "default"; + } else if (specifier.type === "ImportNamespaceSpecifier") { + name = "*"; + } else if (specifier.imported) { + name = specifier.imported.name; + } else if (specifier.local) { + name = specifier.local.name; + } - if (isRestrictedForEverythingImported(importSource, importNames)) { - reportPathForEverythingImported(importSource, node); + if (name) { + if (importNames.has(name)) { + importNames.get(name).push(specifierData); + } else { + importNames.set(name, [specifierData]); + } + } + } } - if (isRestrictedPath(importSource, importNames)) { - reportPath(node); - } + checkRestrictedPathAndReport(importSource, importNames, node); + if (isRestrictedPattern(importSource)) { reportPathForPatterns(node); } diff --git a/tools/node_modules/eslint/lib/rules/no-restricted-modules.js b/tools/node_modules/eslint/lib/rules/no-restricted-modules.js index ef8748a7d04baf..abd8d5cbe29381 100644 --- a/tools/node_modules/eslint/lib/rules/no-restricted-modules.js +++ b/tools/node_modules/eslint/lib/rules/no-restricted-modules.js @@ -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." } }, @@ -106,10 +106,19 @@ module.exports = { * @param {ASTNode} node The node to check. * @returns {boolean} If the node is a string literal. */ - function isString(node) { + function isStringLiteral(node) { return node && node.type === "Literal" && typeof node.value === "string"; } + /** + * Function to check if a node is a static string template literal. + * @param {ASTNode} node The node to check. + * @returns {boolean} If the node is a string template literal. + */ + function isStaticTemplateLiteral(node) { + return node && node.type === "TemplateLiteral" && node.expressions.length === 0; + } + /** * Function to check if a node is a require call. * @param {ASTNode} node The node to check. @@ -119,24 +128,41 @@ module.exports = { return node.callee.type === "Identifier" && node.callee.name === "require"; } + /** + * Extract string from Literal or TemplateLiteral node + * @param {ASTNode} node The node to extract from + * @returns {string|null} Extracted string or null if node doesn't represent a string + */ + function getFirstArgumentString(node) { + if (isStringLiteral(node)) { + return node.value.trim(); + } + + if (isStaticTemplateLiteral(node)) { + return node.quasis[0].value.cooked.trim(); + } + + return null; + } + /** * Report a restricted path. * @param {node} node representing the restricted path reference + * @param {string} name restricted path * @returns {void} * @private */ - function reportPath(node) { - const moduleName = node.arguments[0].value.trim(); - const customMessage = restrictedPathMessages[moduleName]; - const message = customMessage - ? CUSTOM_MESSAGE_TEMPLATE - : DEFAULT_MESSAGE_TEMPLATE; + function reportPath(node, name) { + const customMessage = restrictedPathMessages[name]; + const messageId = customMessage + ? "customMessage" + : "defaultMessage"; context.report({ node, - message, + messageId, data: { - moduleName, + name, customMessage } }); @@ -156,21 +182,25 @@ module.exports = { CallExpression(node) { if (isRequireCall(node)) { - // node has arguments and first argument is string - if (node.arguments.length && isString(node.arguments[0])) { - const moduleName = node.arguments[0].value.trim(); - - // check if argument value is in restricted modules array - if (isRestrictedPath(moduleName)) { - reportPath(node); - } - - if (restrictedPatterns.length > 0 && ig.ignores(moduleName)) { - context.report({ - node, - message: "'{{moduleName}}' module is restricted from being used by a pattern.", - data: { moduleName } - }); + // node has arguments + if (node.arguments.length) { + const name = getFirstArgumentString(node.arguments[0]); + + // if first argument is a string literal or a static string template literal + if (name) { + + // check if argument value is in restricted modules array + if (isRestrictedPath(name)) { + reportPath(node, name); + } + + if (restrictedPatterns.length > 0 && ig.ignores(name)) { + context.report({ + node, + messageId: "patternMessage", + data: { name } + }); + } } } } diff --git a/tools/node_modules/eslint/lib/rules/no-restricted-properties.js b/tools/node_modules/eslint/lib/rules/no-restricted-properties.js index bdab22b19c4edc..7ab83995a3ebbf 100644 --- a/tools/node_modules/eslint/lib/rules/no-restricted-properties.js +++ b/tools/node_modules/eslint/lib/rules/no-restricted-properties.js @@ -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 diff --git a/tools/node_modules/eslint/lib/rules/no-restricted-syntax.js b/tools/node_modules/eslint/lib/rules/no-restricted-syntax.js index 41aa9fa390a88d..9572603a82485a 100644 --- a/tools/node_modules/eslint/lib/rules/no-restricted-syntax.js +++ b/tools/node_modules/eslint/lib/rules/no-restricted-syntax.js @@ -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 } }); } }); diff --git a/tools/node_modules/eslint/lib/rules/no-return-assign.js b/tools/node_modules/eslint/lib/rules/no-return-assign.js index ea6a6bb49fcf6d..4b57d42eb9952b 100644 --- a/tools/node_modules/eslint/lib/rules/no-return-assign.js +++ b/tools/node_modules/eslint/lib/rules/no-return-assign.js @@ -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" }); } } diff --git a/tools/node_modules/eslint/lib/rules/no-return-await.js b/tools/node_modules/eslint/lib/rules/no-return-await.js index 6652b5932dc1b8..d1d89826856dc4 100644 --- a/tools/node_modules/eslint/lib/rules/no-return-await.js +++ b/tools/node_modules/eslint/lib/rules/no-return-await.js @@ -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" }); } diff --git a/tools/node_modules/eslint/lib/rules/no-script-url.js b/tools/node_modules/eslint/lib/rules/no-script-url.js index 40e9bfe8b27544..2078fc1dcea122 100644 --- a/tools/node_modules/eslint/lib/rules/no-script-url.js +++ b/tools/node_modules/eslint/lib/rules/no-script-url.js @@ -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" }); } } } diff --git a/tools/node_modules/eslint/lib/rules/no-self-assign.js b/tools/node_modules/eslint/lib/rules/no-self-assign.js index 705d0f409c4128..170e46b05930d1 100644 --- a/tools/node_modules/eslint/lib/rules/no-self-assign.js +++ b/tools/node_modules/eslint/lib/rules/no-self-assign.js @@ -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, "") } diff --git a/tools/node_modules/eslint/lib/rules/no-self-compare.js b/tools/node_modules/eslint/lib/rules/no-self-compare.js index 8986240ec5c842..79b6ac7ea0f28d 100644 --- a/tools/node_modules/eslint/lib/rules/no-self-compare.js +++ b/tools/node_modules/eslint/lib/rules/no-self-compare.js @@ -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" }); } } }; diff --git a/tools/node_modules/eslint/lib/rules/no-sequences.js b/tools/node_modules/eslint/lib/rules/no-sequences.js index 8046a8711a3e9a..d67635d117549e 100644 --- a/tools/node_modules/eslint/lib/rules/no-sequences.js +++ b/tools/node_modules/eslint/lib/rules/no-sequences.js @@ -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" }); } }; diff --git a/tools/node_modules/eslint/lib/rules/no-setter-return.js b/tools/node_modules/eslint/lib/rules/no-setter-return.js index e0948696c347f5..a558640c357d92 100644 --- a/tools/node_modules/eslint/lib/rules/no-setter-return.js +++ b/tools/node_modules/eslint/lib/rules/no-setter-return.js @@ -145,7 +145,7 @@ module.exports = { docs: { description: "disallow returning values from setters", category: "Possible Errors", - recommended: false, + recommended: true, url: "https://eslint.org/docs/rules/no-setter-return" }, diff --git a/tools/node_modules/eslint/lib/rules/no-shadow-restricted-names.js b/tools/node_modules/eslint/lib/rules/no-shadow-restricted-names.js index 9030d523b705d2..9647e9a1bcdd9e 100644 --- a/tools/node_modules/eslint/lib/rules/no-shadow-restricted-names.js +++ b/tools/node_modules/eslint/lib/rules/no-shadow-restricted-names.js @@ -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 } }); } diff --git a/tools/node_modules/eslint/lib/rules/no-shadow.js b/tools/node_modules/eslint/lib/rules/no-shadow.js index bad6cb5f3094cc..1be8590e47abcb 100644 --- a/tools/node_modules/eslint/lib/rules/no-shadow.js +++ b/tools/node_modules/eslint/lib/rules/no-shadow.js @@ -41,7 +41,11 @@ module.exports = { }, additionalProperties: false } - ] + ], + + messages: { + noShadow: "'{{name}}' is already declared in the upper scope." + } }, create(context) { @@ -163,7 +167,7 @@ module.exports = { ) { context.report({ node: variable.identifiers[0], - message: "'{{name}}' is already declared in the upper scope.", + messageId: "noShadow", data: variable }); } diff --git a/tools/node_modules/eslint/lib/rules/no-spaced-func.js b/tools/node_modules/eslint/lib/rules/no-spaced-func.js index 8535881f435e48..961bc681f7eac5 100644 --- a/tools/node_modules/eslint/lib/rules/no-spaced-func.js +++ b/tools/node_modules/eslint/lib/rules/no-spaced-func.js @@ -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]]); } diff --git a/tools/node_modules/eslint/lib/rules/no-sparse-arrays.js b/tools/node_modules/eslint/lib/rules/no-sparse-arrays.js index 985109c36b267d..e8407c3faede2d 100644 --- a/tools/node_modules/eslint/lib/rules/no-sparse-arrays.js +++ b/tools/node_modules/eslint/lib/rules/no-sparse-arrays.js @@ -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" }); } } diff --git a/tools/node_modules/eslint/lib/rules/no-sync.js b/tools/node_modules/eslint/lib/rules/no-sync.js index 578bac96d3d061..d8111059631734 100644 --- a/tools/node_modules/eslint/lib/rules/no-sync.js +++ b/tools/node_modules/eslint/lib/rules/no-sync.js @@ -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 } diff --git a/tools/node_modules/eslint/lib/rules/no-tabs.js b/tools/node_modules/eslint/lib/rules/no-tabs.js index 3fc0b78b6e741c..ca7be261653c02 100644 --- a/tools/node_modules/eslint/lib/rules/no-tabs.js +++ b/tools/node_modules/eslint/lib/rules/no-tabs.js @@ -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" }); } }); diff --git a/tools/node_modules/eslint/lib/rules/no-template-curly-in-string.js b/tools/node_modules/eslint/lib/rules/no-template-curly-in-string.js index f7822e961cc1e7..539cd5be5ff9c5 100644 --- a/tools/node_modules/eslint/lib/rules/no-template-curly-in-string.js +++ b/tools/node_modules/eslint/lib/rules/no-template-curly-in-string.js @@ -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" }); } } diff --git a/tools/node_modules/eslint/lib/rules/no-ternary.js b/tools/node_modules/eslint/lib/rules/no-ternary.js index 890f2abfa0c59a..b3ced86056614c 100644 --- a/tools/node_modules/eslint/lib/rules/no-ternary.js +++ b/tools/node_modules/eslint/lib/rules/no-ternary.js @@ -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" }); } }; diff --git a/tools/node_modules/eslint/lib/rules/no-this-before-super.js b/tools/node_modules/eslint/lib/rules/no-this-before-super.js index 6975ea060bf00d..44288c0c97136e 100644 --- a/tools/node_modules/eslint/lib/rules/no-this-before-super.js +++ b/tools/node_modules/eslint/lib/rules/no-this-before-super.js @@ -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" diff --git a/tools/node_modules/eslint/lib/rules/no-trailing-spaces.js b/tools/node_modules/eslint/lib/rules/no-trailing-spaces.js index 3a4124f4c0f7a4..98ae62c896359c 100644 --- a/tools/node_modules/eslint/lib/rules/no-trailing-spaces.js +++ b/tools/node_modules/eslint/lib/rules/no-trailing-spaces.js @@ -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); } diff --git a/tools/node_modules/eslint/lib/rules/no-undef-init.js b/tools/node_modules/eslint/lib/rules/no-undef-init.js index 1fdccb867b3c24..5c240fef742b83 100644 --- a/tools/node_modules/eslint/lib/rules/no-undef-init.js +++ b/tools/node_modules/eslint/lib/rules/no-undef-init.js @@ -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") { diff --git a/tools/node_modules/eslint/lib/rules/no-undefined.js b/tools/node_modules/eslint/lib/rules/no-undefined.js index b92f6700637c30..a075d903e21e98 100644 --- a/tools/node_modules/eslint/lib/rules/no-undefined.js +++ b/tools/node_modules/eslint/lib/rules/no-undefined.js @@ -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" }); } diff --git a/tools/node_modules/eslint/lib/rules/no-underscore-dangle.js b/tools/node_modules/eslint/lib/rules/no-underscore-dangle.js index e910e2739a740a..cac594e10047e8 100644 --- a/tools/node_modules/eslint/lib/rules/no-underscore-dangle.js +++ b/tools/node_modules/eslint/lib/rules/no-underscore-dangle.js @@ -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 } @@ -201,10 +205,10 @@ module.exports = { const identifier = node.key.name; const isMethod = node.type === "MethodDefinition" || node.type === "Property" && node.method; - if (typeof identifier !== "undefined" && enforceInMethodNames && isMethod && hasTrailingUnderscore(identifier)) { + if (typeof identifier !== "undefined" && enforceInMethodNames && isMethod && hasTrailingUnderscore(identifier) && !isAllowed(identifier)) { context.report({ node, - message: "Unexpected dangling '_' in '{{identifier}}'.", + messageId: "unexpectedUnderscore", data: { identifier } diff --git a/tools/node_modules/eslint/lib/rules/no-unmodified-loop-condition.js b/tools/node_modules/eslint/lib/rules/no-unmodified-loop-condition.js index 3b8e7417d5b586..7031a4dd8b83fc 100644 --- a/tools/node_modules/eslint/lib/rules/no-unmodified-loop-condition.js +++ b/tools/node_modules/eslint/lib/rules/no-unmodified-loop-condition.js @@ -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 }); } diff --git a/tools/node_modules/eslint/lib/rules/no-unneeded-ternary.js b/tools/node_modules/eslint/lib/rules/no-unneeded-ternary.js index 893baa34f74917..d4438e2fe08fbe 100644 --- a/tools/node_modules/eslint/lib/rules/no-unneeded-ternary.js +++ b/tools/node_modules/eslint/lib/rules/no-unneeded-ternary.js @@ -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 && diff --git a/tools/node_modules/eslint/lib/rules/no-unreachable.js b/tools/node_modules/eslint/lib/rules/no-unreachable.js index 91c4ca7150903f..415631a6f7d726 100644 --- a/tools/node_modules/eslint/lib/rules/no-unreachable.js +++ b/tools/node_modules/eslint/lib/rules/no-unreachable.js @@ -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 }); diff --git a/tools/node_modules/eslint/lib/rules/no-unsafe-finally.js b/tools/node_modules/eslint/lib/rules/no-unsafe-finally.js index a41dff9c80372f..11bf06e872a813 100644 --- a/tools/node_modules/eslint/lib/rules/no-unsafe-finally.js +++ b/tools/node_modules/eslint/lib/rules/no-unsafe-finally.js @@ -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 }, diff --git a/tools/node_modules/eslint/lib/rules/no-unused-expressions.js b/tools/node_modules/eslint/lib/rules/no-unused-expressions.js index fd0440256be016..26a25b7584bc80 100644 --- a/tools/node_modules/eslint/lib/rules/no-unused-expressions.js +++ b/tools/node_modules/eslint/lib/rules/no-unused-expressions.js @@ -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" }); } } }; diff --git a/tools/node_modules/eslint/lib/rules/no-unused-vars.js b/tools/node_modules/eslint/lib/rules/no-unused-vars.js index 63e6e048ef1e46..18c48bf0d7810c 100644 --- a/tools/node_modules/eslint/lib/rules/no-unused-vars.js +++ b/tools/node_modules/eslint/lib/rules/no-unused-vars.js @@ -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()}.` : ""; - - return `'{{name}}' is assigned a value but never used.${additional}`; + function getAssignedMessageData(unusedVar) { + const additional = config.varsIgnorePattern ? `. Allowed unused vars must match ${config.varsIgnorePattern.toString()}` : ""; + + 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) }); } } diff --git a/tools/node_modules/eslint/lib/rules/no-use-before-define.js b/tools/node_modules/eslint/lib/rules/no-use-before-define.js index ed3540532f9095..c7300567ede0b7 100644 --- a/tools/node_modules/eslint/lib/rules/no-use-before-define.js +++ b/tools/node_modules/eslint/lib/rules/no-use-before-define.js @@ -157,7 +157,11 @@ module.exports = { } ] } - ] + ], + + messages: { + usedBeforeDefined: "'{{name}}' was used before it was defined." + } }, create(context) { @@ -212,7 +216,7 @@ module.exports = { // Reports. context.report({ node: reference.identifier, - message: "'{{name}}' was used before it was defined.", + messageId: "usedBeforeDefined", data: reference.identifier }); }); diff --git a/tools/node_modules/eslint/lib/rules/no-useless-backreference.js b/tools/node_modules/eslint/lib/rules/no-useless-backreference.js new file mode 100644 index 00000000000000..8a6fbe14daafe6 --- /dev/null +++ b/tools/node_modules/eslint/lib/rules/no-useless-backreference.js @@ -0,0 +1,193 @@ +/** + * @fileoverview Rule to disallow useless backreferences in regular expressions + * @author Milos Djermanovic + */ + +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const { CALL, CONSTRUCT, ReferenceTracker, getStringIfConstant } = require("eslint-utils"); +const { RegExpParser, visitRegExpAST } = require("regexpp"); +const lodash = require("lodash"); + +//------------------------------------------------------------------------------ +// Helpers +//------------------------------------------------------------------------------ + +const parser = new RegExpParser(); + +/** + * Finds the path from the given `regexpp` AST node to the root node. + * @param {regexpp.Node} node Node. + * @returns {regexpp.Node[]} Array that starts with the given node and ends with the root node. + */ +function getPathToRoot(node) { + const path = []; + let current = node; + + do { + path.push(current); + current = current.parent; + } while (current); + + return path; +} + +/** + * Determines whether the given `regexpp` AST node is a lookaround node. + * @param {regexpp.Node} node Node. + * @returns {boolean} `true` if it is a lookaround node. + */ +function isLookaround(node) { + return node.type === "Assertion" && + (node.kind === "lookahead" || node.kind === "lookbehind"); +} + +/** + * Determines whether the given `regexpp` AST node is a negative lookaround node. + * @param {regexpp.Node} node Node. + * @returns {boolean} `true` if it is a negative lookaround node. + */ +function isNegativeLookaround(node) { + return isLookaround(node) && node.negate; +} + +//------------------------------------------------------------------------------ +// Rule Definition +//------------------------------------------------------------------------------ + +module.exports = { + meta: { + type: "problem", + + docs: { + description: "disallow useless backreferences in regular expressions", + category: "Possible Errors", + recommended: false, + url: "https://eslint.org/docs/rules/no-useless-backreference" + }, + + schema: [], + + messages: { + nested: "Backreference '{{ bref }}' will be ignored. It references group '{{ group }}' from within that group.", + forward: "Backreference '{{ bref }}' will be ignored. It references group '{{ group }}' which appears later in the pattern.", + backward: "Backreference '{{ bref }}' will be ignored. It references group '{{ group }}' which appears before in the same lookbehind.", + disjunctive: "Backreference '{{ bref }}' will be ignored. It references group '{{ group }}' which is in another alternative.", + intoNegativeLookaround: "Backreference '{{ bref }}' will be ignored. It references group '{{ group }}' which is in a negative lookaround." + } + }, + + create(context) { + + /** + * Checks and reports useless backreferences in the given regular expression. + * @param {ASTNode} node Node that represents regular expression. A regex literal or RegExp constructor call. + * @param {string} pattern Regular expression pattern. + * @param {string} flags Regular expression flags. + * @returns {void} + */ + function checkRegex(node, pattern, flags) { + let regExpAST; + + try { + regExpAST = parser.parsePattern(pattern, 0, pattern.length, flags.includes("u")); + } catch (e) { + + // Ignore regular expressions with syntax errors + return; + } + + visitRegExpAST(regExpAST, { + onBackreferenceEnter(bref) { + const group = bref.resolved, + brefPath = getPathToRoot(bref), + groupPath = getPathToRoot(group); + let messageId = null; + + if (brefPath.includes(group)) { + + // group is bref's ancestor => bref is nested ('nested reference') => group hasn't matched yet when bref starts to match. + messageId = "nested"; + } else { + + // Start from the root to find the lowest common ancestor. + let i = brefPath.length - 1, + j = groupPath.length - 1; + + do { + i--; + j--; + } while (brefPath[i] === groupPath[j]); + + const indexOfLowestCommonAncestor = j + 1, + groupCut = groupPath.slice(0, indexOfLowestCommonAncestor), + commonPath = groupPath.slice(indexOfLowestCommonAncestor), + lowestCommonLookaround = commonPath.find(isLookaround), + isMatchingBackward = lowestCommonLookaround && lowestCommonLookaround.kind === "lookbehind"; + + if (!isMatchingBackward && bref.end <= group.start) { + + // bref is left, group is right ('forward reference') => group hasn't matched yet when bref starts to match. + messageId = "forward"; + } else if (isMatchingBackward && group.end <= bref.start) { + + // the opposite of the previous when the regex is matching backward in a lookbehind context. + messageId = "backward"; + } else if (lodash.last(groupCut).type === "Alternative") { + + // group's and bref's ancestor nodes below the lowest common ancestor are sibling alternatives => they're disjunctive. + messageId = "disjunctive"; + } else if (groupCut.some(isNegativeLookaround)) { + + // group is in a negative lookaround which isn't bref's ancestor => group has already failed when bref starts to match. + messageId = "intoNegativeLookaround"; + } + } + + if (messageId) { + context.report({ + node, + messageId, + data: { + bref: bref.raw, + group: group.raw + } + }); + } + } + }); + } + + return { + "Literal[regex]"(node) { + const { pattern, flags } = node.regex; + + checkRegex(node, pattern, flags); + }, + Program() { + const scope = context.getScope(), + tracker = new ReferenceTracker(scope), + traceMap = { + RegExp: { + [CALL]: true, + [CONSTRUCT]: true + } + }; + + for (const { node } of tracker.iterateGlobalReferences(traceMap)) { + const [patternNode, flagsNode] = node.arguments, + pattern = getStringIfConstant(patternNode, scope), + flags = getStringIfConstant(flagsNode, scope); + + if (typeof pattern === "string") { + checkRegex(node, pattern, flags || ""); + } + } + } + }; + } +}; diff --git a/tools/node_modules/eslint/lib/rules/no-useless-call.js b/tools/node_modules/eslint/lib/rules/no-useless-call.js index 11cf524d124211..afc729d5de0d9b 100644 --- a/tools/node_modules/eslint/lib/rules/no-useless-call.js +++ b/tools/node_modules/eslint/lib/rules/no-useless-call.js @@ -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 } }); } } }; diff --git a/tools/node_modules/eslint/lib/rules/no-useless-catch.js b/tools/node_modules/eslint/lib/rules/no-useless-catch.js index 37bf453aecd932..f303c272948489 100644 --- a/tools/node_modules/eslint/lib/rules/no-useless-catch.js +++ b/tools/node_modules/eslint/lib/rules/no-useless-catch.js @@ -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" }); } } diff --git a/tools/node_modules/eslint/lib/rules/no-useless-computed-key.js b/tools/node_modules/eslint/lib/rules/no-useless-computed-key.js index b5e53174e42be7..e0505a318efaae 100644 --- a/tools/node_modules/eslint/lib/rules/no-useless-computed-key.js +++ b/tools/node_modules/eslint/lib/rules/no-useless-computed-key.js @@ -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,17 +70,14 @@ 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.getFirstToken(node, astUtils.isOpeningBracketToken); - const rightSquareBracket = sourceCode.getFirstTokenBetween(node.key, node.value, astUtils.isClosingBracketToken); - const tokensBetween = sourceCode.getTokensBetween(leftSquareBracket, rightSquareBracket, 1); - - if (tokensBetween.slice(0, -1).some((token, index) => - sourceCode.getText().slice(token.range[1], tokensBetween[index + 1].range[0]).trim())) { + const leftSquareBracket = sourceCode.getTokenBefore(key, astUtils.isOpeningBracketToken); + const rightSquareBracket = sourceCode.getTokenAfter(key, astUtils.isClosingBracketToken); - // If there are comments between the brackets and the property name, don't do a fix. + // If there are comments between the brackets and the property name, don't do a fix. + if (sourceCode.commentsExistBetween(leftSquareBracket, rightSquareBracket)) { return null; } diff --git a/tools/node_modules/eslint/lib/rules/no-useless-concat.js b/tools/node_modules/eslint/lib/rules/no-useless-concat.js index cdaca273eb003f..aa46742abdd5ca 100644 --- a/tools/node_modules/eslint/lib/rules/no-useless-concat.js +++ b/tools/node_modules/eslint/lib/rules/no-useless-concat.js @@ -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" }); } } diff --git a/tools/node_modules/eslint/lib/rules/no-useless-constructor.js b/tools/node_modules/eslint/lib/rules/no-useless-constructor.js index 7cf033805f99d9..4c34aeda715937 100644 --- a/tools/node_modules/eslint/lib/rules/no-useless-constructor.js +++ b/tools/node_modules/eslint/lib/rules/no-useless-constructor.js @@ -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 ( @@ -143,7 +143,11 @@ module.exports = { url: "https://eslint.org/docs/rules/no-useless-constructor" }, - schema: [] + schema: [], + + messages: { + noUselessConstructor: "Useless constructor." + } }, create(context) { @@ -165,7 +169,7 @@ module.exports = { if (superClass ? isRedundantSuperCall(body, ctorParams) : (body.length === 0)) { context.report({ node, - message: "Useless constructor." + messageId: "noUselessConstructor" }); } } diff --git a/tools/node_modules/eslint/lib/rules/no-useless-rename.js b/tools/node_modules/eslint/lib/rules/no-useless-rename.js index eb570a3ef5c1d3..fa88f37f50b79c 100644 --- a/tools/node_modules/eslint/lib/rules/no-useless-rename.js +++ b/tools/node_modules/eslint/lib/rules/no-useless-rename.js @@ -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 diff --git a/tools/node_modules/eslint/lib/rules/no-useless-return.js b/tools/node_modules/eslint/lib/rules/no-useless-return.js index 942d4eede9964e..111cb21015fb81 100644 --- a/tools/node_modules/eslint/lib/rules/no-useless-return.js +++ b/tools/node_modules/eslint/lib/rules/no-useless-return.js @@ -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) { diff --git a/tools/node_modules/eslint/lib/rules/no-var.js b/tools/node_modules/eslint/lib/rules/no-var.js index 74203f8bf3bebf..f2cb96b1f708e9 100644 --- a/tools/node_modules/eslint/lib/rules/no-var.js +++ b/tools/node_modules/eslint/lib/rules/no-var.js @@ -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" }); diff --git a/tools/node_modules/eslint/lib/rules/no-void.js b/tools/node_modules/eslint/lib/rules/no-void.js index d2b5d2f9631dff..99c83785552ab8 100644 --- a/tools/node_modules/eslint/lib/rules/no-void.js +++ b/tools/node_modules/eslint/lib/rules/no-void.js @@ -19,22 +19,46 @@ module.exports = { url: "https://eslint.org/docs/rules/no-void" }, - schema: [] + messages: { + noVoid: "Expected 'undefined' and instead saw 'void'." + }, + + schema: [ + { + type: "object", + properties: { + allowAsStatement: { + type: "boolean", + default: false + } + }, + additionalProperties: false + } + ] }, create(context) { + const allowAsStatement = + context.options[0] && context.options[0].allowAsStatement; //-------------------------------------------------------------------------- // Public //-------------------------------------------------------------------------- return { - UnaryExpression(node) { - if (node.operator === "void") { - context.report({ node, message: "Expected 'undefined' and instead saw 'void'." }); + 'UnaryExpression[operator="void"]'(node) { + if ( + allowAsStatement && + node.parent && + node.parent.type === "ExpressionStatement" + ) { + return; } + context.report({ + node, + messageId: "noVoid" + }); } }; - } }; diff --git a/tools/node_modules/eslint/lib/rules/no-warning-comments.js b/tools/node_modules/eslint/lib/rules/no-warning-comments.js index a400c446767ff7..d70bd5dd5c4002 100644 --- a/tools/node_modules/eslint/lib/rules/no-warning-comments.js +++ b/tools/node_modules/eslint/lib/rules/no-warning-comments.js @@ -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 } diff --git a/tools/node_modules/eslint/lib/rules/no-whitespace-before-property.js b/tools/node_modules/eslint/lib/rules/no-whitespace-before-property.js index 9541401a3176b7..ccd0b091b744e3 100644 --- a/tools/node_modules/eslint/lib/rules/no-whitespace-before-property.js +++ b/tools/node_modules/eslint/lib/rules/no-whitespace-before-property.js @@ -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) }, diff --git a/tools/node_modules/eslint/lib/rules/no-with.js b/tools/node_modules/eslint/lib/rules/no-with.js index 5763661584c061..d3e52e02f3d15a 100644 --- a/tools/node_modules/eslint/lib/rules/no-with.js +++ b/tools/node_modules/eslint/lib/rules/no-with.js @@ -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" }); } }; diff --git a/tools/node_modules/eslint/lib/rules/nonblock-statement-body-position.js b/tools/node_modules/eslint/lib/rules/nonblock-statement-body-position.js index 01763cea92f381..34e6eeac39de50 100644 --- a/tools/node_modules/eslint/lib/rules/nonblock-statement-body-position.js +++ b/tools/node_modules/eslint/lib/rules/nonblock-statement-body-position.js @@ -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; diff --git a/tools/node_modules/eslint/lib/rules/object-curly-newline.js b/tools/node_modules/eslint/lib/rules/object-curly-newline.js index e870a69a954180..b48b2526a0b2bd 100644 --- a/tools/node_modules/eslint/lib/rules/object-curly-newline.js +++ b/tools/node_modules/eslint/lib/rules/object-curly-newline.js @@ -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) { diff --git a/tools/node_modules/eslint/lib/rules/object-curly-spacing.js b/tools/node_modules/eslint/lib/rules/object-curly-spacing.js index 117a7a35426103..c0044f5033c005 100644 --- a/tools/node_modules/eslint/lib/rules/object-curly-spacing.js +++ b/tools/node_modules/eslint/lib/rules/object-curly-spacing.js @@ -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 }, diff --git a/tools/node_modules/eslint/lib/rules/object-property-newline.js b/tools/node_modules/eslint/lib/rules/object-property-newline.js index bf777b5ff65ba2..074bc775ae35a3 100644 --- a/tools/node_modules/eslint/lib/rules/object-property-newline.js +++ b/tools/node_modules/eslint/lib/rules/object-property-newline.js @@ -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]]; diff --git a/tools/node_modules/eslint/lib/rules/object-shorthand.js b/tools/node_modules/eslint/lib/rules/object-shorthand.js index d4afd09c5a52c4..3999ff8b99fb29 100644 --- a/tools/node_modules/eslint/lib/rules/object-shorthand.js +++ b/tools/node_modules/eslint/lib/rules/object-shorthand.js @@ -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); } diff --git a/tools/node_modules/eslint/lib/rules/one-var-declaration-per-line.js b/tools/node_modules/eslint/lib/rules/one-var-declaration-per-line.js index b64656eefed0a9..30ca2cf49834fe 100644 --- a/tools/node_modules/eslint/lib/rules/one-var-declaration-per-line.js +++ b/tools/node_modules/eslint/lib/rules/one-var-declaration-per-line.js @@ -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") }); diff --git a/tools/node_modules/eslint/lib/rules/one-var.js b/tools/node_modules/eslint/lib/rules/one-var.js index e79461ce46c5be..c31a0d2b13c187 100644 --- a/tools/node_modules/eslint/lib/rules/one-var.js +++ b/tools/node_modules/eslint/lib/rules/one-var.js @@ -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 }, diff --git a/tools/node_modules/eslint/lib/rules/operator-assignment.js b/tools/node_modules/eslint/lib/rules/operator-assignment.js index b19ba0d02e1a1b..c4c8671f327a93 100644 --- a/tools/node_modules/eslint/lib/rules/operator-assignment.js +++ b/tools/node_modules/eslint/lib/rules/operator-assignment.js @@ -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 } diff --git a/tools/node_modules/eslint/lib/rules/operator-linebreak.js b/tools/node_modules/eslint/lib/rules/operator-linebreak.js index bce0ef56a0cc6c..c2fddcffd25c7f 100644 --- a/tools/node_modules/eslint/lib/rules/operator-linebreak.js +++ b/tools/node_modules/eslint/lib/rules/operator-linebreak.js @@ -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 }, diff --git a/tools/node_modules/eslint/lib/rules/padded-blocks.js b/tools/node_modules/eslint/lib/rules/padded-blocks.js index dafa88115edd78..f58a7535ba86c2 100644 --- a/tools/node_modules/eslint/lib/rules/padded-blocks.js +++ b/tools/node_modules/eslint/lib/rules/padded-blocks.js @@ -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"); } diff --git a/tools/node_modules/eslint/lib/rules/padding-line-between-statements.js b/tools/node_modules/eslint/lib/rules/padding-line-between-statements.js index 350a9dbf2aba15..eea19f5ce5811b 100644 --- a/tools/node_modules/eslint/lib/rules/padding-line-between-statements.js +++ b/tools/node_modules/eslint/lib/rules/padding-line-between-statements.js @@ -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." } }, diff --git a/tools/node_modules/eslint/lib/rules/prefer-arrow-callback.js b/tools/node_modules/eslint/lib/rules/prefer-arrow-callback.js index 08126e5b1a5459..d4e0251940c503 100644 --- a/tools/node_modules/eslint/lib/rules/prefer-arrow-callback.js +++ b/tools/node_modules/eslint/lib/rules/prefer-arrow-callback.js @@ -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)) { diff --git a/tools/node_modules/eslint/lib/rules/prefer-destructuring.js b/tools/node_modules/eslint/lib/rules/prefer-destructuring.js index eff37294a9b6ef..1a51956dde53ff 100644 --- a/tools/node_modules/eslint/lib/rules/prefer-destructuring.js +++ b/tools/node_modules/eslint/lib/rules/prefer-destructuring.js @@ -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 }); diff --git a/tools/node_modules/eslint/lib/rules/prefer-object-spread.js b/tools/node_modules/eslint/lib/rules/prefer-object-spread.js index bbcd88bee3d071..1344433f52fa93 100644 --- a/tools/node_modules/eslint/lib/rules/prefer-object-spread.js +++ b/tools/node_modules/eslint/lib/rules/prefer-object-spread.js @@ -25,6 +25,36 @@ function hasArraySpread(node) { return node.arguments.some(arg => arg.type === "SpreadElement"); } +/** + * Determines whether the given node is an accessor property (getter/setter). + * @param {ASTNode} node Node to check. + * @returns {boolean} `true` if the node is a getter or a setter. + */ +function isAccessorProperty(node) { + return node.type === "Property" && + (node.kind === "get" || node.kind === "set"); +} + +/** + * Determines whether the given object expression node has accessor properties (getters/setters). + * @param {ASTNode} node `ObjectExpression` node to check. + * @returns {boolean} `true` if the node has at least one getter/setter. + */ +function hasAccessors(node) { + return node.properties.some(isAccessorProperty); +} + +/** + * Determines whether the given call expression node has object expression arguments with accessor properties (getters/setters). + * @param {ASTNode} node `CallExpression` node to check. + * @returns {boolean} `true` if the node has at least one argument that is an object expression with at least one getter/setter. + */ +function hasArgumentsWithAccessors(node) { + return node.arguments + .filter(arg => arg.type === "ObjectExpression") + .some(hasAccessors); +} + /** * Helper that checks if the node needs parentheses to be valid JS. * The default is to wrap the node in parentheses to avoid parsing errors. @@ -68,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. @@ -249,7 +279,11 @@ module.exports = { if ( node.arguments.length >= 1 && node.arguments[0].type === "ObjectExpression" && - !hasArraySpread(node) + !hasArraySpread(node) && + !( + node.arguments.length > 1 && + hasArgumentsWithAccessors(node) + ) ) { const messageId = node.arguments.length === 1 ? "useLiteralMessage" diff --git a/tools/node_modules/eslint/lib/rules/prefer-promise-reject-errors.js b/tools/node_modules/eslint/lib/rules/prefer-promise-reject-errors.js index e142a96b55c78f..56911b67adcc99 100644 --- a/tools/node_modules/eslint/lib/rules/prefer-promise-reject-errors.js +++ b/tools/node_modules/eslint/lib/rules/prefer-promise-reject-errors.js @@ -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" }); } } diff --git a/tools/node_modules/eslint/lib/rules/prefer-reflect.js b/tools/node_modules/eslint/lib/rules/prefer-reflect.js index 796bbdf05fd446..fb2de923bea379 100644 --- a/tools/node_modules/eslint/lib/rules/prefer-reflect.js +++ b/tools/node_modules/eslint/lib/rules/prefer-reflect.js @@ -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) { diff --git a/tools/node_modules/eslint/lib/rules/prefer-rest-params.js b/tools/node_modules/eslint/lib/rules/prefer-rest-params.js index 3a28584f6bc126..3ecea732af8b94 100644 --- a/tools/node_modules/eslint/lib/rules/prefer-rest-params.js +++ b/tools/node_modules/eslint/lib/rules/prefer-rest-params.js @@ -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" }); } diff --git a/tools/node_modules/eslint/lib/rules/prefer-spread.js b/tools/node_modules/eslint/lib/rules/prefer-spread.js index 14c05bd97103de..bcb0dc0dd4c1a9 100644 --- a/tools/node_modules/eslint/lib/rules/prefer-spread.js +++ b/tools/node_modules/eslint/lib/rules/prefer-spread.js @@ -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" }); } } diff --git a/tools/node_modules/eslint/lib/rules/prefer-template.js b/tools/node_modules/eslint/lib/rules/prefer-template.js index fa6e58d9721e12..e8f980ebd38c6f 100644 --- a/tools/node_modules/eslint/lib/rules/prefer-template.js +++ b/tools/node_modules/eslint/lib/rules/prefer-template.js @@ -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) }); } diff --git a/tools/node_modules/eslint/lib/rules/quote-props.js b/tools/node_modules/eslint/lib/rules/quote-props.js index ab09b8fa938e63..a2a4e1d47923ff 100644 --- a/tools/node_modules/eslint/lib/rules/quote-props.js +++ b/tools/node_modules/eslint/lib/rules/quote-props.js @@ -8,8 +8,9 @@ // Requirements //------------------------------------------------------------------------------ -const espree = require("espree"), - keywords = require("./utils/keywords"); +const espree = require("espree"); +const astUtils = require("./utils/ast-utils"); +const keywords = require("./utils/keywords"); //------------------------------------------------------------------------------ // Rule Definition @@ -66,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) { @@ -76,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(); @@ -165,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)) }); @@ -173,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" && typeof key.value === "number") { + } 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)) }); @@ -198,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)) }); @@ -253,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)) }); }); @@ -261,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)) }); @@ -270,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)) }); diff --git a/tools/node_modules/eslint/lib/rules/quotes.js b/tools/node_modules/eslint/lib/rules/quotes.js index f78d1129425633..d1f4443b9033c9 100644 --- a/tools/node_modules/eslint/lib/rules/quotes.js +++ b/tools/node_modules/eslint/lib/rules/quotes.js @@ -110,7 +110,11 @@ module.exports = { } ] } - ] + ], + + messages: { + wrongQuotes: "Strings must use {{description}}." + } }, create(context) { @@ -273,7 +277,7 @@ module.exports = { if (!isValid) { context.report({ node, - message: "Strings must use {{description}}.", + messageId: "wrongQuotes", data: { description: settings.description }, @@ -304,7 +308,7 @@ module.exports = { context.report({ node, - message: "Strings must use {{description}}.", + messageId: "wrongQuotes", data: { description: settings.description }, diff --git a/tools/node_modules/eslint/lib/rules/radix.js b/tools/node_modules/eslint/lib/rules/radix.js index ed3c5cb66b8cdc..3903cb2a6a2b01 100644 --- a/tools/node_modules/eslint/lib/rules/radix.js +++ b/tools/node_modules/eslint/lib/rules/radix.js @@ -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; diff --git a/tools/node_modules/eslint/lib/rules/require-atomic-updates.js b/tools/node_modules/eslint/lib/rules/require-atomic-updates.js index bdd6d81ebc4758..4f6acceab804d1 100644 --- a/tools/node_modules/eslint/lib/rules/require-atomic-updates.js +++ b/tools/node_modules/eslint/lib/rules/require-atomic-updates.js @@ -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. diff --git a/tools/node_modules/eslint/lib/rules/require-await.js b/tools/node_modules/eslint/lib/rules/require-await.js index 22c111b6dc852e..274e241cfc7d5b 100644 --- a/tools/node_modules/eslint/lib/rules/require-await.js +++ b/tools/node_modules/eslint/lib/rules/require-await.js @@ -39,7 +39,11 @@ module.exports = { url: "https://eslint.org/docs/rules/require-await" }, - schema: [] + schema: [], + + messages: { + missingAwait: "{{name}} has no 'await' expression." + } }, create(context) { @@ -68,7 +72,7 @@ module.exports = { context.report({ node, loc: astUtils.getFunctionHeadLoc(node, sourceCode), - message: "{{name}} has no 'await' expression.", + messageId: "missingAwait", data: { name: capitalizeFirstLetter( astUtils.getFunctionNameWithKind(node) diff --git a/tools/node_modules/eslint/lib/rules/require-jsdoc.js b/tools/node_modules/eslint/lib/rules/require-jsdoc.js index 416a22ce6c4375..e581b2bee4646a 100644 --- a/tools/node_modules/eslint/lib/rules/require-jsdoc.js +++ b/tools/node_modules/eslint/lib/rules/require-jsdoc.js @@ -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" }); } /** diff --git a/tools/node_modules/eslint/lib/rules/require-yield.js b/tools/node_modules/eslint/lib/rules/require-yield.js index dbfd759948af78..af2344dfa6b8ff 100644 --- a/tools/node_modules/eslint/lib/rules/require-yield.js +++ b/tools/node_modules/eslint/lib/rules/require-yield.js @@ -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" }); } } diff --git a/tools/node_modules/eslint/lib/rules/rest-spread-spacing.js b/tools/node_modules/eslint/lib/rules/rest-spread-spacing.js index cd740fd3a99057..4bb5f787c6c568 100644 --- a/tools/node_modules/eslint/lib/rules/rest-spread-spacing.js +++ b/tools/node_modules/eslint/lib/rules/rest-spread-spacing.js @@ -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 }, diff --git a/tools/node_modules/eslint/lib/rules/semi-spacing.js b/tools/node_modules/eslint/lib/rules/semi-spacing.js index 083dc26199f7bd..92948533d2789e 100644 --- a/tools/node_modules/eslint/lib/rules/semi-spacing.js +++ b/tools/node_modules/eslint/lib/rules/semi-spacing.js @@ -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, " "); } diff --git a/tools/node_modules/eslint/lib/rules/semi-style.js b/tools/node_modules/eslint/lib/rules/semi-style.js index da3c4a38742b88..0c9bec4c85ede8 100644 --- a/tools/node_modules/eslint/lib/rules/semi-style.js +++ b/tools/node_modules/eslint/lib/rules/semi-style.js @@ -75,7 +75,11 @@ module.exports = { }, schema: [{ enum: ["last", "first"] }], - fixable: "whitespace" + fixable: "whitespace", + + messages: { + expectedSemiColon: "Expected this semicolon to be at {{pos}}." + } }, create(context) { @@ -97,7 +101,7 @@ module.exports = { if ((expected === "last" && !prevIsSameLine) || (expected === "first" && !nextIsSameLine)) { context.report({ loc: semiToken.loc, - message: "Expected this semicolon to be at {{pos}}.", + messageId: "expectedSemiColon", data: { pos: (expected === "last") ? "the end of the previous line" diff --git a/tools/node_modules/eslint/lib/rules/semi.js b/tools/node_modules/eslint/lib/rules/semi.js index 22e299efe72e49..d2f0670427b3ab 100644 --- a/tools/node_modules/eslint/lib/rules/semi.js +++ b/tools/node_modules/eslint/lib/rules/semi.js @@ -67,6 +67,11 @@ module.exports = { maxItems: 2 } ] + }, + + messages: { + missingSemi: "Missing semicolon.", + extraSemi: "Extra semicolon." } }, @@ -91,12 +96,12 @@ module.exports = { */ function report(node, missing) { const lastToken = sourceCode.getLastToken(node); - let message, + let messageId, fix, loc; if (!missing) { - message = "Missing semicolon."; + messageId = "missingSemi"; loc = { start: lastToken.loc.end, end: astUtils.getNextLocation(sourceCode, lastToken.loc.end) @@ -105,7 +110,7 @@ module.exports = { return fixer.insertTextAfter(lastToken, ";"); }; } else { - message = "Extra semicolon."; + messageId = "extraSemi"; loc = lastToken.loc; fix = function(fixer) { @@ -123,14 +128,14 @@ module.exports = { context.report({ node, loc, - message, + messageId, fix }); } /** - * Check whether a given semicolon token is redandant. + * Check whether a given semicolon token is redundant. * @param {Token} semiToken A semicolon token to check. * @returns {boolean} `true` if the next token is `;` or `}`. */ diff --git a/tools/node_modules/eslint/lib/rules/sort-imports.js b/tools/node_modules/eslint/lib/rules/sort-imports.js index 3b7f1d010348ad..65ad9a18a93112 100644 --- a/tools/node_modules/eslint/lib/rules/sort-imports.js +++ b/tools/node_modules/eslint/lib/rules/sort-imports.js @@ -50,7 +50,13 @@ module.exports = { } ], - fixable: "code" + fixable: "code", + + messages: { + sortImportsAlphabetically: "Imports should be sorted alphabetically.", + sortMembersAlphabetically: "Member '{{memberName}}' of the import declaration should be sorted alphabetically.", + unexpectedSyntaxOrder: "Expected '{{syntaxA}}' syntax before '{{syntaxB}}' syntax." + } }, create(context) { @@ -132,7 +138,7 @@ module.exports = { if (currentMemberSyntaxGroupIndex < previousMemberSyntaxGroupIndex) { context.report({ node, - message: "Expected '{{syntaxA}}' syntax before '{{syntaxB}}' syntax.", + messageId: "unexpectedSyntaxOrder", data: { syntaxA: memberSyntaxSortOrder[currentMemberSyntaxGroupIndex], syntaxB: memberSyntaxSortOrder[previousMemberSyntaxGroupIndex] @@ -146,7 +152,7 @@ module.exports = { ) { context.report({ node, - message: "Imports should be sorted alphabetically." + messageId: "sortImportsAlphabetically" }); } } @@ -163,7 +169,7 @@ module.exports = { if (firstUnsortedIndex !== -1) { context.report({ node: importSpecifiers[firstUnsortedIndex], - message: "Member '{{memberName}}' of the import declaration should be sorted alphabetically.", + messageId: "sortMembersAlphabetically", data: { memberName: importSpecifiers[firstUnsortedIndex].local.name }, fix(fixer) { if (importSpecifiers.some(specifier => diff --git a/tools/node_modules/eslint/lib/rules/sort-keys.js b/tools/node_modules/eslint/lib/rules/sort-keys.js index a5ce445f71ae93..8a95ee25d61948 100644 --- a/tools/node_modules/eslint/lib/rules/sort-keys.js +++ b/tools/node_modules/eslint/lib/rules/sort-keys.js @@ -41,7 +41,7 @@ function getPropertyName(node) { * Functions which check that the given 2 names are in specific order. * * Postfix `I` is meant insensitive. - * Postfix `N` is meant natual. + * Postfix `N` is meant natural. * @private */ const isValidOrders = { @@ -109,7 +109,11 @@ module.exports = { }, additionalProperties: false } - ] + ], + + messages: { + sortKeys: "Expected object keys to be in {{natural}}{{insensitive}}{{order}}ending order. '{{thisName}}' should be before '{{prevName}}'." + } }, create(context) { @@ -118,10 +122,10 @@ module.exports = { const order = context.options[0] || "asc"; const options = context.options[1]; const insensitive = options && options.caseSensitive === false; - const natual = options && options.natural; + const natural = options && options.natural; const minKeys = options && options.minKeys; const isValidOrder = isValidOrders[ - order + (insensitive ? "I" : "") + (natual ? "N" : "") + order + (insensitive ? "I" : "") + (natural ? "N" : "") ]; // The stack to save the previous property's name for each object literals. @@ -167,13 +171,13 @@ module.exports = { context.report({ node, loc: node.key.loc, - message: "Expected object keys to be in {{natual}}{{insensitive}}{{order}}ending order. '{{thisName}}' should be before '{{prevName}}'.", + messageId: "sortKeys", data: { thisName, prevName, order, insensitive: insensitive ? "insensitive " : "", - natual: natual ? "natural " : "" + natural: natural ? "natural " : "" } }); } diff --git a/tools/node_modules/eslint/lib/rules/sort-vars.js b/tools/node_modules/eslint/lib/rules/sort-vars.js index e85c6534e3a189..7add2cf74b2940 100644 --- a/tools/node_modules/eslint/lib/rules/sort-vars.js +++ b/tools/node_modules/eslint/lib/rules/sort-vars.js @@ -33,7 +33,11 @@ module.exports = { } ], - fixable: "code" + fixable: "code", + + messages: { + sortVars: "Variables within the same declaration block should be sorted alphabetically." + } }, create(context) { @@ -56,7 +60,7 @@ module.exports = { if (currentVariableName < lastVariableName) { context.report({ node: decl, - message: "Variables within the same declaration block should be sorted alphabetically.", + messageId: "sortVars", fix(fixer) { if (unfixable || fixed) { return null; diff --git a/tools/node_modules/eslint/lib/rules/space-before-blocks.js b/tools/node_modules/eslint/lib/rules/space-before-blocks.js index 038e88db5215f5..9b56481bf355fb 100644 --- a/tools/node_modules/eslint/lib/rules/space-before-blocks.js +++ b/tools/node_modules/eslint/lib/rules/space-before-blocks.js @@ -47,7 +47,12 @@ module.exports = { } ] } - ] + ], + + messages: { + unexpectedSpace: "Unexpected space before opening brace.", + missingSpace: "Missing space before opening brace." + } }, create(context) { @@ -114,7 +119,7 @@ module.exports = { if (requireSpace && !hasSpace) { context.report({ node, - message: "Missing space before opening brace.", + messageId: "missingSpace", fix(fixer) { return fixer.insertTextBefore(node, " "); } @@ -122,7 +127,7 @@ module.exports = { } else if (requireNoSpace && hasSpace) { context.report({ node, - message: "Unexpected space before opening brace.", + messageId: "unexpectedSpace", fix(fixer) { return fixer.removeRange([precedingToken.range[1], node.range[0]]); } diff --git a/tools/node_modules/eslint/lib/rules/space-before-function-paren.js b/tools/node_modules/eslint/lib/rules/space-before-function-paren.js index 3a6d430f362051..af609c2e7c72fa 100644 --- a/tools/node_modules/eslint/lib/rules/space-before-function-paren.js +++ b/tools/node_modules/eslint/lib/rules/space-before-function-paren.js @@ -50,7 +50,12 @@ module.exports = { } ] } - ] + ], + + messages: { + unexpectedSpace: "Unexpected space before function parentheses.", + missingSpace: "Missing space before function parentheses." + } }, create(context) { @@ -123,7 +128,7 @@ module.exports = { context.report({ node, loc: leftToken.loc.end, - message: "Unexpected space before function parentheses.", + messageId: "unexpectedSpace", fix(fixer) { const comments = sourceCode.getCommentsBefore(rightToken); @@ -141,7 +146,7 @@ module.exports = { context.report({ node, loc: leftToken.loc.end, - message: "Missing space before function parentheses.", + messageId: "missingSpace", fix: fixer => fixer.insertTextAfter(leftToken, " ") }); } diff --git a/tools/node_modules/eslint/lib/rules/space-in-parens.js b/tools/node_modules/eslint/lib/rules/space-in-parens.js index 85ee74210d6007..b0a604d955d788 100644 --- a/tools/node_modules/eslint/lib/rules/space-in-parens.js +++ b/tools/node_modules/eslint/lib/rules/space-in-parens.js @@ -169,7 +169,7 @@ module.exports = { } /** - * Determines if a closing paren is immediately preceeded by a required space + * Determines if a closing paren is immediately preceded by a required space * @param {Object} tokenBeforeClosingParen The token before the paren * @param {Object} closingParenToken The paren token * @returns {boolean} True if the closing paren is missing a required space @@ -190,7 +190,7 @@ module.exports = { } /** - * Determines if a closer paren is immediately preceeded by a disallowed space + * Determines if a closer paren is immediately preceded by a disallowed space * @param {Object} tokenBeforeClosingParen The token before the paren * @param {Object} closingParenToken The paren token * @returns {boolean} True if the closing paren has a disallowed space diff --git a/tools/node_modules/eslint/lib/rules/space-infix-ops.js b/tools/node_modules/eslint/lib/rules/space-infix-ops.js index bd2c0ae0e1d3b7..471c22210eb613 100644 --- a/tools/node_modules/eslint/lib/rules/space-infix-ops.js +++ b/tools/node_modules/eslint/lib/rules/space-infix-ops.js @@ -32,7 +32,11 @@ module.exports = { }, additionalProperties: false } - ] + ], + + messages: { + missingSpace: "Operator '{{operator}}' must be spaced." + } }, create(context) { @@ -70,7 +74,7 @@ module.exports = { context.report({ node: mainNode, loc: culpritToken.loc, - message: "Operator '{{operator}}' must be spaced.", + messageId: "missingSpace", data: { operator: culpritToken.value }, @@ -123,11 +127,11 @@ module.exports = { * @private */ function checkConditional(node) { - const nonSpacedConsequesntNode = getFirstNonSpacedToken(node.test, node.consequent, "?"); + const nonSpacedConsequentNode = getFirstNonSpacedToken(node.test, node.consequent, "?"); const nonSpacedAlternateNode = getFirstNonSpacedToken(node.consequent, node.alternate, ":"); - if (nonSpacedConsequesntNode) { - report(node, nonSpacedConsequesntNode); + if (nonSpacedConsequentNode) { + report(node, nonSpacedConsequentNode); } else if (nonSpacedAlternateNode) { report(node, nonSpacedAlternateNode); } diff --git a/tools/node_modules/eslint/lib/rules/spaced-comment.js b/tools/node_modules/eslint/lib/rules/spaced-comment.js index daf56cd6bb42d0..d3221f0ea798ac 100644 --- a/tools/node_modules/eslint/lib/rules/spaced-comment.js +++ b/tools/node_modules/eslint/lib/rules/spaced-comment.js @@ -221,7 +221,16 @@ module.exports = { }, additionalProperties: false } - ] + ], + + messages: { + unexpectedSpaceAfterMarker: "Unexpected space or tab after marker ({{refChar}}) in comment.", + expectedExceptionAfter: "Expected exception block, space or tab after '{{refChar}}' in comment.", + unexpectedSpaceBefore: "Unexpected space or tab before '*/' in comment.", + unexpectedSpaceAfter: "Unexpected space or tab after '{{refChar}}' in comment.", + expectedSpaceBefore: "Expected space or tab before '*/' in comment.", + expectedSpaceAfter: "Expected space or tab after '{{refChar}}' in comment." + } }, create(context) { @@ -259,12 +268,12 @@ module.exports = { /** * Reports a beginning spacing error with an appropriate message. * @param {ASTNode} node A comment node to check. - * @param {string} message An error message to report. + * @param {string} messageId An error message to report. * @param {Array} match An array of match results for markers. * @param {string} refChar Character used for reference in the error message. * @returns {void} */ - function reportBegin(node, message, match, refChar) { + function reportBegin(node, messageId, match, refChar) { const type = node.type.toLowerCase(), commentIdentifier = type === "block" ? "/*" : "//"; @@ -284,7 +293,7 @@ module.exports = { return fixer.replaceTextRange([start, end], commentIdentifier + (match[1] ? match[1] : "")); }, - message, + messageId, data: { refChar } }); } @@ -292,11 +301,11 @@ module.exports = { /** * Reports an ending spacing error with an appropriate message. * @param {ASTNode} node A comment node to check. - * @param {string} message An error message to report. + * @param {string} messageId An error message to report. * @param {string} match An array of the matched whitespace characters. * @returns {void} */ - function reportEnd(node, message, match) { + function reportEnd(node, messageId, match) { context.report({ node, fix(fixer) { @@ -309,7 +318,7 @@ module.exports = { return fixer.replaceTextRange([start, end], ""); }, - message + messageId }); } @@ -338,26 +347,26 @@ module.exports = { const marker = hasMarker ? commentIdentifier + hasMarker[0] : commentIdentifier; if (rule.hasExceptions) { - reportBegin(node, "Expected exception block, space or tab after '{{refChar}}' in comment.", hasMarker, marker); + reportBegin(node, "expectedExceptionAfter", hasMarker, marker); } else { - reportBegin(node, "Expected space or tab after '{{refChar}}' in comment.", hasMarker, marker); + reportBegin(node, "expectedSpaceAfter", hasMarker, marker); } } if (balanced && type === "block" && !endMatch) { - reportEnd(node, "Expected space or tab before '*/' in comment."); + reportEnd(node, "expectedSpaceBefore"); } } else { if (beginMatch) { if (!beginMatch[1]) { - reportBegin(node, "Unexpected space or tab after '{{refChar}}' in comment.", beginMatch, commentIdentifier); + reportBegin(node, "unexpectedSpaceAfter", beginMatch, commentIdentifier); } else { - reportBegin(node, "Unexpected space or tab after marker ({{refChar}}) in comment.", beginMatch, beginMatch[1]); + reportBegin(node, "unexpectedSpaceAfterMarker", beginMatch, beginMatch[1]); } } if (balanced && type === "block" && endMatch) { - reportEnd(node, "Unexpected space or tab before '*/' in comment.", endMatch); + reportEnd(node, "unexpectedSpaceBefore", endMatch); } } } diff --git a/tools/node_modules/eslint/lib/rules/template-curly-spacing.js b/tools/node_modules/eslint/lib/rules/template-curly-spacing.js index 07da6a39b0e9bb..a16c0732df7b50 100644 --- a/tools/node_modules/eslint/lib/rules/template-curly-spacing.js +++ b/tools/node_modules/eslint/lib/rules/template-curly-spacing.js @@ -57,7 +57,7 @@ module.exports = { * @returns {void} */ function checkSpacingBefore(token) { - const prevToken = sourceCode.getTokenBefore(token); + const prevToken = sourceCode.getTokenBefore(token, { includeComments: true }); if (prevToken && CLOSE_PAREN.test(token.value) && @@ -86,7 +86,7 @@ module.exports = { * @returns {void} */ function checkSpacingAfter(token) { - const nextToken = sourceCode.getTokenAfter(token); + const nextToken = sourceCode.getTokenAfter(token, { includeComments: true }); if (nextToken && OPEN_PAREN.test(token.value) && diff --git a/tools/node_modules/eslint/lib/rules/use-isnan.js b/tools/node_modules/eslint/lib/rules/use-isnan.js index cd9ccdbaf898ee..7b466be75f2e5e 100644 --- a/tools/node_modules/eslint/lib/rules/use-isnan.js +++ b/tools/node_modules/eslint/lib/rules/use-isnan.js @@ -45,7 +45,7 @@ module.exports = { properties: { enforceForSwitchCase: { type: "boolean", - default: false + default: true }, enforceForIndexOf: { type: "boolean", @@ -66,7 +66,7 @@ module.exports = { create(context) { - const enforceForSwitchCase = context.options[0] && context.options[0].enforceForSwitchCase; + const enforceForSwitchCase = !context.options[0] || context.options[0].enforceForSwitchCase; const enforceForIndexOf = context.options[0] && context.options[0].enforceForIndexOf; /** diff --git a/tools/node_modules/eslint/lib/rules/utils/ast-utils.js b/tools/node_modules/eslint/lib/rules/utils/ast-utils.js index 01c6b47b82eefc..e10544dd61e9ca 100644 --- a/tools/node_modules/eslint/lib/rules/utils/ast-utils.js +++ b/tools/node_modules/eslint/lib/rules/utils/ast-utils.js @@ -865,6 +865,47 @@ module.exports = { return isFunction(node) && module.exports.isEmptyBlock(node.body); }, + /** + * Returns the result of the string conversion applied to the evaluated value of the given expression node, + * if it can be determined statically. + * + * This function returns a `string` value for all `Literal` nodes and simple `TemplateLiteral` nodes only. + * In all other cases, this function returns `null`. + * @param {ASTNode} node Expression node. + * @returns {string|null} String value if it can be determined. Otherwise, `null`. + */ + getStaticStringValue(node) { + switch (node.type) { + case "Literal": + if (node.value === null) { + if (module.exports.isNullLiteral(node)) { + return String(node.value); // "null" + } + if (node.regex) { + return `/${node.regex.pattern}/${node.regex.flags}`; + } + if (node.bigint) { + return node.bigint; + } + + // Otherwise, this is an unknown literal. The function will return null. + + } else { + return String(node.value); + } + break; + case "TemplateLiteral": + if (node.expressions.length === 0 && node.quasis.length === 1) { + return node.quasis[0].value.cooked; + } + break; + + // no default + } + + return null; + }, + /** * Gets the property name of a given node. * The node can be a MemberExpression, a Property, or a MethodDefinition. @@ -911,23 +952,12 @@ module.exports = { // no default } - switch (prop && prop.type) { - case "Literal": - return String(prop.value); - - case "TemplateLiteral": - if (prop.expressions.length === 0 && prop.quasis.length === 1) { - return prop.quasis[0].value.cooked; - } - break; - - case "Identifier": - if (!node.computed) { - return prop.name; - } - break; + if (prop) { + if (prop.type === "Identifier" && !node.computed) { + return prop.name; + } - // no default + return module.exports.getStaticStringValue(prop); } return null; @@ -987,6 +1017,7 @@ module.exports = { * 0o5 // false * 5e0 // false * '5' // false + * 5n // false */ isDecimalInteger(node) { return node.type === "Literal" && typeof node.value === "number" && @@ -1306,6 +1337,18 @@ module.exports = { return node.type === "Literal" && node.value === null && !node.regex && !node.bigint; }, + /** + * Check if a given node is a numeric literal or not. + * @param {ASTNode} node The node to check. + * @returns {boolean} `true` if the node is a number or bigint literal. + */ + isNumericLiteral(node) { + return ( + node.type === "Literal" && + (typeof node.value === "number" || Boolean(node.bigint)) + ); + }, + /** * Determines whether two tokens can safely be placed next to each other without merging into a single token * @param {Token|string} leftValue The left token. If this is a string, it will be tokenized and the last token will be used. diff --git a/tools/node_modules/eslint/lib/rules/utils/unicode/is-combining-character.js b/tools/node_modules/eslint/lib/rules/utils/unicode/is-combining-character.js index 0fa40ee4ae8630..0498b99a21ed45 100644 --- a/tools/node_modules/eslint/lib/rules/utils/unicode/is-combining-character.js +++ b/tools/node_modules/eslint/lib/rules/utils/unicode/is-combining-character.js @@ -1,13 +1,13 @@ -// THIS FILE WAS GENERATED BY 'tools/update-unicode-utils.js' +/** + * @author Toru Nagashima + */ "use strict"; -const combiningChars = new Set([768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,1155,1156,1157,1158,1159,1160,1161,1425,1426,1427,1428,1429,1430,1431,1432,1433,1434,1435,1436,1437,1438,1439,1440,1441,1442,1443,1444,1445,1446,1447,1448,1449,1450,1451,1452,1453,1454,1455,1456,1457,1458,1459,1460,1461,1462,1463,1464,1465,1466,1467,1468,1469,1471,1473,1474,1476,1477,1479,1552,1553,1554,1555,1556,1557,1558,1559,1560,1561,1562,1611,1612,1613,1614,1615,1616,1617,1618,1619,1620,1621,1622,1623,1624,1625,1626,1627,1628,1629,1630,1631,1648,1750,1751,1752,1753,1754,1755,1756,1759,1760,1761,1762,1763,1764,1767,1768,1770,1771,1772,1773,1809,1840,1841,1842,1843,1844,1845,1846,1847,1848,1849,1850,1851,1852,1853,1854,1855,1856,1857,1858,1859,1860,1861,1862,1863,1864,1865,1866,1958,1959,1960,1961,1962,1963,1964,1965,1966,1967,1968,2027,2028,2029,2030,2031,2032,2033,2034,2035,2070,2071,2072,2073,2075,2076,2077,2078,2079,2080,2081,2082,2083,2085,2086,2087,2089,2090,2091,2092,2093,2137,2138,2139,2260,2261,2262,2263,2264,2265,2266,2267,2268,2269,2270,2271,2272,2273,2275,2276,2277,2278,2279,2280,2281,2282,2283,2284,2285,2286,2287,2288,2289,2290,2291,2292,2293,2294,2295,2296,2297,2298,2299,2300,2301,2302,2303,2304,2305,2306,2307,2362,2363,2364,2366,2367,2368,2369,2370,2371,2372,2373,2374,2375,2376,2377,2378,2379,2380,2381,2382,2383,2385,2386,2387,2388,2389,2390,2391,2402,2403,2433,2434,2435,2492,2494,2495,2496,2497,2498,2499,2500,2503,2504,2507,2508,2509,2519,2530,2531,2561,2562,2563,2620,2622,2623,2624,2625,2626,2631,2632,2635,2636,2637,2641,2672,2673,2677,2689,2690,2691,2748,2750,2751,2752,2753,2754,2755,2756,2757,2759,2760,2761,2763,2764,2765,2786,2787,2810,2811,2812,2813,2814,2815,2817,2818,2819,2876,2878,2879,2880,2881,2882,2883,2884,2887,2888,2891,2892,2893,2902,2903,2914,2915,2946,3006,3007,3008,3009,3010,3014,3015,3016,3018,3019,3020,3021,3031,3072,3073,3074,3075,3134,3135,3136,3137,3138,3139,3140,3142,3143,3144,3146,3147,3148,3149,3157,3158,3170,3171,3201,3202,3203,3260,3262,3263,3264,3265,3266,3267,3268,3270,3271,3272,3274,3275,3276,3277,3285,3286,3298,3299,3328,3329,3330,3331,3387,3388,3390,3391,3392,3393,3394,3395,3396,3398,3399,3400,3402,3403,3404,3405,3415,3426,3427,3458,3459,3530,3535,3536,3537,3538,3539,3540,3542,3544,3545,3546,3547,3548,3549,3550,3551,3570,3571,3633,3636,3637,3638,3639,3640,3641,3642,3655,3656,3657,3658,3659,3660,3661,3662,3761,3764,3765,3766,3767,3768,3769,3771,3772,3784,3785,3786,3787,3788,3789,3864,3865,3893,3895,3897,3902,3903,3953,3954,3955,3956,3957,3958,3959,3960,3961,3962,3963,3964,3965,3966,3967,3968,3969,3970,3971,3972,3974,3975,3981,3982,3983,3984,3985,3986,3987,3988,3989,3990,3991,3993,3994,3995,3996,3997,3998,3999,4000,4001,4002,4003,4004,4005,4006,4007,4008,4009,4010,4011,4012,4013,4014,4015,4016,4017,4018,4019,4020,4021,4022,4023,4024,4025,4026,4027,4028,4038,4139,4140,4141,4142,4143,4144,4145,4146,4147,4148,4149,4150,4151,4152,4153,4154,4155,4156,4157,4158,4182,4183,4184,4185,4190,4191,4192,4194,4195,4196,4199,4200,4201,4202,4203,4204,4205,4209,4210,4211,4212,4226,4227,4228,4229,4230,4231,4232,4233,4234,4235,4236,4237,4239,4250,4251,4252,4253,4957,4958,4959,5906,5907,5908,5938,5939,5940,5970,5971,6002,6003,6068,6069,6070,6071,6072,6073,6074,6075,6076,6077,6078,6079,6080,6081,6082,6083,6084,6085,6086,6087,6088,6089,6090,6091,6092,6093,6094,6095,6096,6097,6098,6099,6109,6155,6156,6157,6277,6278,6313,6432,6433,6434,6435,6436,6437,6438,6439,6440,6441,6442,6443,6448,6449,6450,6451,6452,6453,6454,6455,6456,6457,6458,6459,6679,6680,6681,6682,6683,6741,6742,6743,6744,6745,6746,6747,6748,6749,6750,6752,6753,6754,6755,6756,6757,6758,6759,6760,6761,6762,6763,6764,6765,6766,6767,6768,6769,6770,6771,6772,6773,6774,6775,6776,6777,6778,6779,6780,6783,6832,6833,6834,6835,6836,6837,6838,6839,6840,6841,6842,6843,6844,6845,6846,6912,6913,6914,6915,6916,6964,6965,6966,6967,6968,6969,6970,6971,6972,6973,6974,6975,6976,6977,6978,6979,6980,7019,7020,7021,7022,7023,7024,7025,7026,7027,7040,7041,7042,7073,7074,7075,7076,7077,7078,7079,7080,7081,7082,7083,7084,7085,7142,7143,7144,7145,7146,7147,7148,7149,7150,7151,7152,7153,7154,7155,7204,7205,7206,7207,7208,7209,7210,7211,7212,7213,7214,7215,7216,7217,7218,7219,7220,7221,7222,7223,7376,7377,7378,7380,7381,7382,7383,7384,7385,7386,7387,7388,7389,7390,7391,7392,7393,7394,7395,7396,7397,7398,7399,7400,7405,7410,7411,7412,7415,7416,7417,7616,7617,7618,7619,7620,7621,7622,7623,7624,7625,7626,7627,7628,7629,7630,7631,7632,7633,7634,7635,7636,7637,7638,7639,7640,7641,7642,7643,7644,7645,7646,7647,7648,7649,7650,7651,7652,7653,7654,7655,7656,7657,7658,7659,7660,7661,7662,7663,7664,7665,7666,7667,7668,7669,7670,7671,7672,7673,7675,7676,7677,7678,7679,8400,8401,8402,8403,8404,8405,8406,8407,8408,8409,8410,8411,8412,8413,8414,8415,8416,8417,8418,8419,8420,8421,8422,8423,8424,8425,8426,8427,8428,8429,8430,8431,8432,11503,11504,11505,11647,11744,11745,11746,11747,11748,11749,11750,11751,11752,11753,11754,11755,11756,11757,11758,11759,11760,11761,11762,11763,11764,11765,11766,11767,11768,11769,11770,11771,11772,11773,11774,11775,12330,12331,12332,12333,12334,12335,12441,12442,42607,42608,42609,42610,42612,42613,42614,42615,42616,42617,42618,42619,42620,42621,42654,42655,42736,42737,43010,43014,43019,43043,43044,43045,43046,43047,43136,43137,43188,43189,43190,43191,43192,43193,43194,43195,43196,43197,43198,43199,43200,43201,43202,43203,43204,43205,43232,43233,43234,43235,43236,43237,43238,43239,43240,43241,43242,43243,43244,43245,43246,43247,43248,43249,43302,43303,43304,43305,43306,43307,43308,43309,43335,43336,43337,43338,43339,43340,43341,43342,43343,43344,43345,43346,43347,43392,43393,43394,43395,43443,43444,43445,43446,43447,43448,43449,43450,43451,43452,43453,43454,43455,43456,43493,43561,43562,43563,43564,43565,43566,43567,43568,43569,43570,43571,43572,43573,43574,43587,43596,43597,43643,43644,43645,43696,43698,43699,43700,43703,43704,43710,43711,43713,43755,43756,43757,43758,43759,43765,43766,44003,44004,44005,44006,44007,44008,44009,44010,44012,44013,64286,65024,65025,65026,65027,65028,65029,65030,65031,65032,65033,65034,65035,65036,65037,65038,65039,65056,65057,65058,65059,65060,65061,65062,65063,65064,65065,65066,65067,65068,65069,65070,65071,66045,66272,66422,66423,66424,66425,66426,68097,68098,68099,68101,68102,68108,68109,68110,68111,68152,68153,68154,68159,68325,68326,69632,69633,69634,69688,69689,69690,69691,69692,69693,69694,69695,69696,69697,69698,69699,69700,69701,69702,69759,69760,69761,69762,69808,69809,69810,69811,69812,69813,69814,69815,69816,69817,69818,69888,69889,69890,69927,69928,69929,69930,69931,69932,69933,69934,69935,69936,69937,69938,69939,69940,70003,70016,70017,70018,70067,70068,70069,70070,70071,70072,70073,70074,70075,70076,70077,70078,70079,70080,70090,70091,70092,70188,70189,70190,70191,70192,70193,70194,70195,70196,70197,70198,70199,70206,70367,70368,70369,70370,70371,70372,70373,70374,70375,70376,70377,70378,70400,70401,70402,70403,70460,70462,70463,70464,70465,70466,70467,70468,70471,70472,70475,70476,70477,70487,70498,70499,70502,70503,70504,70505,70506,70507,70508,70512,70513,70514,70515,70516,70709,70710,70711,70712,70713,70714,70715,70716,70717,70718,70719,70720,70721,70722,70723,70724,70725,70726,70832,70833,70834,70835,70836,70837,70838,70839,70840,70841,70842,70843,70844,70845,70846,70847,70848,70849,70850,70851,71087,71088,71089,71090,71091,71092,71093,71096,71097,71098,71099,71100,71101,71102,71103,71104,71132,71133,71216,71217,71218,71219,71220,71221,71222,71223,71224,71225,71226,71227,71228,71229,71230,71231,71232,71339,71340,71341,71342,71343,71344,71345,71346,71347,71348,71349,71350,71351,71453,71454,71455,71456,71457,71458,71459,71460,71461,71462,71463,71464,71465,71466,71467,72193,72194,72195,72196,72197,72198,72199,72200,72201,72202,72243,72244,72245,72246,72247,72248,72249,72251,72252,72253,72254,72263,72273,72274,72275,72276,72277,72278,72279,72280,72281,72282,72283,72330,72331,72332,72333,72334,72335,72336,72337,72338,72339,72340,72341,72342,72343,72344,72345,72751,72752,72753,72754,72755,72756,72757,72758,72760,72761,72762,72763,72764,72765,72766,72767,72850,72851,72852,72853,72854,72855,72856,72857,72858,72859,72860,72861,72862,72863,72864,72865,72866,72867,72868,72869,72870,72871,72873,72874,72875,72876,72877,72878,72879,72880,72881,72882,72883,72884,72885,72886,73009,73010,73011,73012,73013,73014,73018,73020,73021,73023,73024,73025,73026,73027,73028,73029,73031,92912,92913,92914,92915,92916,92976,92977,92978,92979,92980,92981,92982,94033,94034,94035,94036,94037,94038,94039,94040,94041,94042,94043,94044,94045,94046,94047,94048,94049,94050,94051,94052,94053,94054,94055,94056,94057,94058,94059,94060,94061,94062,94063,94064,94065,94066,94067,94068,94069,94070,94071,94072,94073,94074,94075,94076,94077,94078,94095,94096,94097,94098,113821,113822,119141,119142,119143,119144,119145,119149,119150,119151,119152,119153,119154,119163,119164,119165,119166,119167,119168,119169,119170,119173,119174,119175,119176,119177,119178,119179,119210,119211,119212,119213,119362,119363,119364,121344,121345,121346,121347,121348,121349,121350,121351,121352,121353,121354,121355,121356,121357,121358,121359,121360,121361,121362,121363,121364,121365,121366,121367,121368,121369,121370,121371,121372,121373,121374,121375,121376,121377,121378,121379,121380,121381,121382,121383,121384,121385,121386,121387,121388,121389,121390,121391,121392,121393,121394,121395,121396,121397,121398,121403,121404,121405,121406,121407,121408,121409,121410,121411,121412,121413,121414,121415,121416,121417,121418,121419,121420,121421,121422,121423,121424,121425,121426,121427,121428,121429,121430,121431,121432,121433,121434,121435,121436,121437,121438,121439,121440,121441,121442,121443,121444,121445,121446,121447,121448,121449,121450,121451,121452,121461,121476,121499,121500,121501,121502,121503,121505,121506,121507,121508,121509,121510,121511,121512,121513,121514,121515,121516,121517,121518,121519,122880,122881,122882,122883,122884,122885,122886,122888,122889,122890,122891,122892,122893,122894,122895,122896,122897,122898,122899,122900,122901,122902,122903,122904,122907,122908,122909,122910,122911,122912,122913,122915,122916,122918,122919,122920,122921,122922,125136,125137,125138,125139,125140,125141,125142,125252,125253,125254,125255,125256,125257,125258,917760,917761,917762,917763,917764,917765,917766,917767,917768,917769,917770,917771,917772,917773,917774,917775,917776,917777,917778,917779,917780,917781,917782,917783,917784,917785,917786,917787,917788,917789,917790,917791,917792,917793,917794,917795,917796,917797,917798,917799,917800,917801,917802,917803,917804,917805,917806,917807,917808,917809,917810,917811,917812,917813,917814,917815,917816,917817,917818,917819,917820,917821,917822,917823,917824,917825,917826,917827,917828,917829,917830,917831,917832,917833,917834,917835,917836,917837,917838,917839,917840,917841,917842,917843,917844,917845,917846,917847,917848,917849,917850,917851,917852,917853,917854,917855,917856,917857,917858,917859,917860,917861,917862,917863,917864,917865,917866,917867,917868,917869,917870,917871,917872,917873,917874,917875,917876,917877,917878,917879,917880,917881,917882,917883,917884,917885,917886,917887,917888,917889,917890,917891,917892,917893,917894,917895,917896,917897,917898,917899,917900,917901,917902,917903,917904,917905,917906,917907,917908,917909,917910,917911,917912,917913,917914,917915,917916,917917,917918,917919,917920,917921,917922,917923,917924,917925,917926,917927,917928,917929,917930,917931,917932,917933,917934,917935,917936,917937,917938,917939,917940,917941,917942,917943,917944,917945,917946,917947,917948,917949,917950,917951,917952,917953,917954,917955,917956,917957,917958,917959,917960,917961,917962,917963,917964,917965,917966,917967,917968,917969,917970,917971,917972,917973,917974,917975,917976,917977,917978,917979,917980,917981,917982,917983,917984,917985,917986,917987,917988,917989,917990,917991,917992,917993,917994,917995,917996,917997,917998,917999]) - /** * Check whether a given character is a combining mark or not. - * @param {number} c The character code to check. - * @returns {boolean} `true` if the character belongs to the category, one of `Mc`, `Me`, and `Mn`. + * @param {number} codePoint The character code to check. + * @returns {boolean} `true` if the character belongs to the category, any of `Mc`, `Me`, and `Mn`. */ -module.exports = function isCombiningCharacter(c) { - return combiningChars.has(c); +module.exports = function isCombiningCharacter(codePoint) { + return /^[\p{Mc}\p{Me}\p{Mn}]$/u.test(String.fromCodePoint(codePoint)); }; diff --git a/tools/node_modules/eslint/lib/rules/wrap-iife.js b/tools/node_modules/eslint/lib/rules/wrap-iife.js index 5e590be13e28b5..896aed63de5222 100644 --- a/tools/node_modules/eslint/lib/rules/wrap-iife.js +++ b/tools/node_modules/eslint/lib/rules/wrap-iife.js @@ -10,6 +10,21 @@ //------------------------------------------------------------------------------ const astUtils = require("./utils/ast-utils"); +const eslintUtils = require("eslint-utils"); + +//---------------------------------------------------------------------- +// Helpers +//---------------------------------------------------------------------- + +/** + * Check if the given node is callee of a `NewExpression` node + * @param {ASTNode} node node to check + * @returns {boolean} True if the node is callee of a `NewExpression` node + * @private + */ +function isCalleeOfNewExpression(node) { + return node.parent.type === "NewExpression" && node.parent.callee === node; +} //------------------------------------------------------------------------------ // Rule Definition @@ -58,15 +73,25 @@ module.exports = { const sourceCode = context.getSourceCode(); /** - * Check if the node is wrapped in () + * Check if the node is wrapped in any (). All parens count: grouping parens and parens for constructs such as if() * @param {ASTNode} node node to evaluate - * @returns {boolean} True if it is wrapped + * @returns {boolean} True if it is wrapped in any parens * @private */ - function wrapped(node) { + function isWrappedInAnyParens(node) { return astUtils.isParenthesised(sourceCode, node); } + /** + * Check if the node is wrapped in grouping (). Parens for constructs such as if() don't count + * @param {ASTNode} node node to evaluate + * @returns {boolean} True if it is wrapped in grouping parens + * @private + */ + function isWrappedInGroupingParens(node) { + return eslintUtils.isParenthesized(1, node, sourceCode); + } + /** * Get the function node from an IIFE * @param {ASTNode} node node to evaluate @@ -99,10 +124,10 @@ module.exports = { return; } - const callExpressionWrapped = wrapped(node), - functionExpressionWrapped = wrapped(innerNode); + const isCallExpressionWrapped = isWrappedInAnyParens(node), + isFunctionExpressionWrapped = isWrappedInAnyParens(innerNode); - if (!callExpressionWrapped && !functionExpressionWrapped) { + if (!isCallExpressionWrapped && !isFunctionExpressionWrapped) { context.report({ node, messageId: "wrapInvocation", @@ -112,27 +137,39 @@ module.exports = { return fixer.replaceText(nodeToSurround, `(${sourceCode.getText(nodeToSurround)})`); } }); - } else if (style === "inside" && !functionExpressionWrapped) { + } else if (style === "inside" && !isFunctionExpressionWrapped) { context.report({ node, messageId: "wrapExpression", fix(fixer) { + // The outer call expression will always be wrapped at this point. + + if (isWrappedInGroupingParens(node) && !isCalleeOfNewExpression(node)) { + + /* + * Parenthesize the function expression and remove unnecessary grouping parens around the call expression. + * Replace the range between the end of the function expression and the end of the call expression. + * for example, in `(function(foo) {}(bar))`, the range `(bar))` should get replaced with `)(bar)`. + */ + + const parenAfter = sourceCode.getTokenAfter(node); + + return fixer.replaceTextRange( + [innerNode.range[1], parenAfter.range[1]], + `)${sourceCode.getText().slice(innerNode.range[1], parenAfter.range[0])}` + ); + } + /* - * The outer call expression will always be wrapped at this point. - * Replace the range between the end of the function expression and the end of the call expression. - * for example, in `(function(foo) {}(bar))`, the range `(bar))` should get replaced with `)(bar)`. - * Replace the parens from the outer expression, and parenthesize the function expression. + * Call expression is wrapped in mandatory parens such as if(), or in necessary grouping parens. + * These parens cannot be removed, so just parenthesize the function expression. */ - const parenAfter = sourceCode.getTokenAfter(node); - return fixer.replaceTextRange( - [innerNode.range[1], parenAfter.range[1]], - `)${sourceCode.getText().slice(innerNode.range[1], parenAfter.range[0])}` - ); + return fixer.replaceText(innerNode, `(${sourceCode.getText(innerNode)})`); } }); - } else if (style === "outside" && !callExpressionWrapped) { + } else if (style === "outside" && !isCallExpressionWrapped) { context.report({ node, messageId: "moveInvocation", diff --git a/tools/node_modules/eslint/lib/rules/yoda.js b/tools/node_modules/eslint/lib/rules/yoda.js index b00acf82c702b0..c4ff3f81938595 100644 --- a/tools/node_modules/eslint/lib/rules/yoda.js +++ b/tools/node_modules/eslint/lib/rules/yoda.js @@ -49,12 +49,30 @@ function isRangeTestOperator(operator) { * @returns {boolean} True if the node is a negative number that looks like a * real literal and should be treated as such. */ -function looksLikeLiteral(node) { +function isNegativeNumericLiteral(node) { return (node.type === "UnaryExpression" && node.operator === "-" && node.prefix && - node.argument.type === "Literal" && - typeof node.argument.value === "number"); + astUtils.isNumericLiteral(node.argument)); +} + +/** + * Determines whether a node is a Template Literal which can be determined statically. + * @param {ASTNode} node Node to test + * @returns {boolean} True if the node is a Template Literal without expression. + */ +function isStaticTemplateLiteral(node) { + return node.type === "TemplateLiteral" && node.expressions.length === 0; +} + +/** + * Determines whether a non-Literal node should be treated as a single Literal node. + * @param {ASTNode} node Node to test + * @returns {boolean} True if the node should be treated as a single Literal node. + */ +function looksLikeLiteral(node) { + return isNegativeNumericLiteral(node) || + isStaticTemplateLiteral(node); } /** @@ -66,15 +84,17 @@ function looksLikeLiteral(node) { * 1. The original node if the node is already a Literal * 2. A normalized Literal node with the negative number as the value if the * node represents a negative number literal. - * 3. The Literal node which has the `defaultValue` argument if it exists. - * 4. Otherwise `null`. + * 3. A normalized Literal node with the string as the value if the node is + * a Template Literal without expression. + * 4. The Literal node which has the `defaultValue` argument if it exists. + * 5. Otherwise `null`. */ function getNormalizedLiteral(node, defaultValue) { if (node.type === "Literal") { return node; } - if (looksLikeLiteral(node)) { + if (isNegativeNumericLiteral(node)) { return { type: "Literal", value: -node.argument.value, @@ -82,6 +102,14 @@ function getNormalizedLiteral(node, defaultValue) { }; } + if (isStaticTemplateLiteral(node)) { + return { + type: "Literal", + value: node.quasis[0].value.cooked, + raw: node.quasis[0].value.raw + }; + } + if (defaultValue) { return { type: "Literal", diff --git a/tools/node_modules/eslint/lib/shared/config-validator.js b/tools/node_modules/eslint/lib/shared/config-validator.js index aca6e1fb274fdb..458bd2a802b95c 100644 --- a/tools/node_modules/eslint/lib/shared/config-validator.js +++ b/tools/node_modules/eslint/lib/shared/config-validator.js @@ -10,13 +10,12 @@ //------------------------------------------------------------------------------ const - path = require("path"), util = require("util"), - lodash = require("lodash"), configSchema = require("../../conf/config-schema"), BuiltInEnvironments = require("../../conf/environments"), BuiltInRules = require("../rules"), - ConfigOps = require("./config-ops"); + ConfigOps = require("./config-ops"), + { emitDeprecationWarning } = require("./deprecation-warnings"); const ajv = require("./ajv")(); const ruleValidators = new WeakMap(); @@ -26,11 +25,6 @@ const noop = Function.prototype; // Private //------------------------------------------------------------------------------ let validateSchema; - -// Defitions for deprecation warnings. -const deprecationWarningMessages = { - ESLINT_LEGACY_ECMAFEATURES: "The 'ecmaFeatures' config file property is deprecated, and has no effect." -}; const severityMap = { error: 2, warn: 1, @@ -196,7 +190,7 @@ function validateRules( /** * Validates a `globals` section of a config file - * @param {Object} globalsConfig The `glboals` section + * @param {Object} globalsConfig The `globals` section * @param {string|null} source The name of the configuration source to report in the event of an error. * @returns {void} */ @@ -254,25 +248,6 @@ function formatErrors(errors) { }).map(message => `\t- ${message}.\n`).join(""); } -/** - * Emits a deprecation warning containing a given filepath. A new deprecation warning is emitted - * for each unique file path, but repeated invocations with the same file path have no effect. - * No warnings are emitted if the `--no-deprecation` or `--no-warnings` Node runtime flags are active. - * @param {string} source The name of the configuration source to report the warning for. - * @param {string} errorCode The warning message to show. - * @returns {void} - */ -const emitDeprecationWarning = lodash.memoize((source, errorCode) => { - const rel = path.relative(process.cwd(), source); - const message = deprecationWarningMessages[errorCode]; - - process.emitWarning( - `${message} (found in "${rel}")`, - "DeprecationWarning", - errorCode - ); -}); - /** * Validates the top level properties of the config object. * @param {Object} config The config object to validate. diff --git a/tools/node_modules/eslint/lib/shared/deprecation-warnings.js b/tools/node_modules/eslint/lib/shared/deprecation-warnings.js new file mode 100644 index 00000000000000..e1481a2e9aa0b8 --- /dev/null +++ b/tools/node_modules/eslint/lib/shared/deprecation-warnings.js @@ -0,0 +1,56 @@ +/** + * @fileoverview Provide the function that emits deprecation warnings. + * @author Toru Nagashima + */ +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const path = require("path"); +const lodash = require("lodash"); + +//------------------------------------------------------------------------------ +// Private +//------------------------------------------------------------------------------ + +// Defitions for deprecation warnings. +const deprecationWarningMessages = { + ESLINT_LEGACY_ECMAFEATURES: + "The 'ecmaFeatures' config file property is deprecated and has no effect.", + ESLINT_PERSONAL_CONFIG_LOAD: + "'~/.eslintrc.*' config files have been deprecated. " + + "Please use a config file per project or the '--config' option.", + ESLINT_PERSONAL_CONFIG_SUPPRESS: + "'~/.eslintrc.*' config files have been deprecated. " + + "Please remove it or add 'root:true' to the config files in your " + + "projects in order to avoid loading '~/.eslintrc.*' accidentally." +}; + +/** + * Emits a deprecation warning containing a given filepath. A new deprecation warning is emitted + * for each unique file path, but repeated invocations with the same file path have no effect. + * No warnings are emitted if the `--no-deprecation` or `--no-warnings` Node runtime flags are active. + * @param {string} source The name of the configuration source to report the warning for. + * @param {string} errorCode The warning message to show. + * @returns {void} + */ +const emitDeprecationWarning = lodash.memoize((source, errorCode) => { + const rel = path.relative(process.cwd(), source); + const message = deprecationWarningMessages[errorCode]; + + process.emitWarning( + `${message} (found in "${rel}")`, + "DeprecationWarning", + errorCode + ); +}, (...args) => JSON.stringify(args)); + +//------------------------------------------------------------------------------ +// Public Interface +//------------------------------------------------------------------------------ + +module.exports = { + emitDeprecationWarning +}; diff --git a/tools/node_modules/eslint/lib/shared/naming.js b/tools/node_modules/eslint/lib/shared/naming.js index b99155f15cafa7..32cff94538af22 100644 --- a/tools/node_modules/eslint/lib/shared/naming.js +++ b/tools/node_modules/eslint/lib/shared/naming.js @@ -78,7 +78,7 @@ function getShorthandName(fullname, prefix) { /** * Gets the scope (namespace) of a term. * @param {string} term The term which may have the namespace. - * @returns {string} The namepace of the term if it has one. + * @returns {string} The namespace of the term if it has one. */ function getNamespaceFromTerm(term) { const match = term.match(NAMESPACE_REGEX); diff --git a/tools/node_modules/eslint/lib/shared/relative-module-resolver.js b/tools/node_modules/eslint/lib/shared/relative-module-resolver.js index 5b25fa111214ed..fa6cca72361df5 100644 --- a/tools/node_modules/eslint/lib/shared/relative-module-resolver.js +++ b/tools/node_modules/eslint/lib/shared/relative-module-resolver.js @@ -6,35 +6,18 @@ "use strict"; const Module = require("module"); -const path = require("path"); -// Polyfill Node's `Module.createRequire` if not present. We only support the case where the argument is a filepath, not a URL. -const createRequire = ( - - // Added in v12.2.0 - Module.createRequire || - - // Added in v10.12.0, but deprecated in v12.2.0. - Module.createRequireFromPath || - - // Polyfill - This is not executed on the tests on node@>=10. - /* istanbul ignore next */ - (filename => { - const mod = new Module(filename, null); - - mod.filename = filename; - mod.paths = Module._nodeModulePaths(path.dirname(filename)); // eslint-disable-line no-underscore-dangle - mod._compile("module.exports = require;", filename); // eslint-disable-line no-underscore-dangle - return mod.exports; - }) -); +/* + * `Module.createRequire` is added in v12.2.0. It supports URL as well. + * We only support the case where the argument is a filepath, not a URL. + */ +const createRequire = Module.createRequire || Module.createRequireFromPath; module.exports = { /** * Resolves a Node module relative to another module * @param {string} moduleName The name of a Node module, or a path to a Node module. - * * @param {string} relativeToPath An absolute path indicating the module that `moduleName` should be resolved relative to. This must be * a file rather than a directory, but the file need not actually exist. * @returns {string} The absolute path that would result from calling `require.resolve(moduleName)` in a file located at `relativeToPath` @@ -43,6 +26,8 @@ module.exports = { try { return createRequire(relativeToPath).resolve(moduleName); } catch (error) { + + // This `if` block is for older Node.js than 12.0.0. We can remove this block in the future. if ( typeof error === "object" && error !== null && diff --git a/tools/node_modules/eslint/lib/shared/types.js b/tools/node_modules/eslint/lib/shared/types.js index a5bd0200e2792a..f3d1a7f29f02f0 100644 --- a/tools/node_modules/eslint/lib/shared/types.js +++ b/tools/node_modules/eslint/lib/shared/types.js @@ -21,7 +21,7 @@ module.exports = {}; /** * @typedef {Object} ParserOptions * @property {EcmaFeatures} [ecmaFeatures] The optional features. - * @property {3|5|6|7|8|9|10|2015|2016|2017|2018|2019} [ecmaVersion] The ECMAScript version (or revision number). + * @property {3|5|6|7|8|9|10|11|2015|2016|2017|2018|2019|2020} [ecmaVersion] The ECMAScript version (or revision number). * @property {"script"|"module"} [sourceType] The source code type. */ diff --git a/tools/node_modules/eslint/lib/source-code/source-code.js b/tools/node_modules/eslint/lib/source-code/source-code.js index 30b4e9ab5c26e3..591d5a7e454ee2 100644 --- a/tools/node_modules/eslint/lib/source-code/source-code.js +++ b/tools/node_modules/eslint/lib/source-code/source-code.js @@ -121,7 +121,7 @@ function isSpaceBetween(sourceCode, first, second, checkInsideOfJSXText) { currentToken.range[1] !== nextToken.range[0] || /* - * For backward compatibility, check speces in JSXText. + * For backward compatibility, check spaces in JSXText. * https://github.com/eslint/eslint/issues/12614 */ ( diff --git a/tools/node_modules/eslint/lib/source-code/token-store/utils.js b/tools/node_modules/eslint/lib/source-code/token-store/utils.js index 444684b52f1bb0..21e1d6ff7c3b6d 100644 --- a/tools/node_modules/eslint/lib/source-code/token-store/utils.js +++ b/tools/node_modules/eslint/lib/source-code/token-store/utils.js @@ -1,5 +1,5 @@ /** - * @fileoverview Define utilify functions for token store. + * @fileoverview Define utility functions for token store. * @author Toru Nagashima */ "use strict"; diff --git a/tools/node_modules/eslint/node_modules/@babel/code-frame/lib/index.js b/tools/node_modules/eslint/node_modules/@babel/code-frame/lib/index.js index 35176fbc0682ca..62945f7782a774 100644 --- a/tools/node_modules/eslint/node_modules/@babel/code-frame/lib/index.js +++ b/tools/node_modules/eslint/node_modules/@babel/code-frame/lib/index.js @@ -6,17 +6,11 @@ Object.defineProperty(exports, "__esModule", { exports.codeFrameColumns = codeFrameColumns; exports.default = _default; -function _highlight() { - const data = _interopRequireWildcard(require("@babel/highlight")); +var _highlight = _interopRequireWildcard(require("@babel/highlight")); - _highlight = function () { - return data; - }; - - return data; -} +function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } } +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } let deprecationWarningShown = false; @@ -35,7 +29,7 @@ function getMarkerLines(loc, source, opts) { column: 0, line: -1 }, loc.start); - const endLoc = Object.assign({}, startLoc, loc.end); + const endLoc = Object.assign({}, startLoc, {}, loc.end); const { linesAbove = 2, linesBelow = 3 @@ -94,8 +88,8 @@ function getMarkerLines(loc, source, opts) { } function codeFrameColumns(rawLines, loc, opts = {}) { - const highlighted = (opts.highlightCode || opts.forceColor) && (0, _highlight().shouldHighlight)(opts); - const chalk = (0, _highlight().getChalk)(opts); + const highlighted = (opts.highlightCode || opts.forceColor) && (0, _highlight.shouldHighlight)(opts); + const chalk = (0, _highlight.getChalk)(opts); const defs = getDefs(chalk); const maybeHighlight = (chalkFn, string) => { @@ -110,7 +104,7 @@ function codeFrameColumns(rawLines, loc, opts = {}) { } = getMarkerLines(loc, lines, opts); const hasColumns = loc.start && typeof loc.start.column === "number"; const numberMaxWidth = String(end).length; - const highlightedLines = highlighted ? (0, _highlight().default)(rawLines, opts) : rawLines; + const highlightedLines = highlighted ? (0, _highlight.default)(rawLines, opts) : rawLines; let frame = highlightedLines.split(NEWLINE).slice(start, end).map((line, index) => { const number = start + 1 + index; const paddedNumber = ` ${number}`.slice(-numberMaxWidth); diff --git a/tools/node_modules/eslint/node_modules/@babel/code-frame/package.json b/tools/node_modules/eslint/node_modules/@babel/code-frame/package.json index d619d9a8f53194..7508b5b1402c94 100644 --- a/tools/node_modules/eslint/node_modules/@babel/code-frame/package.json +++ b/tools/node_modules/eslint/node_modules/@babel/code-frame/package.json @@ -5,7 +5,7 @@ }, "bundleDependencies": false, "dependencies": { - "@babel/highlight": "^7.0.0" + "@babel/highlight": "^7.8.3" }, "deprecated": false, "description": "Generate errors that contain a code frame that point to source locations.", @@ -13,7 +13,7 @@ "chalk": "^2.0.0", "strip-ansi": "^4.0.0" }, - "gitHead": "0407f034f09381b95e9cabefbf6b176c76485a43", + "gitHead": "a7620bd266ae1345975767bbc7abf09034437017", "homepage": "https://babeljs.io/", "license": "MIT", "main": "lib/index.js", @@ -25,5 +25,5 @@ "type": "git", "url": "https://github.com/babel/babel/tree/master/packages/babel-code-frame" }, - "version": "7.5.5" + "version": "7.8.3" } \ No newline at end of file diff --git a/tools/node_modules/eslint/node_modules/@babel/highlight/lib/index.js b/tools/node_modules/eslint/node_modules/@babel/highlight/lib/index.js index 6ac5b4a350b8e6..bf275748784b50 100644 --- a/tools/node_modules/eslint/node_modules/@babel/highlight/lib/index.js +++ b/tools/node_modules/eslint/node_modules/@babel/highlight/lib/index.js @@ -7,39 +7,17 @@ exports.shouldHighlight = shouldHighlight; exports.getChalk = getChalk; exports.default = highlight; -function _jsTokens() { - const data = _interopRequireWildcard(require("js-tokens")); +var _jsTokens = _interopRequireWildcard(require("js-tokens")); - _jsTokens = function () { - return data; - }; - - return data; -} - -function _esutils() { - const data = _interopRequireDefault(require("esutils")); +var _esutils = _interopRequireDefault(require("esutils")); - _esutils = function () { - return data; - }; - - return data; -} - -function _chalk() { - const data = _interopRequireDefault(require("chalk")); - - _chalk = function () { - return data; - }; - - return data; -} +var _chalk = _interopRequireDefault(require("chalk")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } } +function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } function getDefs(chalk) { return { @@ -61,10 +39,10 @@ const BRACKET = /^[()[\]{}]$/; function getTokenType(match) { const [offset, text] = match.slice(-2); - const token = (0, _jsTokens().matchToToken)(match); + const token = (0, _jsTokens.matchToToken)(match); if (token.type === "name") { - if (_esutils().default.keyword.isReservedWordES6(token.value)) { + if (_esutils.default.keyword.isReservedWordES6(token.value)) { return "keyword"; } @@ -89,7 +67,7 @@ function getTokenType(match) { } function highlightTokens(defs, text) { - return text.replace(_jsTokens().default, function (...args) { + return text.replace(_jsTokens.default, function (...args) { const type = getTokenType(args); const colorize = defs[type]; @@ -102,14 +80,14 @@ function highlightTokens(defs, text) { } function shouldHighlight(options) { - return _chalk().default.supportsColor || options.forceColor; + return _chalk.default.supportsColor || options.forceColor; } function getChalk(options) { - let chalk = _chalk().default; + let chalk = _chalk.default; if (options.forceColor) { - chalk = new (_chalk().default.constructor)({ + chalk = new _chalk.default.constructor({ enabled: true, level: 1 }); diff --git a/tools/node_modules/eslint/node_modules/chalk/index.js b/tools/node_modules/eslint/node_modules/@babel/highlight/node_modules/chalk/index.js similarity index 100% rename from tools/node_modules/eslint/node_modules/chalk/index.js rename to tools/node_modules/eslint/node_modules/@babel/highlight/node_modules/chalk/index.js diff --git a/tools/node_modules/eslint/node_modules/chalk/index.js.flow b/tools/node_modules/eslint/node_modules/@babel/highlight/node_modules/chalk/index.js.flow similarity index 100% rename from tools/node_modules/eslint/node_modules/chalk/index.js.flow rename to tools/node_modules/eslint/node_modules/@babel/highlight/node_modules/chalk/index.js.flow diff --git a/tools/node_modules/eslint/node_modules/string-width/node_modules/strip-ansi/license b/tools/node_modules/eslint/node_modules/@babel/highlight/node_modules/chalk/license similarity index 100% rename from tools/node_modules/eslint/node_modules/string-width/node_modules/strip-ansi/license rename to tools/node_modules/eslint/node_modules/@babel/highlight/node_modules/chalk/license diff --git a/tools/node_modules/eslint/node_modules/@babel/highlight/node_modules/chalk/package.json b/tools/node_modules/eslint/node_modules/@babel/highlight/node_modules/chalk/package.json new file mode 100644 index 00000000000000..270fecdc347d42 --- /dev/null +++ b/tools/node_modules/eslint/node_modules/@babel/highlight/node_modules/chalk/package.json @@ -0,0 +1,80 @@ +{ + "bugs": { + "url": "https://github.com/chalk/chalk/issues" + }, + "bundleDependencies": false, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "deprecated": false, + "description": "Terminal string styling done right", + "devDependencies": { + "ava": "*", + "coveralls": "^3.0.0", + "execa": "^0.9.0", + "flow-bin": "^0.68.0", + "import-fresh": "^2.0.0", + "matcha": "^0.7.0", + "nyc": "^11.0.2", + "resolve-from": "^4.0.0", + "typescript": "^2.5.3", + "xo": "*" + }, + "engines": { + "node": ">=4" + }, + "files": [ + "index.js", + "templates.js", + "types/index.d.ts", + "index.js.flow" + ], + "homepage": "https://github.com/chalk/chalk#readme", + "keywords": [ + "color", + "colour", + "colors", + "terminal", + "console", + "cli", + "string", + "str", + "ansi", + "style", + "styles", + "tty", + "formatting", + "rgb", + "256", + "shell", + "xterm", + "log", + "logging", + "command-line", + "text" + ], + "license": "MIT", + "name": "chalk", + "repository": { + "type": "git", + "url": "git+https://github.com/chalk/chalk.git" + }, + "scripts": { + "bench": "matcha benchmark.js", + "coveralls": "nyc report --reporter=text-lcov | coveralls", + "test": "xo && tsc --project types && flow --max-warnings=0 && nyc ava" + }, + "types": "types/index.d.ts", + "version": "2.4.2", + "xo": { + "envs": [ + "node", + "mocha" + ], + "ignores": [ + "test/_flow.js" + ] + } +} \ No newline at end of file diff --git a/tools/node_modules/eslint/node_modules/@babel/highlight/node_modules/chalk/readme.md b/tools/node_modules/eslint/node_modules/@babel/highlight/node_modules/chalk/readme.md new file mode 100644 index 00000000000000..d298e2c48d64a0 --- /dev/null +++ b/tools/node_modules/eslint/node_modules/@babel/highlight/node_modules/chalk/readme.md @@ -0,0 +1,314 @@ +

+
+
+ Chalk +
+
+
+

+ +> Terminal string styling done right + +[![Build Status](https://travis-ci.org/chalk/chalk.svg?branch=master)](https://travis-ci.org/chalk/chalk) [![Coverage Status](https://coveralls.io/repos/github/chalk/chalk/badge.svg?branch=master)](https://coveralls.io/github/chalk/chalk?branch=master) [![](https://img.shields.io/badge/unicorn-approved-ff69b4.svg)](https://www.youtube.com/watch?v=9auOCbH5Ns4) [![XO code style](https://img.shields.io/badge/code_style-XO-5ed9c7.svg)](https://github.com/xojs/xo) [![Mentioned in Awesome Node.js](https://awesome.re/mentioned-badge.svg)](https://github.com/sindresorhus/awesome-nodejs) + +### [See what's new in Chalk 2](https://github.com/chalk/chalk/releases/tag/v2.0.0) + + + + +## Highlights + +- Expressive API +- Highly performant +- Ability to nest styles +- [256/Truecolor color support](#256-and-truecolor-color-support) +- Auto-detects color support +- Doesn't extend `String.prototype` +- Clean and focused +- Actively maintained +- [Used by ~23,000 packages](https://www.npmjs.com/browse/depended/chalk) as of December 31, 2017 + + +## Install + +```console +$ npm install chalk +``` + + + + + + +## Usage + +```js +const chalk = require('chalk'); + +console.log(chalk.blue('Hello world!')); +``` + +Chalk comes with an easy to use composable API where you just chain and nest the styles you want. + +```js +const chalk = require('chalk'); +const log = console.log; + +// Combine styled and normal strings +log(chalk.blue('Hello') + ' World' + chalk.red('!')); + +// Compose multiple styles using the chainable API +log(chalk.blue.bgRed.bold('Hello world!')); + +// Pass in multiple arguments +log(chalk.blue('Hello', 'World!', 'Foo', 'bar', 'biz', 'baz')); + +// Nest styles +log(chalk.red('Hello', chalk.underline.bgBlue('world') + '!')); + +// Nest styles of the same type even (color, underline, background) +log(chalk.green( + 'I am a green line ' + + chalk.blue.underline.bold('with a blue substring') + + ' that becomes green again!' +)); + +// ES2015 template literal +log(` +CPU: ${chalk.red('90%')} +RAM: ${chalk.green('40%')} +DISK: ${chalk.yellow('70%')} +`); + +// ES2015 tagged template literal +log(chalk` +CPU: {red ${cpu.totalPercent}%} +RAM: {green ${ram.used / ram.total * 100}%} +DISK: {rgb(255,131,0) ${disk.used / disk.total * 100}%} +`); + +// Use RGB colors in terminal emulators that support it. +log(chalk.keyword('orange')('Yay for orange colored text!')); +log(chalk.rgb(123, 45, 67).underline('Underlined reddish color')); +log(chalk.hex('#DEADED').bold('Bold gray!')); +``` + +Easily define your own themes: + +```js +const chalk = require('chalk'); + +const error = chalk.bold.red; +const warning = chalk.keyword('orange'); + +console.log(error('Error!')); +console.log(warning('Warning!')); +``` + +Take advantage of console.log [string substitution](https://nodejs.org/docs/latest/api/console.html#console_console_log_data_args): + +```js +const name = 'Sindre'; +console.log(chalk.green('Hello %s'), name); +//=> 'Hello Sindre' +``` + + +## API + +### chalk.`