From d3726936c18319403189a193cb77da4ec08707a0 Mon Sep 17 00:00:00 2001 From: Thomas Lamprecht Date: Sat, 6 Jun 2020 15:59:12 +0200 Subject: [PATCH] import and build new upstream release 7.2.0 Signed-off-by: Thomas Lamprecht --- Makefile | 2 +- eslint/.github/FUNDING.yml | 2 - eslint/.github/ISSUE_TEMPLATE/config.yml | 5 + eslint/CHANGELOG.md | 19 + eslint/CODE_OF_CONDUCT.md | 1 - eslint/CONTRIBUTING.md | 2 +- eslint/README.md | 4 +- .../developer-guide/working-with-rules.md | 2 +- eslint/docs/rules/no-extra-parens.md | 19 +- eslint/docs/rules/no-mixed-operators.md | 1 + eslint/lib/cli-engine/cli-engine.js | 4 +- eslint/lib/cli-engine/config-array-factory.js | 2 +- eslint/lib/init/config-initializer.js | 8 +- .../code-path-analysis/code-path-analyzer.js | 4 +- .../code-path-analysis/code-path-state.js | 46 +- eslint/lib/linter/config-comment-parser.js | 2 +- eslint/lib/rules/func-call-spacing.js | 21 +- eslint/lib/rules/keyword-spacing.js | 11 +- eslint/lib/rules/multiline-ternary.js | 69 ++- eslint/lib/rules/no-control-regex.js | 2 +- eslint/lib/rules/no-extra-boolean-cast.js | 3 + eslint/lib/rules/no-extra-parens.js | 32 +- eslint/lib/rules/no-invalid-regexp.js | 2 +- .../rules/no-misleading-character-class.js | 2 +- eslint/lib/rules/no-mixed-operators.js | 5 +- eslint/lib/rules/no-mixed-spaces-and-tabs.js | 20 +- eslint/lib/rules/no-regex-spaces.js | 2 +- eslint/lib/rules/no-restricted-exports.js | 6 + eslint/lib/rules/no-unneeded-ternary.js | 10 +- eslint/lib/rules/no-unused-expressions.js | 2 +- eslint/lib/rules/no-unused-vars.js | 4 +- eslint/lib/rules/no-useless-backreference.js | 2 +- .../lib/rules/prefer-named-capture-group.js | 2 +- eslint/lib/rules/quote-props.js | 4 +- eslint/lib/rules/template-tag-spacing.js | 10 +- eslint/lib/rules/utils/ast-utils.js | 58 ++- eslint/package.json | 10 +- eslint/tests/_utils/in-memory-fs.js | 2 +- .../logical--do-while-qq-1.js | 23 + .../logical--do-while-qq-2.js | 33 ++ .../logical--if-mix-and-qq-1.js | 33 ++ .../logical--if-mix-and-qq-2.js | 33 ++ .../logical--if-mix-or-qq-1.js | 33 ++ .../logical--if-mix-or-qq-2.js | 33 ++ .../code-path-analysis/logical--if-qq-1.js | 25 + .../code-path-analysis/logical--if-qq-2.js | 30 ++ .../code-path-analysis/logical--if-qq-3.js | 40 ++ .../code-path-analysis/logical--if-qq-4.js | 40 ++ .../code-path-analysis/logical--if-qq-5.js | 44 ++ .../code-path-analysis/logical--simple-3.js | 24 + .../code-path-analysis/logical--while-qq-1.js | 24 + .../code-path-analysis/logical--while-qq-2.js | 34 ++ eslint/tests/lib/cli-engine/cli-engine.js | 6 +- eslint/tests/lib/eslint/eslint.js | 6 +- eslint/tests/lib/init/config-initializer.js | 6 +- eslint/tests/lib/init/source-code-utils.js | 2 +- .../code-path-analysis/code-path-analyzer.js | 5 +- eslint/tests/lib/linter/linter.js | 20 +- eslint/tests/lib/rules/camelcase.js | 11 + eslint/tests/lib/rules/func-call-spacing.js | 163 +++++- eslint/tests/lib/rules/id-blacklist.js | 8 + eslint/tests/lib/rules/id-match.js | 11 + eslint/tests/lib/rules/keyword-spacing.js | 61 +++ eslint/tests/lib/rules/multiline-ternary.js | 467 +++++++++++++++++- .../tests/lib/rules/no-extra-boolean-cast.js | 13 + eslint/tests/lib/rules/no-extra-parens.js | 414 +++++++++++++++- eslint/tests/lib/rules/no-mixed-operators.js | 25 + .../lib/rules/no-mixed-spaces-and-tabs.js | 178 ++++++- .../tests/lib/rules/no-restricted-exports.js | 8 +- .../tests/lib/rules/no-restricted-imports.js | 28 +- eslint/tests/lib/rules/no-undef.js | 14 +- eslint/tests/lib/rules/no-unneeded-ternary.js | 12 + .../tests/lib/rules/no-unused-expressions.js | 4 + eslint/tests/lib/rules/no-unused-vars.js | 72 ++- eslint/tests/lib/rules/operator-linebreak.js | 10 + .../tests/lib/rules/template-tag-spacing.js | 306 ++++++++++-- eslint/tools/code-sample-minimizer.js | 2 +- src/eslint.js | 345 ++++++++++--- 78 files changed, 2757 insertions(+), 291 deletions(-) delete mode 100644 eslint/.github/FUNDING.yml create mode 100644 eslint/.github/ISSUE_TEMPLATE/config.yml delete mode 100644 eslint/CODE_OF_CONDUCT.md create mode 100644 eslint/tests/fixtures/code-path-analysis/logical--do-while-qq-1.js create mode 100644 eslint/tests/fixtures/code-path-analysis/logical--do-while-qq-2.js create mode 100644 eslint/tests/fixtures/code-path-analysis/logical--if-mix-and-qq-1.js create mode 100644 eslint/tests/fixtures/code-path-analysis/logical--if-mix-and-qq-2.js create mode 100644 eslint/tests/fixtures/code-path-analysis/logical--if-mix-or-qq-1.js create mode 100644 eslint/tests/fixtures/code-path-analysis/logical--if-mix-or-qq-2.js create mode 100644 eslint/tests/fixtures/code-path-analysis/logical--if-qq-1.js create mode 100644 eslint/tests/fixtures/code-path-analysis/logical--if-qq-2.js create mode 100644 eslint/tests/fixtures/code-path-analysis/logical--if-qq-3.js create mode 100644 eslint/tests/fixtures/code-path-analysis/logical--if-qq-4.js create mode 100644 eslint/tests/fixtures/code-path-analysis/logical--if-qq-5.js create mode 100644 eslint/tests/fixtures/code-path-analysis/logical--simple-3.js create mode 100644 eslint/tests/fixtures/code-path-analysis/logical--while-qq-1.js create mode 100644 eslint/tests/fixtures/code-path-analysis/logical--while-qq-2.js diff --git a/Makefile b/Makefile index 2dc6bd2..44a29a1 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ DSC=${PACKAGE}_${DEB_VERSION_UPSTREAM_REVISION}.dsc SRCDIR=src UPSTREAM=eslint -UPSTREAMTAG=v7.1.0 +UPSTREAMTAG=v7.2.0 BUILDSRC=${UPSTREAM}-${UPSTREAMTAG} all: ${DEB} diff --git a/eslint/.github/FUNDING.yml b/eslint/.github/FUNDING.yml deleted file mode 100644 index fec5535..0000000 --- a/eslint/.github/FUNDING.yml +++ /dev/null @@ -1,2 +0,0 @@ -github: eslint -open_collective: eslint diff --git a/eslint/.github/ISSUE_TEMPLATE/config.yml b/eslint/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..822fe54 --- /dev/null +++ b/eslint/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,5 @@ +blank_issues_enabled: false +contact_links: + - name: Breaking/Core change + url: https://github.com/eslint/rfcs#how-to-submit-an-rfc + about: Please submit an RFC here. diff --git a/eslint/CHANGELOG.md b/eslint/CHANGELOG.md index 3321fe6..52ff78d 100644 --- a/eslint/CHANGELOG.md +++ b/eslint/CHANGELOG.md @@ -1,3 +1,22 @@ +v7.2.0 - June 5, 2020 + +* [`b735a48`](https://github.com/eslint/eslint/commit/b735a485e77bcc791e4c4c6b8716801d94e98b2c) Update: add enforceForFunctionPrototypeMethods option to no-extra-parens (#12895) (Milos Djermanovic) +* [`27ef73f`](https://github.com/eslint/eslint/commit/27ef73ffb7428d5eff792d443186a2313e417bda) Update: reporter locr of func-call-spacing (refs #12334) (#13311) (Anix) +* [`353bfe9`](https://github.com/eslint/eslint/commit/353bfe9760ec640f470859855d4018df084a4e88) Update: handle parentheses in multiline-ternary (fixes #13195) (#13367) (Milos Djermanovic) +* [`a7fd343`](https://github.com/eslint/eslint/commit/a7fd343991cde99d8a219e3b25616db5792fe9a9) Update: keyword-spacing unexpected space loc improve (refs #12334) (#13377) (Anix) +* [`e49732e`](https://github.com/eslint/eslint/commit/e49732eb41bff6347ca7718c3c5ca1d13f1cd2d3) Fix: Ignore import expressions in no-unused-expressions rule (#13387) (Veniamin Krol) +* [`220349f`](https://github.com/eslint/eslint/commit/220349f5404060effe02fb5ec176a92e1383c3b5) Chore: Remove duplicate health files (#13380) (Nicholas C. Zakas) +* [`dd949ae`](https://github.com/eslint/eslint/commit/dd949aedb81fa772e10568920156daf075d25ea2) Update: support `??` operator, import.meta, and `export * as ns` (#13196) (Toru Nagashima) +* [`d5fce9f`](https://github.com/eslint/eslint/commit/d5fce9fa07e37ce61010a1fbb65964f1f7aefd82) Update: enable es2020 environment in --init (#13357) (Milos Djermanovic) +* [`21b1583`](https://github.com/eslint/eslint/commit/21b15832e326f96d349c063cd7e85e72c3abb670) Docs: fixed broken hash link for working-with-rules.md (#13386) (Yosuke Ota) +* [`b76aef7`](https://github.com/eslint/eslint/commit/b76aef778befb32afe7ad249934b132dc49713d2) Update: Improve report location for template-tag-spacing (refs #12334) (#13203) (Milos Djermanovic) +* [`578efad`](https://github.com/eslint/eslint/commit/578efad331b797e28c0f5f1547ce4769d2ea23ee) Chore: update no-unused-vars caughtErrors in eslint-config-eslint (#13351) (Milos Djermanovic) +* [`426088c`](https://github.com/eslint/eslint/commit/426088c966dc79dc338b33100f3adf827b147d69) Fix: no-unused-vars updated location to last reference (fixes #13181) (#13354) (Anix) +* [`cb50b69`](https://github.com/eslint/eslint/commit/cb50b69c08d4393e32d5c42c537d769c51dd34d8) Update: Improve location for no-mixed-spaces-and-tabs (refs #12334) (#13365) (Milos Djermanovic) +* [`f858f2a`](https://github.com/eslint/eslint/commit/f858f2a8f83232484491bd90b0bc5001b5056ad0) Chore: Add Tidelift to funding.yml (#13371) (Nicholas C. Zakas) +* [`ee30e5d`](https://github.com/eslint/eslint/commit/ee30e5d8bb1a4c82a2a3fbe1b9ee9f979b55c5c4) Sponsors: Sync README with website (ESLint Jenkins) +* [`c29bd9f`](https://github.com/eslint/eslint/commit/c29bd9f75582e5b1a403a8ffd0aafd1ffc8c58e1) Chore: Add breaking/core change link to issue templates (#13344) (Kai Cataldo) +* [`d55490f`](https://github.com/eslint/eslint/commit/d55490fa73ff69416de375e4c1cd67b6edba531c) Sponsors: Sync README with website (ESLint Jenkins) v7.1.0 - May 22, 2020 * [`a93083a`](https://github.com/eslint/eslint/commit/a93083af89c6f9714dcdd4a7f27c8655a0b0dba6) Fix: astUtils.getNextLocation returns invalid location after CRLF (#13275) (Milos Djermanovic) diff --git a/eslint/CODE_OF_CONDUCT.md b/eslint/CODE_OF_CONDUCT.md deleted file mode 100644 index 2fc80dd..0000000 --- a/eslint/CODE_OF_CONDUCT.md +++ /dev/null @@ -1 +0,0 @@ -This project adheres to the [JS Foundation Code of Conduct](https://js.foundation/community/code-of-conduct). diff --git a/eslint/CONTRIBUTING.md b/eslint/CONTRIBUTING.md index d0db77c..9260dfe 100644 --- a/eslint/CONTRIBUTING.md +++ b/eslint/CONTRIBUTING.md @@ -4,7 +4,7 @@ Please be sure to read the contribution guidelines before making or requesting a ## Code of Conduct -This project adheres to the [JS Foundation Code of Conduct](https://js.foundation/community/code-of-conduct). We kindly request that you read over our code of conduct before contributing. +This project adheres to the [Open JS Foundation Code of Conduct](https://eslint.org/conduct). We kindly request that you read over our code of conduct before contributing. ## Filing Issues diff --git a/eslint/README.md b/eslint/README.md index 1838496..0cb3963 100644 --- a/eslint/README.md +++ b/eslint/README.md @@ -250,8 +250,8 @@ The following companies, organizations, and individuals support ESLint's ongoing

Gold Sponsors

Shopify Salesforce Airbnb

Silver Sponsors

-

AMP Project

Bronze Sponsors

-

Bruce EduBirdie CasinoTop.com Casino Topp Writers Per Hour Anagram Solver vpn netflix Kasinot.fi Pelisivut Nettikasinot.org BonusFinder Deutschland Bugsnag Stability Monitoring Mixpanel VPS Server Free Icons by Icons8 Discord ThemeIsle TekHattan Marfeel Fire Stick Tricks

+

Liftoff AMP Project

Bronze Sponsors

+

Bruce EduBirdie CasinoTop.com Casino Topp Writers Per Hour Anagram Solver vpn netflix Kasinot.fi Pelisivut Nettikasinot.org BonusFinder Deutschland Bugsnag Stability Monitoring Mixpanel VPS Server Free Icons by Icons8 Discord ThemeIsle TekHattan Marfeel Fire Stick Tricks

## Technology Sponsors diff --git a/eslint/docs/developer-guide/working-with-rules.md b/eslint/docs/developer-guide/working-with-rules.md index 608a38b..17058b4 100644 --- a/eslint/docs/developer-guide/working-with-rules.md +++ b/eslint/docs/developer-guide/working-with-rules.md @@ -140,7 +140,7 @@ Additionally, the `context` object has the following methods: * Otherwise, if the node does not declare any variables, an empty array is returned. * `getFilename()` - returns the filename associated with the source. * `getScope()` - returns the [scope](./scope-manager-interface.md#scope-interface) of the currently-traversed node. This information can be used to track references to variables. -* `getSourceCode()` - returns a [`SourceCode`](#contextgetsourcecode) object that you can use to work with the source that was passed to ESLint. +* `getSourceCode()` - returns a [`SourceCode`](#context-getsourcecode) object that you can use to work with the source that was passed to ESLint. * `markVariableAsUsed(name)` - marks a variable with the given name in the current scope as used. This affects the [no-unused-vars](../rules/no-unused-vars.md) rule. Returns `true` if a variable with the given name was found and marked as used, otherwise `false`. * `report(descriptor)` - reports a problem in the code (see the [dedicated section](#context-report)). diff --git a/eslint/docs/rules/no-extra-parens.md b/eslint/docs/rules/no-extra-parens.md index 4cadaa7..68b986e 100644 --- a/eslint/docs/rules/no-extra-parens.md +++ b/eslint/docs/rules/no-extra-parens.md @@ -7,7 +7,7 @@ This rule restricts the use of parentheses to only where they are necessary. This rule always ignores extra parentheses around the following: * RegExp literals such as `(/abc/).test(var)` to avoid conflicts with the [wrap-regex](wrap-regex.md) rule -* immediately-invoked function expressions (also known as IIFEs) such as `var x = (function () {})();` and `((function foo() {return 1;})())` to avoid conflicts with the [wrap-iife](wrap-iife.md) rule +* immediately-invoked function expressions (also known as IIFEs) such as `var x = (function () {})();` and `var x = (function () {}());` to avoid conflicts with the [wrap-iife](wrap-iife.md) rule * arrow function arguments to avoid conflicts with the [arrow-parens](arrow-parens.md) rule ## Options @@ -26,6 +26,7 @@ This rule has an object option for exceptions to the `"all"` option: * `"enforceForArrowConditionals": false` allows extra parentheses around ternary expressions which are the body of an arrow function * `"enforceForSequenceExpressions": false` allows extra parentheses around sequence expressions * `"enforceForNewInMemberExpressions": false` allows extra parentheses around `new` expressions in member expressions +* `"enforceForFunctionPrototypeMethods": false` allows extra parentheses around immediate `.call` and `.apply` method calls on function expressions and around function expressions in the same context. ### all @@ -222,6 +223,22 @@ const quux = (new Bar())[baz]; (new Bar()).doSomething(); ``` +### enforceForFunctionPrototypeMethods + +Examples of **correct** code for this rule with the `"all"` and `{ "enforceForFunctionPrototypeMethods": false }` options: + +```js +/* eslint no-extra-parens: ["error", "all", { "enforceForFunctionPrototypeMethods": false }] */ + +const foo = (function () {}).call(); + +const bar = (function () {}).apply(); + +const baz = (function () {}.call()); + +const quux = (function () {}.apply()); +``` + ### functions Examples of **incorrect** code for this rule with the `"functions"` option: diff --git a/eslint/docs/rules/no-mixed-operators.md b/eslint/docs/rules/no-mixed-operators.md index 3206d18..674a847 100644 --- a/eslint/docs/rules/no-mixed-operators.md +++ b/eslint/docs/rules/no-mixed-operators.md @@ -100,6 +100,7 @@ The following operators can be used in `groups` option: * Bitwise Operators: `"&"`, `"|"`, `"^"`, `"~"`, `"<<"`, `">>"`, `">>>"` * Comparison Operators: `"=="`, `"!="`, `"==="`, `"!=="`, `">"`, `">="`, `"<"`, `"<="` * Logical Operators: `"&&"`, `"||"` +* Coalesce Operator: `"??"` * Relational Operators: `"in"`, `"instanceof"` * Ternary Operator: `?:` diff --git a/eslint/lib/cli-engine/cli-engine.js b/eslint/lib/cli-engine/cli-engine.js index b6aa995..802a405 100644 --- a/eslint/lib/cli-engine/cli-engine.js +++ b/eslint/lib/cli-engine/cli-engine.js @@ -403,7 +403,7 @@ function getCacheFile(cacheFile, cwd) { try { fileStats = fs.lstatSync(resolvedCacheFile); - } catch (ex) { + } catch { fileStats = null; } @@ -991,7 +991,7 @@ class CLIEngine { const npmFormat = naming.normalizePackageName(normalizedFormatName, "eslint-formatter"); formatterPath = ModuleResolver.resolve(npmFormat, path.join(cwd, "__placeholder__.js")); - } catch (e) { + } catch { formatterPath = path.resolve(__dirname, "formatters", normalizedFormatName); } } diff --git a/eslint/lib/cli-engine/config-array-factory.js b/eslint/lib/cli-engine/config-array-factory.js index fa3fdb3..7c0fba6 100644 --- a/eslint/lib/cli-engine/config-array-factory.js +++ b/eslint/lib/cli-engine/config-array-factory.js @@ -517,7 +517,7 @@ class ConfigArrayFactory { try { loadPackageJSONConfigFile(filePath); return filePath; - } catch (error) { /* ignore */ } + } catch { /* ignore */ } } else { return filePath; } diff --git a/eslint/lib/init/config-initializer.js b/eslint/lib/init/config-initializer.js index 00f1767..dce3994 100644 --- a/eslint/lib/init/config-initializer.js +++ b/eslint/lib/init/config-initializer.js @@ -265,11 +265,7 @@ function processAnswers(answers) { }; config.parserOptions.ecmaVersion = espree.latestEcmaVersion; - config.env.es6 = true; - config.globals = { - Atomics: "readonly", - SharedArrayBuffer: "readonly" - }; + config.env.es2020 = true; // set the module type if (answers.moduleType === "esm") { @@ -350,7 +346,7 @@ function getLocalESLintVersion() { const eslint = require(eslintPath); return eslint.linter.version || null; - } catch (_err) { + } catch { return null; } } diff --git a/eslint/lib/linter/code-path-analysis/code-path-analyzer.js b/eslint/lib/linter/code-path-analysis/code-path-analyzer.js index 8a623e3..b612cf4 100644 --- a/eslint/lib/linter/code-path-analysis/code-path-analyzer.js +++ b/eslint/lib/linter/code-path-analysis/code-path-analyzer.js @@ -33,10 +33,10 @@ function isCaseNode(node) { * Checks whether the given logical operator is taken into account for the code * path analysis. * @param {string} operator The operator found in the LogicalExpression node - * @returns {boolean} `true` if the operator is "&&" or "||" + * @returns {boolean} `true` if the operator is "&&" or "||" or "??" */ function isHandledLogicalOperator(operator) { - return operator === "&&" || operator === "||"; + return operator === "&&" || operator === "||" || operator === "??"; } /** diff --git a/eslint/lib/linter/code-path-analysis/code-path-state.js b/eslint/lib/linter/code-path-analysis/code-path-state.js index 75de1bc..9e76060 100644 --- a/eslint/lib/linter/code-path-analysis/code-path-state.js +++ b/eslint/lib/linter/code-path-analysis/code-path-state.js @@ -201,6 +201,7 @@ function finalizeTestSegmentsOfFor(context, choiceContext, head) { if (!choiceContext.processed) { choiceContext.trueForkContext.add(head); choiceContext.falseForkContext.add(head); + choiceContext.qqForkContext.add(head); } if (context.test !== true) { @@ -351,6 +352,7 @@ class CodePathState { isForkingAsResult, trueForkContext: ForkContext.newEmpty(this.forkContext), falseForkContext: ForkContext.newEmpty(this.forkContext), + qqForkContext: ForkContext.newEmpty(this.forkContext), processed: false }; } @@ -370,6 +372,7 @@ class CodePathState { switch (context.kind) { case "&&": case "||": + case "??": /* * If any result were not transferred from child contexts, @@ -379,6 +382,7 @@ class CodePathState { if (!context.processed) { context.trueForkContext.add(headSegments); context.falseForkContext.add(headSegments); + context.qqForkContext.add(headSegments); } /* @@ -390,6 +394,7 @@ class CodePathState { parentContext.trueForkContext.addAll(context.trueForkContext); parentContext.falseForkContext.addAll(context.falseForkContext); + parentContext.qqForkContext.addAll(context.qqForkContext); parentContext.processed = true; return context; @@ -456,13 +461,24 @@ class CodePathState { * This got segments already from the child choice context. * Creates the next path from own true/false fork context. */ - const prevForkContext = - context.kind === "&&" ? context.trueForkContext - /* kind === "||" */ : context.falseForkContext; + let prevForkContext; + + switch (context.kind) { + case "&&": // if true then go to the right-hand side. + prevForkContext = context.trueForkContext; + break; + case "||": // if false then go to the right-hand side. + prevForkContext = context.falseForkContext; + break; + case "??": // Both true/false can short-circuit, so needs the third path to go to the right-hand side. That's qqForkContext. + prevForkContext = context.qqForkContext; + break; + default: + throw new Error("unreachable"); + } forkContext.replaceHead(prevForkContext.makeNext(0, -1)); prevForkContext.clear(); - context.processed = false; } else { @@ -471,14 +487,19 @@ class CodePathState { * So addresses the head segments. * The head segments are the path of the left-hand operand. */ - if (context.kind === "&&") { - - // The path does short-circuit if false. - context.falseForkContext.add(forkContext.head); - } else { - - // The path does short-circuit if true. - context.trueForkContext.add(forkContext.head); + switch (context.kind) { + case "&&": // the false path can short-circuit. + context.falseForkContext.add(forkContext.head); + break; + case "||": // the true path can short-circuit. + context.trueForkContext.add(forkContext.head); + break; + case "??": // both can short-circuit. + context.trueForkContext.add(forkContext.head); + context.falseForkContext.add(forkContext.head); + break; + default: + throw new Error("unreachable"); } forkContext.replaceHead(forkContext.makeNext(-1, -1)); @@ -501,6 +522,7 @@ class CodePathState { if (!context.processed) { context.trueForkContext.add(forkContext.head); context.falseForkContext.add(forkContext.head); + context.qqForkContext.add(forkContext.head); } context.processed = false; diff --git a/eslint/lib/linter/config-comment-parser.js b/eslint/lib/linter/config-comment-parser.js index 3586231..067d024 100644 --- a/eslint/lib/linter/config-comment-parser.js +++ b/eslint/lib/linter/config-comment-parser.js @@ -78,7 +78,7 @@ module.exports = class ConfigCommentParser { config: items }; } - } catch (ex) { + } catch { debug("Levn parsing failed; falling back to manual parsing."); diff --git a/eslint/lib/rules/func-call-spacing.js b/eslint/lib/rules/func-call-spacing.js index dccdd0a..5ecb63e 100644 --- a/eslint/lib/rules/func-call-spacing.js +++ b/eslint/lib/rules/func-call-spacing.js @@ -116,7 +116,13 @@ module.exports = { if (never && hasWhitespace) { context.report({ node, - loc: leftToken.loc.start, + loc: { + start: leftToken.loc.end, + end: { + line: rightToken.loc.start.line, + column: rightToken.loc.start.column - 1 + } + }, messageId: "unexpectedWhitespace", fix(fixer) { @@ -134,7 +140,13 @@ module.exports = { } else if (!never && !hasWhitespace) { context.report({ node, - loc: leftToken.loc.start, + loc: { + start: { + line: leftToken.loc.end.line, + column: leftToken.loc.end.column - 1 + }, + end: rightToken.loc.start + }, messageId: "missing", fix(fixer) { return fixer.insertTextBefore(rightToken, " "); @@ -143,7 +155,10 @@ module.exports = { } else if (!never && !allowNewlines && hasNewline) { context.report({ node, - loc: leftToken.loc.start, + loc: { + start: leftToken.loc.end, + end: rightToken.loc.start + }, messageId: "unexpectedNewline", fix(fixer) { return fixer.replaceTextRange([leftToken.range[1], rightToken.range[0]], " "); diff --git a/eslint/lib/rules/keyword-spacing.js b/eslint/lib/rules/keyword-spacing.js index 2b3fef3..99979a3 100644 --- a/eslint/lib/rules/keyword-spacing.js +++ b/eslint/lib/rules/keyword-spacing.js @@ -152,7 +152,7 @@ module.exports = { sourceCode.isSpaceBetweenTokens(prevToken, token) ) { context.report({ - loc: token.loc.start, + loc: { start: prevToken.loc.end, end: token.loc.start }, messageId: "unexpectedBefore", data: token, fix(fixer) { @@ -203,8 +203,9 @@ module.exports = { astUtils.isTokenOnSameLine(token, nextToken) && sourceCode.isSpaceBetweenTokens(token, nextToken) ) { + context.report({ - loc: token.loc.start, + loc: { start: token.loc.end, end: nextToken.loc.start }, messageId: "unexpectedAfter", data: token, fix(fixer) { @@ -442,6 +443,12 @@ module.exports = { checkSpacingAround(sourceCode.getTokenAfter(firstToken)); } + if (node.type === "ExportAllDeclaration" && node.exported) { + const asToken = sourceCode.getTokenBefore(node.exported); + + checkSpacingBefore(asToken, PREV_TOKEN_M); + } + if (node.source) { const fromToken = sourceCode.getTokenBefore(node.source); diff --git a/eslint/lib/rules/multiline-ternary.js b/eslint/lib/rules/multiline-ternary.js index 1df90b6..6668bff 100644 --- a/eslint/lib/rules/multiline-ternary.js +++ b/eslint/lib/rules/multiline-ternary.js @@ -39,25 +39,7 @@ module.exports = { const option = context.options[0]; const multiline = option !== "never"; const allowSingleLine = option === "always-multiline"; - - //-------------------------------------------------------------------------- - // Helpers - //-------------------------------------------------------------------------- - - /** - * Tests whether node is preceded by supplied tokens - * @param {ASTNode} node node to check - * @param {ASTNode} parentNode parent of node to report - * @param {boolean} expected whether newline was expected or not - * @returns {void} - * @private - */ - function reportError(node, parentNode, expected) { - context.report({ - node, - messageId: `${expected ? "expected" : "unexpected"}${node === parentNode.test ? "TestCons" : "ConsAlt"}` - }); - } + const sourceCode = context.getSourceCode(); //-------------------------------------------------------------------------- // Public @@ -65,16 +47,39 @@ module.exports = { return { ConditionalExpression(node) { - const areTestAndConsequentOnSameLine = astUtils.isTokenOnSameLine(node.test, node.consequent); - const areConsequentAndAlternateOnSameLine = astUtils.isTokenOnSameLine(node.consequent, node.alternate); + const questionToken = sourceCode.getTokenAfter(node.test, astUtils.isNotClosingParenToken); + const colonToken = sourceCode.getTokenAfter(node.consequent, astUtils.isNotClosingParenToken); + + const firstTokenOfTest = sourceCode.getFirstToken(node); + const lastTokenOfTest = sourceCode.getTokenBefore(questionToken); + const firstTokenOfConsequent = sourceCode.getTokenAfter(questionToken); + const lastTokenOfConsequent = sourceCode.getTokenBefore(colonToken); + const firstTokenOfAlternate = sourceCode.getTokenAfter(colonToken); + + const areTestAndConsequentOnSameLine = astUtils.isTokenOnSameLine(lastTokenOfTest, firstTokenOfConsequent); + const areConsequentAndAlternateOnSameLine = astUtils.isTokenOnSameLine(lastTokenOfConsequent, firstTokenOfAlternate); if (!multiline) { if (!areTestAndConsequentOnSameLine) { - reportError(node.test, node, false); + context.report({ + node: node.test, + loc: { + start: firstTokenOfTest.loc.start, + end: lastTokenOfTest.loc.end + }, + messageId: "unexpectedTestCons" + }); } if (!areConsequentAndAlternateOnSameLine) { - reportError(node.consequent, node, false); + context.report({ + node: node.consequent, + loc: { + start: firstTokenOfConsequent.loc.start, + end: lastTokenOfConsequent.loc.end + }, + messageId: "unexpectedConsAlt" + }); } } else { if (allowSingleLine && node.loc.start.line === node.loc.end.line) { @@ -82,11 +87,25 @@ module.exports = { } if (areTestAndConsequentOnSameLine) { - reportError(node.test, node, true); + context.report({ + node: node.test, + loc: { + start: firstTokenOfTest.loc.start, + end: lastTokenOfTest.loc.end + }, + messageId: "expectedTestCons" + }); } if (areConsequentAndAlternateOnSameLine) { - reportError(node.consequent, node, true); + context.report({ + node: node.consequent, + loc: { + start: firstTokenOfConsequent.loc.start, + end: lastTokenOfConsequent.loc.end + }, + messageId: "expectedConsAlt" + }); } } } diff --git a/eslint/lib/rules/no-control-regex.js b/eslint/lib/rules/no-control-regex.js index b39f731..146c4f2 100644 --- a/eslint/lib/rules/no-control-regex.js +++ b/eslint/lib/rules/no-control-regex.js @@ -35,7 +35,7 @@ const collector = new (class { try { this._source = regexpStr; this._validator.validatePattern(regexpStr); // Call onCharacter hook - } catch (err) { + } catch { // Ignore syntax errors in RegExp. } diff --git a/eslint/lib/rules/no-extra-boolean-cast.js b/eslint/lib/rules/no-extra-boolean-cast.js index aba8e63..b90757b 100644 --- a/eslint/lib/rules/no-extra-boolean-cast.js +++ b/eslint/lib/rules/no-extra-boolean-cast.js @@ -172,6 +172,9 @@ module.exports = { case "UnaryExpression": return precedence(node) < precedence(parent); case "LogicalExpression": + if (astUtils.isMixedLogicalAndCoalesceExpressions(node, parent)) { + return true; + } if (previousNode === parent.left) { return precedence(node) < precedence(parent); } diff --git a/eslint/lib/rules/no-extra-parens.js b/eslint/lib/rules/no-extra-parens.js index 7cbb752..bae1a49 100644 --- a/eslint/lib/rules/no-extra-parens.js +++ b/eslint/lib/rules/no-extra-parens.js @@ -51,7 +51,8 @@ module.exports = { ignoreJSX: { enum: ["none", "all", "single-line", "multi-line"] }, enforceForArrowConditionals: { type: "boolean" }, enforceForSequenceExpressions: { type: "boolean" }, - enforceForNewInMemberExpressions: { type: "boolean" } + enforceForNewInMemberExpressions: { type: "boolean" }, + enforceForFunctionPrototypeMethods: { type: "boolean" } }, additionalProperties: false } @@ -83,12 +84,28 @@ module.exports = { context.options[1].enforceForSequenceExpressions === false; const IGNORE_NEW_IN_MEMBER_EXPR = ALL_NODES && context.options[1] && context.options[1].enforceForNewInMemberExpressions === false; + const IGNORE_FUNCTION_PROTOTYPE_METHODS = ALL_NODES && context.options[1] && + context.options[1].enforceForFunctionPrototypeMethods === false; const PRECEDENCE_OF_ASSIGNMENT_EXPR = precedence({ type: "AssignmentExpression" }); const PRECEDENCE_OF_UPDATE_EXPR = precedence({ type: "UpdateExpression" }); let reportsBuffer; + /** + * Determines whether the given node is a `call` or `apply` method call, invoked directly on a `FunctionExpression` node. + * Example: function(){}.call() + * @param {ASTNode} node The node to be checked. + * @returns {boolean} True if the node is an immediate `call` or `apply` method call. + * @private + */ + function isImmediateFunctionPrototypeMethodCall(node) { + return node.type === "CallExpression" && + node.callee.type === "MemberExpression" && + node.callee.object.type === "FunctionExpression" && + ["call", "apply"].includes(astUtils.getStaticPropertyName(node.callee)); + } + /** * Determines if this rule should be enforced for a node given the current configuration. * @param {ASTNode} node The node to be checked. @@ -125,6 +142,10 @@ module.exports = { return false; } + if (isImmediateFunctionPrototypeMethodCall(node) && IGNORE_FUNCTION_PROTOTYPE_METHODS) { + return false; + } + return ALL_NODES || node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression"; } @@ -478,6 +499,7 @@ module.exports = { if (!shouldSkipLeft && hasExcessParens(node.left)) { if ( !(node.left.type === "UnaryExpression" && isExponentiation) && + !astUtils.isMixedLogicalAndCoalesceExpressions(node.left, node) && (leftPrecedence > prec || (leftPrecedence === prec && !isExponentiation)) || isParenthesisedTwice(node.left) ) { @@ -487,6 +509,7 @@ module.exports = { if (!shouldSkipRight && hasExcessParens(node.right)) { if ( + !astUtils.isMixedLogicalAndCoalesceExpressions(node.right, node) && (rightPrecedence > prec || (rightPrecedence === prec && isExponentiation)) || isParenthesisedTwice(node.right) ) { @@ -927,7 +950,12 @@ module.exports = { LogicalExpression: checkBinaryLogical, MemberExpression(node) { - const nodeObjHasExcessParens = hasExcessParens(node.object); + const nodeObjHasExcessParens = hasExcessParens(node.object) && + !( + isImmediateFunctionPrototypeMethodCall(node.parent) && + node.parent.callee === node && + IGNORE_FUNCTION_PROTOTYPE_METHODS + ); if ( nodeObjHasExcessParens && diff --git a/eslint/lib/rules/no-invalid-regexp.js b/eslint/lib/rules/no-invalid-regexp.js index c09e36f..48b7188 100644 --- a/eslint/lib/rules/no-invalid-regexp.js +++ b/eslint/lib/rules/no-invalid-regexp.js @@ -93,7 +93,7 @@ module.exports = { try { validator.validateFlags(flags); return null; - } catch (err) { + } catch { return `Invalid flags supplied to RegExp constructor '${flags}'`; } } diff --git a/eslint/lib/rules/no-misleading-character-class.js b/eslint/lib/rules/no-misleading-character-class.js index 9315ba6..3d00461 100644 --- a/eslint/lib/rules/no-misleading-character-class.js +++ b/eslint/lib/rules/no-misleading-character-class.js @@ -147,7 +147,7 @@ module.exports = { pattern.length, flags.includes("u") ); - } catch (e) { + } catch { // Ignore regular expressions with syntax errors return; diff --git a/eslint/lib/rules/no-mixed-operators.js b/eslint/lib/rules/no-mixed-operators.js index 37e8906..f0290e9 100644 --- a/eslint/lib/rules/no-mixed-operators.js +++ b/eslint/lib/rules/no-mixed-operators.js @@ -21,13 +21,15 @@ const COMPARISON_OPERATORS = ["==", "!=", "===", "!==", ">", ">=", "<", "<="]; const LOGICAL_OPERATORS = ["&&", "||"]; const RELATIONAL_OPERATORS = ["in", "instanceof"]; const TERNARY_OPERATOR = ["?:"]; +const COALESCE_OPERATOR = ["??"]; const ALL_OPERATORS = [].concat( ARITHMETIC_OPERATORS, BITWISE_OPERATORS, COMPARISON_OPERATORS, LOGICAL_OPERATORS, RELATIONAL_OPERATORS, - TERNARY_OPERATOR + TERNARY_OPERATOR, + COALESCE_OPERATOR ); const DEFAULT_GROUPS = [ ARITHMETIC_OPERATORS, @@ -236,7 +238,6 @@ module.exports = { return { BinaryExpression: check, LogicalExpression: check - }; } }; diff --git a/eslint/lib/rules/no-mixed-spaces-and-tabs.js b/eslint/lib/rules/no-mixed-spaces-and-tabs.js index 16c2bd4..287cbda 100644 --- a/eslint/lib/rules/no-mixed-spaces-and-tabs.js +++ b/eslint/lib/rules/no-mixed-spaces-and-tabs.js @@ -67,7 +67,7 @@ module.exports = { * or the reverse before non-tab/-space * characters begin. */ - let regex = /^(?=[\t ]*(\t | \t))/u; + let regex = /^(?=( +|\t+))\1(?:\t| )/u; if (smartTabs) { @@ -75,19 +75,27 @@ module.exports = { * At least one space followed by a tab * before non-tab/-space characters begin. */ - regex = /^(?=[\t ]* \t)/u; + regex = /^(?=(\t*))\1(?=( +))\2\t/u; } lines.forEach((line, i) => { const match = regex.exec(line); if (match) { - const lineNumber = i + 1, - column = match.index + 1, - loc = { line: lineNumber, column }; + const lineNumber = i + 1; + const loc = { + start: { + line: lineNumber, + column: match[0].length - 2 + }, + end: { + line: lineNumber, + column: match[0].length + } + }; if (!ignoredCommentLines.has(lineNumber)) { - const containingNode = sourceCode.getNodeByRangeIndex(sourceCode.getIndexFromLoc(loc)); + const containingNode = sourceCode.getNodeByRangeIndex(sourceCode.getIndexFromLoc(loc.start)); if (!(containingNode && ["Literal", "TemplateElement"].includes(containingNode.type))) { context.report({ diff --git a/eslint/lib/rules/no-regex-spaces.js b/eslint/lib/rules/no-regex-spaces.js index afb26d7..e6d4c9e 100644 --- a/eslint/lib/rules/no-regex-spaces.js +++ b/eslint/lib/rules/no-regex-spaces.js @@ -76,7 +76,7 @@ module.exports = { try { regExpAST = regExpParser.parsePattern(pattern, 0, pattern.length, flags.includes("u")); - } catch (e) { + } catch { // Ignore regular expressions with syntax errors return; diff --git a/eslint/lib/rules/no-restricted-exports.js b/eslint/lib/rules/no-restricted-exports.js index 5b5c7d9..6031e26 100644 --- a/eslint/lib/rules/no-restricted-exports.js +++ b/eslint/lib/rules/no-restricted-exports.js @@ -61,6 +61,12 @@ module.exports = { } return { + ExportAllDeclaration(node) { + if (node.exported) { + checkExportedName(node.exported); + } + }, + ExportNamedDeclaration(node) { const declaration = node.declaration; diff --git a/eslint/lib/rules/no-unneeded-ternary.js b/eslint/lib/rules/no-unneeded-ternary.js index d4438e2..0fefc42 100644 --- a/eslint/lib/rules/no-unneeded-ternary.js +++ b/eslint/lib/rules/no-unneeded-ternary.js @@ -147,10 +147,12 @@ module.exports = { loc: node.consequent.loc.start, messageId: "unnecessaryConditionalAssignment", fix: fixer => { - const shouldParenthesizeAlternate = ( - astUtils.getPrecedence(node.alternate) < OR_PRECEDENCE && - !astUtils.isParenthesised(sourceCode, node.alternate) - ); + const shouldParenthesizeAlternate = + ( + astUtils.getPrecedence(node.alternate) < OR_PRECEDENCE || + astUtils.isCoalesceExpression(node.alternate) + ) && + !astUtils.isParenthesised(sourceCode, node.alternate); const alternateText = shouldParenthesizeAlternate ? `(${sourceCode.getText(node.alternate)})` : astUtils.getParenthesisedText(sourceCode, node.alternate); diff --git a/eslint/lib/rules/no-unused-expressions.js b/eslint/lib/rules/no-unused-expressions.js index 26a25b7..8c049f5 100644 --- a/eslint/lib/rules/no-unused-expressions.js +++ b/eslint/lib/rules/no-unused-expressions.js @@ -124,7 +124,7 @@ module.exports = { return true; } - return /^(?:Assignment|Call|New|Update|Yield|Await)Expression$/u.test(node.type) || + return /^(?:Assignment|Call|New|Update|Yield|Await|Import)Expression$/u.test(node.type) || (node.type === "UnaryExpression" && ["delete", "void"].indexOf(node.operator) >= 0); } diff --git a/eslint/lib/rules/no-unused-vars.js b/eslint/lib/rules/no-unused-vars.js index 18c48bf..50dcab4 100644 --- a/eslint/lib/rules/no-unused-vars.js +++ b/eslint/lib/rules/no-unused-vars.js @@ -619,7 +619,9 @@ module.exports = { // Report the first declaration. if (unusedVar.defs.length > 0) { context.report({ - node: unusedVar.identifiers[0], + node: unusedVar.references.length ? unusedVar.references[ + unusedVar.references.length - 1 + ].identifier : unusedVar.identifiers[0], messageId: "unusedVar", data: unusedVar.references.some(ref => ref.isWrite()) ? getAssignedMessageData(unusedVar) diff --git a/eslint/lib/rules/no-useless-backreference.js b/eslint/lib/rules/no-useless-backreference.js index 8a6fbe1..958e3d5 100644 --- a/eslint/lib/rules/no-useless-backreference.js +++ b/eslint/lib/rules/no-useless-backreference.js @@ -95,7 +95,7 @@ module.exports = { try { regExpAST = parser.parsePattern(pattern, 0, pattern.length, flags.includes("u")); - } catch (e) { + } catch { // Ignore regular expressions with syntax errors return; diff --git a/eslint/lib/rules/prefer-named-capture-group.js b/eslint/lib/rules/prefer-named-capture-group.js index c8af043..7d0aa3f 100644 --- a/eslint/lib/rules/prefer-named-capture-group.js +++ b/eslint/lib/rules/prefer-named-capture-group.js @@ -59,7 +59,7 @@ module.exports = { try { ast = parser.parsePattern(pattern, 0, pattern.length, uFlag); - } catch (_) { + } catch { // ignore regex syntax errors return; diff --git a/eslint/lib/rules/quote-props.js b/eslint/lib/rules/quote-props.js index a2a4e1d..fab7bdc 100644 --- a/eslint/lib/rules/quote-props.js +++ b/eslint/lib/rules/quote-props.js @@ -154,7 +154,7 @@ module.exports = { try { tokens = espree.tokenize(key.value); - } catch (e) { + } catch { return; } @@ -239,7 +239,7 @@ module.exports = { try { tokens = espree.tokenize(key.value); - } catch (e) { + } catch { necessaryQuotes = true; return; } diff --git a/eslint/lib/rules/template-tag-spacing.js b/eslint/lib/rules/template-tag-spacing.js index 9eb6d86..16f5862 100644 --- a/eslint/lib/rules/template-tag-spacing.js +++ b/eslint/lib/rules/template-tag-spacing.js @@ -49,7 +49,10 @@ module.exports = { if (never && hasWhitespace) { context.report({ node, - loc: tagToken.loc.start, + loc: { + start: tagToken.loc.end, + end: literalToken.loc.start + }, messageId: "unexpected", fix(fixer) { const comments = sourceCode.getCommentsBefore(node.quasi); @@ -68,7 +71,10 @@ module.exports = { } else if (!never && !hasWhitespace) { context.report({ node, - loc: tagToken.loc.start, + loc: { + start: node.loc.start, + end: literalToken.loc.start + }, messageId: "missing", fix(fixer) { return fixer.insertTextAfter(tagToken, " "); diff --git a/eslint/lib/rules/utils/ast-utils.js b/eslint/lib/rules/utils/ast-utils.js index 83ecf69..ecea694 100644 --- a/eslint/lib/rules/utils/ast-utils.js +++ b/eslint/lib/rules/utils/ast-utils.js @@ -416,6 +416,53 @@ function equalTokens(left, right, sourceCode) { return true; } +/** + * Check if the given node is a true logical expression or not. + * + * The three binary expressions logical-or (`||`), logical-and (`&&`), and + * coalesce (`??`) are known as `ShortCircuitExpression`. + * But ESTree represents those by `LogicalExpression` node. + * + * This function rejects coalesce expressions of `LogicalExpression` node. + * @param {ASTNode} node The node to check. + * @returns {boolean} `true` if the node is `&&` or `||`. + * @see https://tc39.es/ecma262/#prod-ShortCircuitExpression + */ +function isLogicalExpression(node) { + return ( + node.type === "LogicalExpression" && + (node.operator === "&&" || node.operator === "||") + ); +} + +/** + * Check if the given node is a nullish coalescing expression or not. + * + * The three binary expressions logical-or (`||`), logical-and (`&&`), and + * coalesce (`??`) are known as `ShortCircuitExpression`. + * But ESTree represents those by `LogicalExpression` node. + * + * This function finds only coalesce expressions of `LogicalExpression` node. + * @param {ASTNode} node The node to check. + * @returns {boolean} `true` if the node is `??`. + */ +function isCoalesceExpression(node) { + return node.type === "LogicalExpression" && node.operator === "??"; +} + +/** + * Check if given two nodes are the pair of a logical expression and a coalesce expression. + * @param {ASTNode} left A node to check. + * @param {ASTNode} right Another node to check. + * @returns {boolean} `true` if the two nodes are the pair of a logical expression and a coalesce expression. + */ +function isMixedLogicalAndCoalesceExpressions(left, right) { + return ( + (isLogicalExpression(left) && isCoalesceExpression(right)) || + (isCoalesceExpression(left) && isLogicalExpression(right)) + ); +} + //------------------------------------------------------------------------------ // Public Interface //------------------------------------------------------------------------------ @@ -779,6 +826,7 @@ module.exports = { case "LogicalExpression": switch (node.operator) { case "||": + case "??": return 4; case "&&": return 5; @@ -1415,7 +1463,7 @@ module.exports = { try { tokens = espree.tokenize(leftValue, espreeOptions); - } catch (e) { + } catch { return false; } @@ -1444,7 +1492,7 @@ module.exports = { try { tokens = espree.tokenize(rightValue, espreeOptions); - } catch (e) { + } catch { return false; } @@ -1538,5 +1586,9 @@ module.exports = { */ hasOctalEscapeSequence(rawString) { return OCTAL_ESCAPE_PATTERN.test(rawString); - } + }, + + isLogicalExpression, + isCoalesceExpression, + isMixedLogicalAndCoalesceExpressions }; diff --git a/eslint/package.json b/eslint/package.json index dddf620..f9e204c 100644 --- a/eslint/package.json +++ b/eslint/package.json @@ -1,6 +1,6 @@ { "name": "eslint", - "version": "7.1.0", + "version": "7.2.0", "author": "Nicholas C. Zakas ", "description": "An AST-based pattern checker for JavaScript.", "bin": { @@ -52,10 +52,10 @@ "cross-spawn": "^7.0.2", "debug": "^4.0.1", "doctrine": "^3.0.0", - "eslint-scope": "^5.0.0", + "eslint-scope": "^5.1.0", "eslint-utils": "^2.0.0", - "eslint-visitor-keys": "^1.1.0", - "espree": "^7.0.0", + "eslint-visitor-keys": "^1.2.0", + "espree": "^7.1.0", "esquery": "^1.2.0", "esutils": "^2.0.2", "file-entry-cache": "^5.0.1", @@ -86,7 +86,7 @@ "devDependencies": { "@babel/core": "^7.4.3", "@babel/preset-env": "^7.4.3", - "acorn": "^7.1.1", + "acorn": "^7.2.0", "babel-loader": "^8.0.5", "chai": "^4.0.1", "cheerio": "^0.22.0", diff --git a/eslint/tests/_utils/in-memory-fs.js b/eslint/tests/_utils/in-memory-fs.js index 5ef4f04..a458209 100644 --- a/eslint/tests/_utils/in-memory-fs.js +++ b/eslint/tests/_utils/in-memory-fs.js @@ -111,7 +111,7 @@ const context = vm.createContext(); function isExistingFile(fs, filePath) { try { return fs.statSync(filePath).isFile(); - } catch (error) { + } catch { return false; } } diff --git a/eslint/tests/fixtures/code-path-analysis/logical--do-while-qq-1.js b/eslint/tests/fixtures/code-path-analysis/logical--do-while-qq-1.js new file mode 100644 index 0000000..4b68567 --- /dev/null +++ b/eslint/tests/fixtures/code-path-analysis/logical--do-while-qq-1.js @@ -0,0 +1,23 @@ +/*expected +initial->s1_1->s1_2->s1_3->s1_2->s1_2; +s1_3->s1_4; +s1_2->s1_4->final; +*/ +do { + foo(); +} while (a ?? b); + +/*DOT +digraph { + node[shape=box,style="rounded,filled",fillcolor=white]; + initial[label="",shape=circle,style=filled,fillcolor=black,width=0.25,height=0.25]; + final[label="",shape=doublecircle,style=filled,fillcolor=black,width=0.25,height=0.25]; + s1_1[label="Program\nDoWhileStatement"]; + s1_2[label="BlockStatement\nExpressionStatement\nCallExpression\nIdentifier (foo)\nLogicalExpression\nIdentifier (a)\nIdentifier:exit (foo)\nCallExpression:exit\nExpressionStatement:exit\nBlockStatement:exit\nIdentifier:exit (a)"]; + s1_3[label="Identifier (b)\nIdentifier:exit (b)\nLogicalExpression:exit"]; + s1_4[label="DoWhileStatement:exit\nProgram:exit"]; + initial->s1_1->s1_2->s1_3->s1_2->s1_2; + s1_3->s1_4; + s1_2->s1_4->final; +} +*/ diff --git a/eslint/tests/fixtures/code-path-analysis/logical--do-while-qq-2.js b/eslint/tests/fixtures/code-path-analysis/logical--do-while-qq-2.js new file mode 100644 index 0000000..c033142 --- /dev/null +++ b/eslint/tests/fixtures/code-path-analysis/logical--do-while-qq-2.js @@ -0,0 +1,33 @@ +/*expected +initial->s1_1->s1_2->s1_3->s1_4->s1_5->s1_2->s1_2; +s1_3->s1_2; +s1_4->s1_2; +s1_5->s1_6; +s1_2->s1_6; +s1_3->s1_6; +s1_4->s1_6->final; +*/ +do { + foo(); +} while (a ?? b ?? c ?? d); + +/*DOT +digraph { + node[shape=box,style="rounded,filled",fillcolor=white]; + initial[label="",shape=circle,style=filled,fillcolor=black,width=0.25,height=0.25]; + final[label="",shape=doublecircle,style=filled,fillcolor=black,width=0.25,height=0.25]; + s1_1[label="Program\nDoWhileStatement"]; + s1_2[label="BlockStatement\nExpressionStatement\nCallExpression\nIdentifier (foo)\nLogicalExpression\nLogicalExpression\nLogicalExpression\nIdentifier (a)\nIdentifier:exit (foo)\nCallExpression:exit\nExpressionStatement:exit\nBlockStatement:exit\nIdentifier:exit (a)"]; + s1_3[label="Identifier (b)\nIdentifier:exit (b)\nLogicalExpression:exit"]; + s1_4[label="Identifier (c)\nIdentifier:exit (c)\nLogicalExpression:exit"]; + s1_5[label="Identifier (d)\nIdentifier:exit (d)\nLogicalExpression:exit"]; + s1_6[label="DoWhileStatement:exit\nProgram:exit"]; + initial->s1_1->s1_2->s1_3->s1_4->s1_5->s1_2->s1_2; + s1_3->s1_2; + s1_4->s1_2; + s1_5->s1_6; + s1_2->s1_6; + s1_3->s1_6; + s1_4->s1_6->final; +} +*/ diff --git a/eslint/tests/fixtures/code-path-analysis/logical--if-mix-and-qq-1.js b/eslint/tests/fixtures/code-path-analysis/logical--if-mix-and-qq-1.js new file mode 100644 index 0000000..4863ac8 --- /dev/null +++ b/eslint/tests/fixtures/code-path-analysis/logical--if-mix-and-qq-1.js @@ -0,0 +1,33 @@ +/*expected +initial->s1_1->s1_2->s1_3->s1_4->s1_6; +s1_1->s1_5->s1_6; +s1_2->s1_4; +s1_3->s1_5; +s1_2->s1_5; +s1_6->final; +*/ +if ((a && b) ?? c) { + foo(); +} else { + bar(); +} + +/*DOT +digraph { + node[shape=box,style="rounded,filled",fillcolor=white]; + initial[label="",shape=circle,style=filled,fillcolor=black,width=0.25,height=0.25]; + final[label="",shape=doublecircle,style=filled,fillcolor=black,width=0.25,height=0.25]; + s1_1[label="Program\nIfStatement\nLogicalExpression\nLogicalExpression\nIdentifier (a)\nIdentifier:exit (a)"]; + s1_2[label="Identifier (b)\nIdentifier:exit (b)\nLogicalExpression:exit"]; + s1_3[label="Identifier (c)\nIdentifier:exit (c)\nLogicalExpression:exit"]; + s1_4[label="BlockStatement\nExpressionStatement\nCallExpression\nIdentifier (foo)\nIdentifier:exit (foo)\nCallExpression:exit\nExpressionStatement:exit\nBlockStatement:exit"]; + s1_6[label="IfStatement:exit\nProgram:exit"]; + s1_5[label="BlockStatement\nExpressionStatement\nCallExpression\nIdentifier (bar)\nIdentifier:exit (bar)\nCallExpression:exit\nExpressionStatement:exit\nBlockStatement:exit"]; + initial->s1_1->s1_2->s1_3->s1_4->s1_6; + s1_1->s1_5->s1_6; + s1_2->s1_4; + s1_3->s1_5; + s1_2->s1_5; + s1_6->final; +} +*/ diff --git a/eslint/tests/fixtures/code-path-analysis/logical--if-mix-and-qq-2.js b/eslint/tests/fixtures/code-path-analysis/logical--if-mix-and-qq-2.js new file mode 100644 index 0000000..0dd1f2a --- /dev/null +++ b/eslint/tests/fixtures/code-path-analysis/logical--if-mix-and-qq-2.js @@ -0,0 +1,33 @@ +/*expected +initial->s1_1->s1_2->s1_3->s1_4->s1_6; +s1_1->s1_5->s1_6; +s1_2->s1_4; +s1_3->s1_5; +s1_2->s1_5; +s1_6->final; +*/ +if (a && (b ?? c)) { + foo(); +} else { + bar(); +} + +/*DOT +digraph { + node[shape=box,style="rounded,filled",fillcolor=white]; + initial[label="",shape=circle,style=filled,fillcolor=black,width=0.25,height=0.25]; + final[label="",shape=doublecircle,style=filled,fillcolor=black,width=0.25,height=0.25]; + s1_1[label="Program\nIfStatement\nLogicalExpression\nIdentifier (a)\nIdentifier:exit (a)"]; + s1_2[label="LogicalExpression\nIdentifier (b)\nIdentifier:exit (b)"]; + s1_3[label="Identifier (c)\nIdentifier:exit (c)\nLogicalExpression:exit\nLogicalExpression:exit"]; + s1_4[label="BlockStatement\nExpressionStatement\nCallExpression\nIdentifier (foo)\nIdentifier:exit (foo)\nCallExpression:exit\nExpressionStatement:exit\nBlockStatement:exit"]; + s1_6[label="IfStatement:exit\nProgram:exit"]; + s1_5[label="BlockStatement\nExpressionStatement\nCallExpression\nIdentifier (bar)\nIdentifier:exit (bar)\nCallExpression:exit\nExpressionStatement:exit\nBlockStatement:exit"]; + initial->s1_1->s1_2->s1_3->s1_4->s1_6; + s1_1->s1_5->s1_6; + s1_2->s1_4; + s1_3->s1_5; + s1_2->s1_5; + s1_6->final; +} +*/ diff --git a/eslint/tests/fixtures/code-path-analysis/logical--if-mix-or-qq-1.js b/eslint/tests/fixtures/code-path-analysis/logical--if-mix-or-qq-1.js new file mode 100644 index 0000000..e598999 --- /dev/null +++ b/eslint/tests/fixtures/code-path-analysis/logical--if-mix-or-qq-1.js @@ -0,0 +1,33 @@ +/*expected +initial->s1_1->s1_2->s1_3->s1_4->s1_6; +s1_1->s1_4; +s1_2->s1_4; +s1_3->s1_5->s1_6; +s1_2->s1_5; +s1_6->final; +*/ +if ((a || b) ?? c) { + foo(); +} else { + bar(); +} + +/*DOT +digraph { + node[shape=box,style="rounded,filled",fillcolor=white]; + initial[label="",shape=circle,style=filled,fillcolor=black,width=0.25,height=0.25]; + final[label="",shape=doublecircle,style=filled,fillcolor=black,width=0.25,height=0.25]; + s1_1[label="Program\nIfStatement\nLogicalExpression\nLogicalExpression\nIdentifier (a)\nIdentifier:exit (a)"]; + s1_2[label="Identifier (b)\nIdentifier:exit (b)\nLogicalExpression:exit"]; + s1_3[label="Identifier (c)\nIdentifier:exit (c)\nLogicalExpression:exit"]; + s1_4[label="BlockStatement\nExpressionStatement\nCallExpression\nIdentifier (foo)\nIdentifier:exit (foo)\nCallExpression:exit\nExpressionStatement:exit\nBlockStatement:exit"]; + s1_6[label="IfStatement:exit\nProgram:exit"]; + s1_5[label="BlockStatement\nExpressionStatement\nCallExpression\nIdentifier (bar)\nIdentifier:exit (bar)\nCallExpression:exit\nExpressionStatement:exit\nBlockStatement:exit"]; + initial->s1_1->s1_2->s1_3->s1_4->s1_6; + s1_1->s1_4; + s1_2->s1_4; + s1_3->s1_5->s1_6; + s1_2->s1_5; + s1_6->final; +} +*/ diff --git a/eslint/tests/fixtures/code-path-analysis/logical--if-mix-or-qq-2.js b/eslint/tests/fixtures/code-path-analysis/logical--if-mix-or-qq-2.js new file mode 100644 index 0000000..f98962d --- /dev/null +++ b/eslint/tests/fixtures/code-path-analysis/logical--if-mix-or-qq-2.js @@ -0,0 +1,33 @@ +/*expected +initial->s1_1->s1_2->s1_3->s1_4->s1_6; +s1_1->s1_4; +s1_2->s1_4; +s1_3->s1_5->s1_6; +s1_2->s1_5; +s1_6->final; +*/ +if (a || (b ?? c)) { + foo(); +} else { + bar(); +} + +/*DOT +digraph { + node[shape=box,style="rounded,filled",fillcolor=white]; + initial[label="",shape=circle,style=filled,fillcolor=black,width=0.25,height=0.25]; + final[label="",shape=doublecircle,style=filled,fillcolor=black,width=0.25,height=0.25]; + s1_1[label="Program\nIfStatement\nLogicalExpression\nLogicalExpression\nIdentifier (a)\nIdentifier:exit (a)"]; + s1_2[label="Identifier (b)\nIdentifier:exit (b)\nLogicalExpression:exit"]; + s1_3[label="Identifier (c)\nIdentifier:exit (c)\nLogicalExpression:exit"]; + s1_4[label="BlockStatement\nExpressionStatement\nCallExpression\nIdentifier (foo)\nIdentifier:exit (foo)\nCallExpression:exit\nExpressionStatement:exit\nBlockStatement:exit"]; + s1_6[label="IfStatement:exit\nProgram:exit"]; + s1_5[label="BlockStatement\nExpressionStatement\nCallExpression\nIdentifier (bar)\nIdentifier:exit (bar)\nCallExpression:exit\nExpressionStatement:exit\nBlockStatement:exit"]; + initial->s1_1->s1_2->s1_3->s1_4->s1_6; + s1_1->s1_4; + s1_2->s1_4; + s1_3->s1_5->s1_6; + s1_2->s1_5; + s1_6->final; +} +*/ diff --git a/eslint/tests/fixtures/code-path-analysis/logical--if-qq-1.js b/eslint/tests/fixtures/code-path-analysis/logical--if-qq-1.js new file mode 100644 index 0000000..80a7728 --- /dev/null +++ b/eslint/tests/fixtures/code-path-analysis/logical--if-qq-1.js @@ -0,0 +1,25 @@ +/*expected +initial->s1_1->s1_2->s1_3->s1_4; +s1_1->s1_3; +s1_2->s1_4; +s1_1->s1_4->final; +*/ +if (a ?? b) { + foo(); +} + +/*DOT +digraph { + node[shape=box,style="rounded,filled",fillcolor=white]; + initial[label="",shape=circle,style=filled,fillcolor=black,width=0.25,height=0.25]; + final[label="",shape=doublecircle,style=filled,fillcolor=black,width=0.25,height=0.25]; + s1_1[label="Program\nIfStatement\nLogicalExpression\nIdentifier (a)\nIdentifier:exit (a)"]; + s1_2[label="Identifier (b)\nIdentifier:exit (b)\nLogicalExpression:exit"]; + s1_3[label="BlockStatement\nExpressionStatement\nCallExpression\nIdentifier (foo)\nIdentifier:exit (foo)\nCallExpression:exit\nExpressionStatement:exit\nBlockStatement:exit"]; + s1_4[label="IfStatement:exit\nProgram:exit"]; + initial->s1_1->s1_2->s1_3->s1_4; + s1_1->s1_3; + s1_2->s1_4; + s1_1->s1_4->final; +} +*/ diff --git a/eslint/tests/fixtures/code-path-analysis/logical--if-qq-2.js b/eslint/tests/fixtures/code-path-analysis/logical--if-qq-2.js new file mode 100644 index 0000000..e9604bf --- /dev/null +++ b/eslint/tests/fixtures/code-path-analysis/logical--if-qq-2.js @@ -0,0 +1,30 @@ +/*expected +initial->s1_1->s1_2->s1_3->s1_5; +s1_1->s1_3; +s1_2->s1_4->s1_5; +s1_1->s1_4; +s1_5->final; +*/ +if (a ?? b) { + foo(); +} else { + bar(); +} + +/*DOT +digraph { + node[shape=box,style="rounded,filled",fillcolor=white]; + initial[label="",shape=circle,style=filled,fillcolor=black,width=0.25,height=0.25]; + final[label="",shape=doublecircle,style=filled,fillcolor=black,width=0.25,height=0.25]; + s1_1[label="Program\nIfStatement\nLogicalExpression\nIdentifier (a)\nIdentifier:exit (a)"]; + s1_2[label="Identifier (b)\nIdentifier:exit (b)\nLogicalExpression:exit"]; + s1_3[label="BlockStatement\nExpressionStatement\nCallExpression\nIdentifier (foo)\nIdentifier:exit (foo)\nCallExpression:exit\nExpressionStatement:exit\nBlockStatement:exit"]; + s1_5[label="IfStatement:exit\nProgram:exit"]; + s1_4[label="BlockStatement\nExpressionStatement\nCallExpression\nIdentifier (bar)\nIdentifier:exit (bar)\nCallExpression:exit\nExpressionStatement:exit\nBlockStatement:exit"]; + initial->s1_1->s1_2->s1_3->s1_5; + s1_1->s1_3; + s1_2->s1_4->s1_5; + s1_1->s1_4; + s1_5->final; +} +*/ diff --git a/eslint/tests/fixtures/code-path-analysis/logical--if-qq-3.js b/eslint/tests/fixtures/code-path-analysis/logical--if-qq-3.js new file mode 100644 index 0000000..3586ce3 --- /dev/null +++ b/eslint/tests/fixtures/code-path-analysis/logical--if-qq-3.js @@ -0,0 +1,40 @@ +/*expected +initial->s1_1->s1_2->s1_3->s1_9; +s1_1->s1_3; +s1_2->s1_4->s1_5->s1_6->s1_8->s1_9; +s1_1->s1_4->s1_6; +s1_5->s1_7->s1_8; +s1_4->s1_7; +s1_9->final; +*/ +if (a ?? b) { + foo(); +} else if (c ?? d) { + bar(); +} else { + qiz(); +} + +/*DOT +digraph { + node[shape=box,style="rounded,filled",fillcolor=white]; + initial[label="",shape=circle,style=filled,fillcolor=black,width=0.25,height=0.25]; + final[label="",shape=doublecircle,style=filled,fillcolor=black,width=0.25,height=0.25]; + s1_1[label="Program\nIfStatement\nLogicalExpression\nIdentifier (a)\nIdentifier:exit (a)"]; + s1_2[label="Identifier (b)\nIdentifier:exit (b)\nLogicalExpression:exit"]; + s1_3[label="BlockStatement\nExpressionStatement\nCallExpression\nIdentifier (foo)\nIdentifier:exit (foo)\nCallExpression:exit\nExpressionStatement:exit\nBlockStatement:exit"]; + s1_9[label="IfStatement:exit\nProgram:exit"]; + s1_4[label="IfStatement\nLogicalExpression\nIdentifier (c)\nIdentifier:exit (c)"]; + s1_5[label="Identifier (d)\nIdentifier:exit (d)\nLogicalExpression:exit"]; + s1_6[label="BlockStatement\nExpressionStatement\nCallExpression\nIdentifier (bar)\nIdentifier:exit (bar)\nCallExpression:exit\nExpressionStatement:exit\nBlockStatement:exit"]; + s1_8[label="IfStatement:exit"]; + s1_7[label="BlockStatement\nExpressionStatement\nCallExpression\nIdentifier (qiz)\nIdentifier:exit (qiz)\nCallExpression:exit\nExpressionStatement:exit\nBlockStatement:exit"]; + initial->s1_1->s1_2->s1_3->s1_9; + s1_1->s1_3; + s1_2->s1_4->s1_5->s1_6->s1_8->s1_9; + s1_1->s1_4->s1_6; + s1_5->s1_7->s1_8; + s1_4->s1_7; + s1_9->final; +} +*/ diff --git a/eslint/tests/fixtures/code-path-analysis/logical--if-qq-4.js b/eslint/tests/fixtures/code-path-analysis/logical--if-qq-4.js new file mode 100644 index 0000000..ba81360 --- /dev/null +++ b/eslint/tests/fixtures/code-path-analysis/logical--if-qq-4.js @@ -0,0 +1,40 @@ +/*expected +initial->s1_1->s1_2->s1_3->s1_4->s1_5->s1_7; +s1_1->s1_5; +s1_2->s1_5; +s1_3->s1_5; +s1_4->s1_6->s1_7; +s1_1->s1_6; +s1_2->s1_6; +s1_3->s1_6; +s1_7->final; +*/ +if (a ?? b ?? c ?? d) { + foo(); +} else { + bar(); +} + +/*DOT +digraph { + node[shape=box,style="rounded,filled",fillcolor=white]; + initial[label="",shape=circle,style=filled,fillcolor=black,width=0.25,height=0.25]; + final[label="",shape=doublecircle,style=filled,fillcolor=black,width=0.25,height=0.25]; + s1_1[label="Program\nIfStatement\nLogicalExpression\nLogicalExpression\nLogicalExpression\nIdentifier (a)\nIdentifier:exit (a)"]; + s1_2[label="Identifier (b)\nIdentifier:exit (b)\nLogicalExpression:exit"]; + s1_3[label="Identifier (c)\nIdentifier:exit (c)\nLogicalExpression:exit"]; + s1_4[label="Identifier (d)\nIdentifier:exit (d)\nLogicalExpression:exit"]; + s1_5[label="BlockStatement\nExpressionStatement\nCallExpression\nIdentifier (foo)\nIdentifier:exit (foo)\nCallExpression:exit\nExpressionStatement:exit\nBlockStatement:exit"]; + s1_7[label="IfStatement:exit\nProgram:exit"]; + s1_6[label="BlockStatement\nExpressionStatement\nCallExpression\nIdentifier (bar)\nIdentifier:exit (bar)\nCallExpression:exit\nExpressionStatement:exit\nBlockStatement:exit"]; + initial->s1_1->s1_2->s1_3->s1_4->s1_5->s1_7; + s1_1->s1_5; + s1_2->s1_5; + s1_3->s1_5; + s1_4->s1_6->s1_7; + s1_1->s1_6; + s1_2->s1_6; + s1_3->s1_6; + s1_7->final; +} +*/ diff --git a/eslint/tests/fixtures/code-path-analysis/logical--if-qq-5.js b/eslint/tests/fixtures/code-path-analysis/logical--if-qq-5.js new file mode 100644 index 0000000..ba2d222 --- /dev/null +++ b/eslint/tests/fixtures/code-path-analysis/logical--if-qq-5.js @@ -0,0 +1,44 @@ +/*expected +initial->s1_1->s1_2->s1_3->s1_4->s1_5->s1_7->s1_9; +s1_1->s1_3; +s1_2->s1_8->s1_9; +s1_3->s1_5; +s1_4->s1_6->s1_7; +s1_1->s1_8; +s1_3->s1_6; +s1_9->final; +*/ +if (a ?? b) { + if (c ?? d) { + foo(); + } else { + bar(); + } +} else { + qiz(); +} + +/*DOT +digraph { + node[shape=box,style="rounded,filled",fillcolor=white]; + initial[label="",shape=circle,style=filled,fillcolor=black,width=0.25,height=0.25]; + final[label="",shape=doublecircle,style=filled,fillcolor=black,width=0.25,height=0.25]; + s1_1[label="Program\nIfStatement\nLogicalExpression\nIdentifier (a)\nIdentifier:exit (a)"]; + s1_2[label="Identifier (b)\nIdentifier:exit (b)\nLogicalExpression:exit"]; + s1_3[label="BlockStatement\nIfStatement\nLogicalExpression\nIdentifier (c)\nIdentifier:exit (c)"]; + s1_4[label="Identifier (d)\nIdentifier:exit (d)\nLogicalExpression:exit"]; + s1_5[label="BlockStatement\nExpressionStatement\nCallExpression\nIdentifier (foo)\nIdentifier:exit (foo)\nCallExpression:exit\nExpressionStatement:exit\nBlockStatement:exit"]; + s1_7[label="IfStatement:exit\nBlockStatement:exit"]; + s1_9[label="IfStatement:exit\nProgram:exit"]; + s1_8[label="BlockStatement\nExpressionStatement\nCallExpression\nIdentifier (qiz)\nIdentifier:exit (qiz)\nCallExpression:exit\nExpressionStatement:exit\nBlockStatement:exit"]; + s1_6[label="BlockStatement\nExpressionStatement\nCallExpression\nIdentifier (bar)\nIdentifier:exit (bar)\nCallExpression:exit\nExpressionStatement:exit\nBlockStatement:exit"]; + initial->s1_1->s1_2->s1_3->s1_4->s1_5->s1_7->s1_9; + s1_1->s1_3; + s1_2->s1_8->s1_9; + s1_3->s1_5; + s1_4->s1_6->s1_7; + s1_1->s1_8; + s1_3->s1_6; + s1_9->final; +} +*/ diff --git a/eslint/tests/fixtures/code-path-analysis/logical--simple-3.js b/eslint/tests/fixtures/code-path-analysis/logical--simple-3.js new file mode 100644 index 0000000..0ae12a3 --- /dev/null +++ b/eslint/tests/fixtures/code-path-analysis/logical--simple-3.js @@ -0,0 +1,24 @@ +/*expected +initial->s1_1->s1_2->s1_3->s1_4->s1_5; +s1_1->s1_5; +s1_2->s1_5; +s1_3->s1_5->final; +*/ +a ?? b ?? c ?? d; + +/*DOT +digraph { + node[shape=box,style="rounded,filled",fillcolor=white]; + initial[label="",shape=circle,style=filled,fillcolor=black,width=0.25,height=0.25]; + final[label="",shape=doublecircle,style=filled,fillcolor=black,width=0.25,height=0.25]; + s1_1[label="Program\nExpressionStatement\nLogicalExpression\nLogicalExpression\nLogicalExpression\nIdentifier (a)"]; + s1_2[label="Identifier (b)"]; + s1_3[label="Identifier (c)"]; + s1_4[label="Identifier (d)"]; + s1_5[label="LogicalExpression:exit\nExpressionStatement:exit\nProgram:exit"]; + initial->s1_1->s1_2->s1_3->s1_4->s1_5; + s1_1->s1_5; + s1_2->s1_5; + s1_3->s1_5->final; +} +*/ diff --git a/eslint/tests/fixtures/code-path-analysis/logical--while-qq-1.js b/eslint/tests/fixtures/code-path-analysis/logical--while-qq-1.js new file mode 100644 index 0000000..de729d7 --- /dev/null +++ b/eslint/tests/fixtures/code-path-analysis/logical--while-qq-1.js @@ -0,0 +1,24 @@ +/*expected +initial->s1_1->s1_2->s1_3->s1_4->s1_2->s1_4; +s1_3->s1_5; +s1_2->s1_5->final; +*/ +while (a ?? b) { + foo(); +} + +/*DOT +digraph { + node[shape=box,style="rounded,filled",fillcolor=white]; + initial[label="",shape=circle,style=filled,fillcolor=black,width=0.25,height=0.25]; + final[label="",shape=doublecircle,style=filled,fillcolor=black,width=0.25,height=0.25]; + s1_1[label="Program\nWhileStatement"]; + s1_2[label="LogicalExpression\nIdentifier (a)\nIdentifier:exit (a)"]; + s1_3[label="Identifier (b)\nIdentifier:exit (b)\nLogicalExpression:exit"]; + s1_4[label="BlockStatement\nExpressionStatement\nCallExpression\nIdentifier (foo)\nIdentifier:exit (foo)\nCallExpression:exit\nExpressionStatement:exit\nBlockStatement:exit"]; + s1_5[label="WhileStatement:exit\nProgram:exit"]; + initial->s1_1->s1_2->s1_3->s1_4->s1_2->s1_4; + s1_3->s1_5; + s1_2->s1_5->final; +} +*/ diff --git a/eslint/tests/fixtures/code-path-analysis/logical--while-qq-2.js b/eslint/tests/fixtures/code-path-analysis/logical--while-qq-2.js new file mode 100644 index 0000000..fac385d --- /dev/null +++ b/eslint/tests/fixtures/code-path-analysis/logical--while-qq-2.js @@ -0,0 +1,34 @@ +/*expected +initial->s1_1->s1_2->s1_3->s1_4->s1_5->s1_6->s1_2->s1_6; +s1_3->s1_6; +s1_4->s1_6; +s1_5->s1_7; +s1_2->s1_7; +s1_3->s1_7; +s1_4->s1_7->final; +*/ +while (a ?? b ?? c ?? d) { + foo(); +} + +/*DOT +digraph { + node[shape=box,style="rounded,filled",fillcolor=white]; + initial[label="",shape=circle,style=filled,fillcolor=black,width=0.25,height=0.25]; + final[label="",shape=doublecircle,style=filled,fillcolor=black,width=0.25,height=0.25]; + s1_1[label="Program\nWhileStatement"]; + s1_2[label="LogicalExpression\nLogicalExpression\nLogicalExpression\nIdentifier (a)\nIdentifier:exit (a)"]; + s1_3[label="Identifier (b)\nIdentifier:exit (b)\nLogicalExpression:exit"]; + s1_4[label="Identifier (c)\nIdentifier:exit (c)\nLogicalExpression:exit"]; + s1_5[label="Identifier (d)\nIdentifier:exit (d)\nLogicalExpression:exit"]; + s1_6[label="BlockStatement\nExpressionStatement\nCallExpression\nIdentifier (foo)\nIdentifier:exit (foo)\nCallExpression:exit\nExpressionStatement:exit\nBlockStatement:exit"]; + s1_7[label="WhileStatement:exit\nProgram:exit"]; + initial->s1_1->s1_2->s1_3->s1_4->s1_5->s1_6->s1_2->s1_6; + s1_3->s1_6; + s1_4->s1_6; + s1_5->s1_7; + s1_2->s1_7; + s1_3->s1_7; + s1_4->s1_7->final; +} +*/ diff --git a/eslint/tests/lib/cli-engine/cli-engine.js b/eslint/tests/lib/cli-engine/cli-engine.js index a8394b6..fb3c365 100644 --- a/eslint/tests/lib/cli-engine/cli-engine.js +++ b/eslint/tests/lib/cli-engine/cli-engine.js @@ -58,7 +58,7 @@ describe("CLIEngine", () => { try { return fs.realpathSync(filepath); - } catch (e) { + } catch { return filepath; } } @@ -2161,7 +2161,7 @@ describe("CLIEngine", () => { function doDelete(filePath) { try { fs.unlinkSync(filePath); - } catch (ex) { + } catch { /* * we don't care if the file didn't exist, since our @@ -2197,7 +2197,7 @@ describe("CLIEngine", () => { function deleteCacheDir() { try { fs.unlinkSync("./tmp/.cacheFileDir/.cache_hashOfCurrentWorkingDirectory"); - } catch (ex) { + } catch { /* * we don't care if the file didn't exist, since our diff --git a/eslint/tests/lib/eslint/eslint.js b/eslint/tests/lib/eslint/eslint.js index fc86a78..6807a57 100644 --- a/eslint/tests/lib/eslint/eslint.js +++ b/eslint/tests/lib/eslint/eslint.js @@ -55,7 +55,7 @@ describe("ESLint", () => { try { return fs.realpathSync(filepath); - } catch (e) { + } catch { return filepath; } } @@ -2102,7 +2102,7 @@ describe("ESLint", () => { function doDelete(filePath) { try { fs.unlinkSync(filePath); - } catch (ex) { + } catch { /* * we don't care if the file didn't exist, since our @@ -2138,7 +2138,7 @@ describe("ESLint", () => { function deleteCacheDir() { try { fs.unlinkSync("./tmp/.cacheFileDir/.cache_hashOfCurrentWorkingDirectory"); - } catch (ex) { + } catch { /* * we don't care if the file didn't exist, since our diff --git a/eslint/tests/lib/init/config-initializer.js b/eslint/tests/lib/init/config-initializer.js index fe9120f..945e185 100644 --- a/eslint/tests/lib/init/config-initializer.js +++ b/eslint/tests/lib/init/config-initializer.js @@ -67,7 +67,7 @@ describe("configInitializer", () => { try { return fs.realpathSync(filepath); - } catch (e) { + } catch { return filepath; } } @@ -136,9 +136,7 @@ describe("configInitializer", () => { assert.deepStrictEqual(config.rules.quotes, ["error", "single"]); assert.deepStrictEqual(config.rules["linebreak-style"], ["error", "unix"]); assert.deepStrictEqual(config.rules.semi, ["error", "always"]); - assert.strictEqual(config.env.es6, true); - assert.strictEqual(config.globals.Atomics, "readonly"); - assert.strictEqual(config.globals.SharedArrayBuffer, "readonly"); + assert.strictEqual(config.env.es2020, true); assert.strictEqual(config.parserOptions.ecmaVersion, espree.latestEcmaVersion); assert.strictEqual(config.parserOptions.sourceType, "module"); assert.strictEqual(config.env.browser, true); diff --git a/eslint/tests/lib/init/source-code-utils.js b/eslint/tests/lib/init/source-code-utils.js index 8c821de..994d23d 100644 --- a/eslint/tests/lib/init/source-code-utils.js +++ b/eslint/tests/lib/init/source-code-utils.js @@ -41,7 +41,7 @@ describe("SourceCodeUtil", () => { try { filepath = fs.realpathSync(filepath); return filepath; - } catch (e) { + } catch { return filepath; } } diff --git a/eslint/tests/lib/linter/code-path-analysis/code-path-analyzer.js b/eslint/tests/lib/linter/code-path-analysis/code-path-analyzer.js index 6460ba1..ec516c5 100644 --- a/eslint/tests/lib/linter/code-path-analysis/code-path-analyzer.js +++ b/eslint/tests/lib/linter/code-path-analysis/code-path-analyzer.js @@ -556,7 +556,10 @@ describe("CodePathAnalyzer", () => { actual.push(debug.makeDotArrows(codePath)); } })); - const messages = linter.verify(source, { rules: { test: 2 }, env: { es6: true } }); + const messages = linter.verify(source, { + parserOptions: { ecmaVersion: 2020 }, + rules: { test: 2 } + }); assert.strictEqual(messages.length, 0); assert.strictEqual(actual.length, expected.length, "a count of code paths is wrong."); diff --git a/eslint/tests/lib/linter/linter.js b/eslint/tests/lib/linter/linter.js index f2efc00..093ebcf 100644 --- a/eslint/tests/lib/linter/linter.js +++ b/eslint/tests/lib/linter/linter.js @@ -3918,9 +3918,9 @@ var a = "test2"; messages, [{ column: 25, - endLine: 3, + endLine: 4, endColumn: 28, - line: 3, + line: 4, message: "'aaa' is assigned a value but never used.", messageId: "unusedVar", nodeType: "Identifier", @@ -3966,9 +3966,9 @@ var a = "test2"; messages, [{ column: 25, - endLine: 2, + endLine: 3, endColumn: 28, - line: 2, + line: 3, message: "'aaa' is assigned a value but never used.", messageId: "unusedVar", nodeType: "Identifier", @@ -3989,9 +3989,9 @@ var a = "test2"; messages, [{ column: 25, - endLine: 2, + endLine: 3, endColumn: 28, - line: 2, + line: 3, message: "'aaa' is assigned a value but never used.", messageId: "unusedVar", nodeType: "Identifier", @@ -4014,9 +4014,9 @@ var a = "test2"; messages, [{ column: 25, - endLine: 3, + endLine: 5, endColumn: 28, - line: 3, + line: 5, message: "'aaa' is assigned a value but never used.", messageId: "unusedVar", nodeType: "Identifier", @@ -4039,9 +4039,9 @@ var a = "test2"; messages, [{ column: 25, - endLine: 3, + endLine: 5, endColumn: 28, - line: 3, + line: 5, message: "'aaa' is assigned a value but never used.", messageId: "unusedVar", nodeType: "Identifier", diff --git a/eslint/tests/lib/rules/camelcase.js b/eslint/tests/lib/rules/camelcase.js index 1e3eecc..7c7a457 100644 --- a/eslint/tests/lib/rules/camelcase.js +++ b/eslint/tests/lib/rules/camelcase.js @@ -652,6 +652,17 @@ ruleTester.run("camelcase", rule, { } ] }, + { + code: "export * as snake_cased from 'mod'", + parserOptions: { ecmaVersion: 2020, sourceType: "module" }, + errors: [ + { + messageId: "notCamelCase", + data: { name: "snake_cased" }, + type: "Identifier" + } + ] + }, { code: "function foo({ no_camelcased }) {};", parserOptions: { ecmaVersion: 6 }, diff --git a/eslint/tests/lib/rules/func-call-spacing.js b/eslint/tests/lib/rules/func-call-spacing.js index 0774ec4..f0199fd 100644 --- a/eslint/tests/lib/rules/func-call-spacing.js +++ b/eslint/tests/lib/rules/func-call-spacing.js @@ -236,12 +236,30 @@ ruleTester.run("func-call-spacing", rule, { { code: "f.b ();", output: "f.b();", - errors: [{ messageId: "unexpectedWhitespace", type: "CallExpression", column: 3 }] + errors: [ + { + messageId: "unexpectedWhitespace", + type: "CallExpression", + column: 4, + line: 1, + endColumn: 4, + endLine: 1 + } + ] }, { code: "f.b().c ();", output: "f.b().c();", - errors: [{ messageId: "unexpectedWhitespace", type: "CallExpression", column: 7 }] + errors: [ + { + messageId: "unexpectedWhitespace", + type: "CallExpression", + column: 8, + line: 1, + endColumn: 8, + endLine: 1 + } + ] }, { code: "f() ()", @@ -335,16 +353,34 @@ ruleTester.run("func-call-spacing", rule, { errors: [{ messageId: "unexpectedWhitespace", type: "CallExpression" }] }, { - code: "f.b ();", + code: "f.b ();", output: "f.b();", options: ["never"], - errors: [{ messageId: "unexpectedWhitespace", type: "CallExpression", column: 3 }] + errors: [ + { + messageId: "unexpectedWhitespace", + type: "CallExpression", + column: 4, + line: 1, + endColumn: 5, + endLine: 1 + } + ] }, { code: "f.b().c ();", output: "f.b().c();", options: ["never"], - errors: [{ messageId: "unexpectedWhitespace", type: "CallExpression", column: 7 }] + errors: [ + { + messageId: "unexpectedWhitespace", + type: "CallExpression", + column: 8, + line: 1, + endColumn: 8, + endLine: 1 + } + ] }, { code: "f() ()", @@ -407,7 +443,11 @@ ruleTester.run("func-call-spacing", rule, { errors: [ { messageId: "unexpectedWhitespace", - type: "CallExpression" + type: "CallExpression", + line: 1, + column: 2, + endLine: 2, + endColumn: 0 } ] }, @@ -424,7 +464,9 @@ ruleTester.run("func-call-spacing", rule, { messageId: "unexpectedWhitespace", type: "CallExpression", line: 2, - column: 23 + column: 24, + endLine: 3, + endColumn: 0 } ] }, @@ -440,7 +482,9 @@ ruleTester.run("func-call-spacing", rule, { messageId: "unexpectedWhitespace", type: "CallExpression", line: 1, - column: 9 + column: 12, + endLine: 2, + endColumn: 0 } ] }, @@ -456,7 +500,9 @@ ruleTester.run("func-call-spacing", rule, { messageId: "unexpectedWhitespace", type: "CallExpression", line: 1, - column: 9 + column: 12, + endColumn: 0, + endLine: 2 } ] }, @@ -534,13 +580,31 @@ ruleTester.run("func-call-spacing", rule, { code: "f.b();", output: "f.b ();", options: ["always"], - errors: [{ messageId: "missing", type: "CallExpression", column: 3 }] + errors: [ + { + messageId: "missing", + type: "CallExpression", + column: 3, + line: 1, + endLine: 1, + endColumn: 4 + } + ] }, { code: "f.b\n();", output: "f.b ();", options: ["always"], - errors: [{ messageId: "unexpectedNewline", type: "CallExpression", column: 3 }] + errors: [ + { + messageId: "unexpectedNewline", + type: "CallExpression", + column: 4, + line: 1, + endColumn: 1, + endLine: 2 + } + ] }, { code: "f.b().c ();", @@ -552,7 +616,16 @@ ruleTester.run("func-call-spacing", rule, { code: "f.b\n().c ();", output: "f.b ().c ();", options: ["always"], - errors: [{ messageId: "unexpectedNewline", type: "CallExpression", column: 3 }] + errors: [ + { + messageId: "unexpectedNewline", + type: "CallExpression", + column: 4, + line: 1, + endColumn: 1, + endLine: 2 + } + ] }, { code: "f() ()", @@ -664,7 +737,13 @@ ruleTester.run("func-call-spacing", rule, { code: "f.b();", output: "f.b ();", options: ["always", { allowNewlines: true }], - errors: [{ messageId: "missing", type: "CallExpression", column: 3 }] + errors: [ + { + messageId: "missing", + type: "CallExpression", + column: 3 + } + ] }, { code: "f.b().c ();", @@ -716,6 +795,64 @@ ruleTester.run("func-call-spacing", rule, { { messageId: "missing", type: "CallExpression" }, { messageId: "missing", type: "CallExpression" } ] + }, + { + code: "f ();", + output: "f();", + errors: [ + { + messageId: "unexpectedWhitespace", + type: "CallExpression", + line: 1, + column: 2, + endLine: 1, + endColumn: 5 + } + ] + }, + { + code: "f\n ();", + output: null, + errors: [ + { + messageId: "unexpectedWhitespace", + type: "CallExpression", + line: 1, + column: 2, + endLine: 2, + endColumn: 1 + } + ] + }, + { + code: "fn();", + output: "fn ();", + options: ["always"], + errors: [ + { + messageId: "missing", + type: "CallExpression", + line: 1, + column: 2, + endLine: 1, + endColumn: 3 + } + ] + }, + { + code: "fnn\n (a, b);", + output: "fnn (a, b);", + options: ["always"], + errors: [ + { + messageId: "unexpectedNewline", + type: "CallExpression", + line: 1, + column: 4, + endLine: 2, + endColumn: 2 + } + ] } ] }); diff --git a/eslint/tests/lib/rules/id-blacklist.js b/eslint/tests/lib/rules/id-blacklist.js index a900924..6c3f729 100644 --- a/eslint/tests/lib/rules/id-blacklist.js +++ b/eslint/tests/lib/rules/id-blacklist.js @@ -251,6 +251,14 @@ ruleTester.run("id-blacklist", rule, { error ] }, + { + code: "export * as foo from 'mod'", + options: ["foo"], + parserOptions: { ecmaVersion: 2020, sourceType: "module" }, + errors: [ + error + ] + }, { code: "import { foo } from 'mod'", options: ["foo"], diff --git a/eslint/tests/lib/rules/id-match.js b/eslint/tests/lib/rules/id-match.js index 77aee18..f733dcc 100644 --- a/eslint/tests/lib/rules/id-match.js +++ b/eslint/tests/lib/rules/id-match.js @@ -401,6 +401,17 @@ ruleTester.run("id-match", rule, { } ] }, + { + code: "export * as no_camelcased from \"external-module\";", + options: ["^[^_]+$"], + parserOptions: { ecmaVersion: 2020, sourceType: "module" }, + errors: [ + { + message: "Identifier 'no_camelcased' does not match the pattern '^[^_]+$'.", + type: "Identifier" + } + ] + }, { code: "import { no_camelcased } from \"external-module\";", options: ["^[^_]+$", { diff --git a/eslint/tests/lib/rules/keyword-spacing.js b/eslint/tests/lib/rules/keyword-spacing.js index f7f5cca..b67ee52 100644 --- a/eslint/tests/lib/rules/keyword-spacing.js +++ b/eslint/tests/lib/rules/keyword-spacing.js @@ -129,6 +129,10 @@ ruleTester.run("keyword-spacing", rule, { { code: "import*as a from\"foo\"", options: [NEITHER], parserOptions: { ecmaVersion: 6, sourceType: "module" } }, { code: "import* as a from\"foo\"", options: [override("as", BOTH)], parserOptions: { ecmaVersion: 6, sourceType: "module" } }, { code: "import *as a from \"foo\"", options: [override("as", NEITHER)], parserOptions: { ecmaVersion: 6, sourceType: "module" } }, + { code: "export * as a from \"foo\"", parserOptions: { ecmaVersion: 2020, sourceType: "module" } }, + { code: "export*as a from\"foo\"", options: [NEITHER], parserOptions: { ecmaVersion: 2020, sourceType: "module" } }, + { code: "export* as a from\"foo\"", options: [override("as", BOTH)], parserOptions: { ecmaVersion: 2020, sourceType: "module" } }, + { code: "export *as a from \"foo\"", options: [override("as", NEITHER)], parserOptions: { ecmaVersion: 2020, sourceType: "module" } }, //---------------------------------------------------------------------- // async @@ -1369,6 +1373,35 @@ ruleTester.run("keyword-spacing", rule, { parserOptions: { ecmaVersion: 6, sourceType: "module" }, errors: unexpectedBefore("as") }, + { + code: "import* as a from\"foo\"", + output: "import*as a from\"foo\"", + options: [NEITHER], + parserOptions: { ecmaVersion: 6, sourceType: "module" }, + errors: [{ + messageId: "unexpectedBefore", + line: 1, + column: 8, + endLine: 1, + endColumn: 9 + } + ] + }, + { + code: "import *as a from\"foo\"", + output: "import*as a from\"foo\"", + options: [NEITHER], + parserOptions: { ecmaVersion: 6, sourceType: "module" }, + errors: [ + { + messageId: "unexpectedAfter", + line: 1, + column: 7, + endLine: 1, + endColumn: 8 + } + ] + }, { code: "import*as a from\"foo\"", output: "import* as a from\"foo\"", @@ -1383,6 +1416,33 @@ ruleTester.run("keyword-spacing", rule, { parserOptions: { ecmaVersion: 6, sourceType: "module" }, errors: unexpectedBefore("as") }, + { + code: "export *as a from \"foo\"", + output: "export * as a from \"foo\"", + parserOptions: { ecmaVersion: 2020, sourceType: "module" }, + errors: expectedBefore("as") + }, + { + code: "export* as a from\"foo\"", + output: "export*as a from\"foo\"", + options: [NEITHER], + parserOptions: { ecmaVersion: 2020, sourceType: "module" }, + errors: unexpectedBefore("as") + }, + { + code: "export*as a from\"foo\"", + output: "export* as a from\"foo\"", + options: [override("as", BOTH)], + parserOptions: { ecmaVersion: 2020, sourceType: "module" }, + errors: expectedBefore("as") + }, + { + code: "export * as a from \"foo\"", + output: "export *as a from \"foo\"", + options: [override("as", NEITHER)], + parserOptions: { ecmaVersion: 2020, sourceType: "module" }, + errors: unexpectedBefore("as") + }, //---------------------------------------------------------------------- // async @@ -3134,4 +3194,5 @@ ruleTester.run("keyword-spacing", rule, { errors: expectedAfter("async") } ] + }); diff --git a/eslint/tests/lib/rules/multiline-ternary.js b/eslint/tests/lib/rules/multiline-ternary.js index a8d2ef6..ff0f9d1 100644 --- a/eslint/tests/lib/rules/multiline-ternary.js +++ b/eslint/tests/lib/rules/multiline-ternary.js @@ -32,6 +32,22 @@ ruleTester.run("multiline-ternary", rule, { { code: "a ?\nb :\nc", options: ["always"] }, { code: "a\n? b\n? c\n: d\n: e", options: ["always"] }, { code: "a\n? (b\n? c\n: d)\n: e", options: ["always"] }, + { code: "(a\n ? b\n : c)", options: ["always"] }, + { code: "(a)\n? b\n: c", options: ["always"] }, + { code: "((a))\n? b\n: c", options: ["always"] }, + { code: "(a)?\n b\n: c", options: ["always"] }, + { code: "((a))?\n b\n: c", options: ["always"] }, + { code: "a\n? (b)\n: c", options: ["always"] }, + { code: "a\n? ((b))\n: c", options: ["always"] }, + { code: "a ?\n (b)\n: c", options: ["always"] }, + { code: "a ?\n ((b))\n: c", options: ["always"] }, + { code: "a \n? b\n: (c)", options: ["always"] }, + { code: "a \n? b\n: ((c))", options: ["always"] }, + { code: "a \n? b:\n (c)", options: ["always"] }, + { code: "a \n? b:\n ((c))", options: ["always"] }, + { code: "(a) \n? (b)\n: (c)", options: ["always"] }, + { code: "((a)) \n? ((b))\n: ((c))", options: ["always"] }, + { code: "((a)) ?\n ((b)):\n ((c))", options: ["always"] }, // "always-multiline" { code: "a\n? b\n: c", options: ["always-multiline"] }, @@ -43,11 +59,56 @@ ruleTester.run("multiline-ternary", rule, { { code: "a ? (b ? c : d) : e", options: ["always-multiline"] }, { code: "a\n? (b ? c : d)\n: e", options: ["always-multiline"] }, { code: "a ?\n(b ? c : d) :\ne", options: ["always-multiline"] }, + { code: "(a\n ? b\n : c)", options: ["always-multiline"] }, + { code: "(\na ? b : c\n)", options: ["always-multiline"] }, + { code: "(a)\n? b\n: c", options: ["always-multiline"] }, + { code: "((a))\n? b\n: c", options: ["always-multiline"] }, + { code: "(a)?\n b\n: c", options: ["always-multiline"] }, + { code: "((a))?\n b\n: c", options: ["always-multiline"] }, + { code: "a\n? (b)\n: c", options: ["always-multiline"] }, + { code: "a\n? ((b))\n: c", options: ["always-multiline"] }, + { code: "a ?\n (b)\n: c", options: ["always-multiline"] }, + { code: "a ?\n ((b))\n: c", options: ["always-multiline"] }, + { code: "a \n? b\n: (c)", options: ["always-multiline"] }, + { code: "a \n? b\n: ((c))", options: ["always-multiline"] }, + { code: "a \n? b:\n (c)", options: ["always-multiline"] }, + { code: "a \n? b:\n ((c))", options: ["always-multiline"] }, + { code: "(a) \n? (b)\n: (c)", options: ["always-multiline"] }, + { code: "((a)) \n? ((b))\n: ((c))", options: ["always-multiline"] }, + { code: "((a)) ?\n ((b)):\n ((c))", options: ["always-multiline"] }, + { code: "(a) ? b : c", options: ["always-multiline"] }, + { code: "((a)) ? b : c", options: ["always-multiline"] }, + { code: "a ? (b) : c", options: ["always-multiline"] }, + { code: "a ? ((b)) : c", options: ["always-multiline"] }, + { code: "a ? b : (c)", options: ["always-multiline"] }, + { code: "a ? b : ((c))", options: ["always-multiline"] }, + { code: "(a) ? (b) : (c)", options: ["always-multiline"] }, + { code: "((a)) ? ((b)) : ((c))", options: ["always-multiline"] }, // "never" { code: "a ? b : c", options: ["never"] }, { code: "a ? b ? c : d : e", options: ["never"] }, - { code: "a ? (b ? c : d) : e", options: ["never"] } + { code: "a ? (b ? c : d) : e", options: ["never"] }, + { code: "a +\n b ? c +\n d : e + \nf", options: ["never"] }, + { code: "(\na ? b : c\n)", options: ["never"] }, + { code: "(a) ? b : c", options: ["never"] }, + { code: "((a)) ? b : c", options: ["never"] }, + { code: "a ? (b) : c", options: ["never"] }, + { code: "a ? ((b)) : c", options: ["never"] }, + { code: "a ? b : (c)", options: ["never"] }, + { code: "a ? b : ((c))", options: ["never"] }, + { code: "(a) ? (b) : (c)", options: ["never"] }, + { code: "((a)) ? ((b)) : ((c))", options: ["never"] }, + { code: "(a\n) ? b : c", options: ["never"] }, + { code: "((a)\n) ? b : c", options: ["never"] }, + { code: "a ? (\nb) : c", options: ["never"] }, + { code: "a ? (\n(b)) : c", options: ["never"] }, + { code: "a ? (b\n) : c", options: ["never"] }, + { code: "a ? ((b)\n) : c", options: ["never"] }, + { code: "a ? b : (\nc)", options: ["never"] }, + { code: "a ? b : (\n(c))", options: ["never"] }, + { code: "(a\n) ? (\nb\n) : (\nc)", options: ["never"] }, + { code: "((a)\n) ? (\n(b)\n) : (\n(c))", options: ["never"] } ], invalid: [ @@ -92,7 +153,9 @@ ruleTester.run("multiline-ternary", rule, { { messageId: "expectedConsAlt", line: 1, - column: 6 + column: 5, + endLine: 1, + endColumn: 16 }, { messageId: "expectedTestCons", @@ -128,7 +191,9 @@ ruleTester.run("multiline-ternary", rule, { { messageId: "expectedConsAlt", line: 1, - column: 6 + column: 5, + endLine: 3, + endColumn: 5 }] }, { @@ -136,7 +201,9 @@ ruleTester.run("multiline-ternary", rule, { errors: [{ messageId: "expectedConsAlt", line: 2, - column: 2 + column: 1, + endLine: 3, + endColumn: 5 }, { messageId: "expectedTestCons", @@ -149,7 +216,9 @@ ruleTester.run("multiline-ternary", rule, { errors: [{ messageId: "expectedConsAlt", line: 2, - column: 2 + column: 1, + endLine: 3, + endColumn: 9 }, { messageId: "expectedConsAlt", @@ -162,7 +231,9 @@ ruleTester.run("multiline-ternary", rule, { errors: [{ messageId: "expectedConsAlt", line: 2, - column: 2 + column: 1, + endLine: 4, + endColumn: 6 }] }, @@ -173,12 +244,34 @@ ruleTester.run("multiline-ternary", rule, { errors: [{ messageId: "expectedTestCons", line: 1, - column: 1 + column: 1, + endLine: 1, + endColumn: 2 }, { messageId: "expectedConsAlt", line: 1, - column: 5 + column: 5, + endLine: 1, + endColumn: 6 + }] + }, + { + code: "f() ? a + b : c", + options: ["always"], + errors: [{ + messageId: "expectedTestCons", + line: 1, + column: 1, + endLine: 1, + endColumn: 4 + }, + { + messageId: "expectedConsAlt", + line: 1, + column: 7, + endLine: 1, + endColumn: 12 }] }, { @@ -210,7 +303,9 @@ ruleTester.run("multiline-ternary", rule, { { messageId: "expectedConsAlt", line: 1, - column: 6 + column: 5, + endLine: 1, + endColumn: 16 }, { messageId: "expectedTestCons", @@ -248,7 +343,9 @@ ruleTester.run("multiline-ternary", rule, { { messageId: "expectedConsAlt", line: 1, - column: 6 + column: 5, + endLine: 3, + endColumn: 5 }] }, { @@ -257,7 +354,9 @@ ruleTester.run("multiline-ternary", rule, { errors: [{ messageId: "expectedConsAlt", line: 2, - column: 2 + column: 1, + endLine: 3, + endColumn: 5 }, { messageId: "expectedTestCons", @@ -271,7 +370,9 @@ ruleTester.run("multiline-ternary", rule, { errors: [{ messageId: "expectedConsAlt", line: 2, - column: 2 + column: 1, + endLine: 3, + endColumn: 9 }, { messageId: "expectedConsAlt", @@ -285,7 +386,133 @@ ruleTester.run("multiline-ternary", rule, { errors: [{ messageId: "expectedConsAlt", line: 2, - column: 2 + column: 1, + endLine: 4, + endColumn: 6 + }] + }, + { + code: "(a\n) ? b\n: c", + options: ["always"], + errors: [{ + messageId: "expectedTestCons", + line: 1, + column: 1, + endLine: 2, + endColumn: 2 + }] + }, + { + code: "((a)\n) ? b\n: c", + options: ["always"], + errors: [{ + messageId: "expectedTestCons", + line: 1, + column: 1, + endLine: 2, + endColumn: 2 + }] + }, + { + code: "a ? (\nb)\n: c", + options: ["always"], + errors: [{ + messageId: "expectedTestCons", + line: 1, + column: 1, + endLine: 1, + endColumn: 2 + }] + }, + { + code: "a ? (\n(b))\n: c", + options: ["always"], + errors: [{ + messageId: "expectedTestCons", + line: 1, + column: 1, + endLine: 1, + endColumn: 2 + }] + }, + { + code: "a\n? (b\n): c", + options: ["always"], + errors: [{ + messageId: "expectedConsAlt", + line: 2, + column: 3, + endLine: 3, + endColumn: 2 + }] + }, + { + code: "a\n? ((b)\n): c", + options: ["always"], + errors: [{ + messageId: "expectedConsAlt", + line: 2, + column: 3, + endLine: 3, + endColumn: 2 + }] + }, + { + code: "a\n? b : (\nc)", + options: ["always"], + errors: [{ + messageId: "expectedConsAlt", + line: 2, + column: 3, + endLine: 2, + endColumn: 4 + }] + }, + { + code: "a\n? b : (\n(c))", + options: ["always"], + errors: [{ + messageId: "expectedConsAlt", + line: 2, + column: 3, + endLine: 2, + endColumn: 4 + }] + }, + { + code: "(a\n) ? (\nb\n) : (\nc)", + options: ["always"], + errors: [{ + messageId: "expectedTestCons", + line: 1, + column: 1, + endLine: 2, + endColumn: 2 + }, + { + messageId: "expectedConsAlt", + line: 2, + column: 5, + endLine: 4, + endColumn: 2 + }] + }, + { + code: "((a)\n) ? (\n(b)\n) : (\n(c))", + options: ["always"], + errors: [{ + messageId: "expectedTestCons", + line: 1, + column: 1, + endLine: 2, + endColumn: 2 + }, + { + messageId: "expectedConsAlt", + line: 2, + column: 5, + endLine: 4, + endColumn: 2 }] }, @@ -314,7 +541,9 @@ ruleTester.run("multiline-ternary", rule, { errors: [{ messageId: "expectedTestCons", line: 1, - column: 1 + column: 1, + endLine: 2, + endColumn: 2 }, { messageId: "expectedConsAlt", @@ -356,7 +585,9 @@ ruleTester.run("multiline-ternary", rule, { errors: [{ messageId: "expectedConsAlt", line: 2, - column: 2 + column: 1, + endLine: 2, + endColumn: 12 }] }, { @@ -379,7 +610,9 @@ ruleTester.run("multiline-ternary", rule, { { messageId: "expectedConsAlt", line: 1, - column: 6 + column: 5, + endLine: 3, + endColumn: 5 }] }, { @@ -388,7 +621,9 @@ ruleTester.run("multiline-ternary", rule, { errors: [{ messageId: "expectedConsAlt", line: 2, - column: 2 + column: 1, + endLine: 3, + endColumn: 5 }, { messageId: "expectedTestCons", @@ -402,7 +637,9 @@ ruleTester.run("multiline-ternary", rule, { errors: [{ messageId: "expectedConsAlt", line: 2, - column: 2 + column: 1, + endLine: 3, + endColumn: 9 }, { messageId: "expectedConsAlt", @@ -416,7 +653,133 @@ ruleTester.run("multiline-ternary", rule, { errors: [{ messageId: "expectedConsAlt", line: 2, - column: 2 + column: 1, + endLine: 4, + endColumn: 6 + }] + }, + { + code: "(a\n) ? b\n: c", + options: ["always-multiline"], + errors: [{ + messageId: "expectedTestCons", + line: 1, + column: 1, + endLine: 2, + endColumn: 2 + }] + }, + { + code: "((a)\n) ? b\n: c", + options: ["always-multiline"], + errors: [{ + messageId: "expectedTestCons", + line: 1, + column: 1, + endLine: 2, + endColumn: 2 + }] + }, + { + code: "a ? (\nb)\n: c", + options: ["always-multiline"], + errors: [{ + messageId: "expectedTestCons", + line: 1, + column: 1, + endLine: 1, + endColumn: 2 + }] + }, + { + code: "a ? (\n(b))\n: c", + options: ["always-multiline"], + errors: [{ + messageId: "expectedTestCons", + line: 1, + column: 1, + endLine: 1, + endColumn: 2 + }] + }, + { + code: "a\n? (b\n): c", + options: ["always-multiline"], + errors: [{ + messageId: "expectedConsAlt", + line: 2, + column: 3, + endLine: 3, + endColumn: 2 + }] + }, + { + code: "a\n? ((b)\n): c", + options: ["always-multiline"], + errors: [{ + messageId: "expectedConsAlt", + line: 2, + column: 3, + endLine: 3, + endColumn: 2 + }] + }, + { + code: "a\n? b : (\nc)", + options: ["always-multiline"], + errors: [{ + messageId: "expectedConsAlt", + line: 2, + column: 3, + endLine: 2, + endColumn: 4 + }] + }, + { + code: "a\n? b : (\n(c))", + options: ["always-multiline"], + errors: [{ + messageId: "expectedConsAlt", + line: 2, + column: 3, + endLine: 2, + endColumn: 4 + }] + }, + { + code: "(a\n) ? (\nb\n) : (\nc)", + options: ["always-multiline"], + errors: [{ + messageId: "expectedTestCons", + line: 1, + column: 1, + endLine: 2, + endColumn: 2 + }, + { + messageId: "expectedConsAlt", + line: 2, + column: 5, + endLine: 4, + endColumn: 2 + }] + }, + { + code: "((a)\n) ? (\n(b)\n) : (\n(c))", + options: ["always-multiline"], + errors: [{ + messageId: "expectedTestCons", + line: 1, + column: 1, + endLine: 2, + endColumn: 2 + }, + { + messageId: "expectedConsAlt", + line: 2, + column: 5, + endLine: 4, + endColumn: 2 }] }, @@ -450,7 +813,9 @@ ruleTester.run("multiline-ternary", rule, { { messageId: "unexpectedConsAlt", line: 2, - column: 2 + column: 1, + endLine: 2, + endColumn: 12 }] }, { @@ -520,7 +885,9 @@ ruleTester.run("multiline-ternary", rule, { errors: [{ messageId: "unexpectedConsAlt", line: 1, - column: 6 + column: 5, + endLine: 3, + endColumn: 5 }, { messageId: "unexpectedTestCons", @@ -544,7 +911,9 @@ ruleTester.run("multiline-ternary", rule, { { messageId: "unexpectedConsAlt", line: 3, - column: 2 + column: 1, + endLine: 7, + endColumn: 3 }, { messageId: "unexpectedTestCons", @@ -556,6 +925,60 @@ ruleTester.run("multiline-ternary", rule, { line: 5, column: 1 }] + }, + { + code: "(a)\n ? b \n : (c)", + options: ["never"], + errors: [{ + messageId: "unexpectedTestCons", + line: 1, + column: 1, + endLine: 1, + endColumn: 4 + }, + { + messageId: "unexpectedConsAlt", + line: 2, + column: 4, + endLine: 2, + endColumn: 5 + }] + }, + { + code: "(a)\n ? (b) \n : (c)", + options: ["never"], + errors: [{ + messageId: "unexpectedTestCons", + line: 1, + column: 1, + endLine: 1, + endColumn: 4 + }, + { + messageId: "unexpectedConsAlt", + line: 2, + column: 4, + endLine: 2, + endColumn: 7 + }] + }, + { + code: "((a))\n ? ((b)) \n : ((c))", + options: ["never"], + errors: [{ + messageId: "unexpectedTestCons", + line: 1, + column: 1, + endLine: 1, + endColumn: 6 + }, + { + messageId: "unexpectedConsAlt", + line: 2, + column: 4, + endLine: 2, + endColumn: 9 + }] } ] }); diff --git a/eslint/tests/lib/rules/no-extra-boolean-cast.js b/eslint/tests/lib/rules/no-extra-boolean-cast.js index 715fe91..70ec8bd 100644 --- a/eslint/tests/lib/rules/no-extra-boolean-cast.js +++ b/eslint/tests/lib/rules/no-extra-boolean-cast.js @@ -105,6 +105,11 @@ ruleTester.run("no-extra-boolean-cast", rule, { { code: "if ((!!foo || bar) === baz) {}", options: [{ enforceForLogicalOperands: true }] + }, + { + code: "if (!!foo ?? bar) {}", + options: [{ enforceForLogicalOperands: true }], + parserOptions: { ecmaVersion: 2020 } } ], @@ -2395,6 +2400,14 @@ ruleTester.run("no-extra-boolean-cast", rule, { { messageId: "unexpectedNegation", type: "UnaryExpression" }, { messageId: "unexpectedCall", type: "CallExpression" } ] + }, + + { + code: "if (Boolean(a ?? b) || c) {}", + output: "if ((a ?? b) || c) {}", + options: [{ enforceForLogicalOperands: true }], + parserOptions: { ecmaVersion: 2020 }, + errors: [{ messageId: "unexpectedCall", type: "CallExpression" }] } ] }); diff --git a/eslint/tests/lib/rules/no-extra-parens.js b/eslint/tests/lib/rules/no-extra-parens.js index 5062857..91099f8 100644 --- a/eslint/tests/lib/rules/no-extra-parens.js +++ b/eslint/tests/lib/rules/no-extra-parens.js @@ -508,6 +508,27 @@ ruleTester.run("no-extra-parens", rule, { { code: "(new foo.bar()).baz()", options: ["all", { enforceForNewInMemberExpressions: false }] }, { code: "((new foo.bar())).baz()", options: ["all", { enforceForNewInMemberExpressions: false }] }, + // ["all", { enforceForFunctionPrototypeMethods: false }] + { code: "var foo = (function(){}).call()", options: ["all", { enforceForFunctionPrototypeMethods: false }] }, + { code: "var foo = (function(){}).apply()", options: ["all", { enforceForFunctionPrototypeMethods: false }] }, + { code: "var foo = (function(){}.call())", options: ["all", { enforceForFunctionPrototypeMethods: false }] }, + { code: "var foo = (function(){}.apply())", options: ["all", { enforceForFunctionPrototypeMethods: false }] }, + { code: "var foo = (function(){}).call(arg)", options: ["all", { enforceForFunctionPrototypeMethods: false }] }, + { code: "var foo = (function(){}.apply(arg))", options: ["all", { enforceForFunctionPrototypeMethods: false }] }, + { code: "var foo = (function(){}['call']())", options: ["all", { enforceForFunctionPrototypeMethods: false }] }, + { code: "var foo = (function(){})[`apply`]()", options: ["all", { enforceForFunctionPrototypeMethods: false }] }, + { code: "var foo = ((function(){})).call()", options: ["all", { enforceForFunctionPrototypeMethods: false }] }, + { code: "var foo = ((function(){}).apply())", options: ["all", { enforceForFunctionPrototypeMethods: false }] }, + { code: "var foo = ((function(){}.call()))", options: ["all", { enforceForFunctionPrototypeMethods: false }] }, + { code: "var foo = ((((function(){})).apply()))", options: ["all", { enforceForFunctionPrototypeMethods: false }] }, + { code: "foo((function(){}).call().bar)", options: ["all", { enforceForFunctionPrototypeMethods: false }] }, + { code: "foo = (function(){}).call()()", options: ["all", { enforceForFunctionPrototypeMethods: false }] }, + { code: "foo = (function(){}.call())()", options: ["all", { enforceForFunctionPrototypeMethods: false }] }, + { code: "var foo = { bar: (function(){}.call()) }", options: ["all", { enforceForFunctionPrototypeMethods: false }] }, + { code: "var foo = { [(function(){}.call())]: bar }", options: ["all", { enforceForFunctionPrototypeMethods: false }] }, + { code: "if((function(){}).call()){}", options: ["all", { enforceForFunctionPrototypeMethods: false }] }, + { code: "while((function(){}.apply())){}", options: ["all", { enforceForFunctionPrototypeMethods: false }] }, + "let a = [ ...b ]", "let a = { ...b }", { @@ -589,7 +610,17 @@ ruleTester.run("no-extra-parens", rule, { "for (let a = b; a; a); a; a;", "for (a; a; a); a; a;", "for (; a; a); a; a;", - "for (let a = (b && c) === d; ;);" + "for (let a = (b && c) === d; ;);", + + // Nullish coalescing + { code: "var v = (a ?? b) || c", parserOptions: { ecmaVersion: 2020 } }, + { code: "var v = a ?? (b || c)", parserOptions: { ecmaVersion: 2020 } }, + { code: "var v = (a ?? b) && c", parserOptions: { ecmaVersion: 2020 } }, + { code: "var v = a ?? (b && c)", parserOptions: { ecmaVersion: 2020 } }, + { code: "var v = (a || b) ?? c", parserOptions: { ecmaVersion: 2020 } }, + { code: "var v = a || (b ?? c)", parserOptions: { ecmaVersion: 2020 } }, + { code: "var v = (a && b) ?? c", parserOptions: { ecmaVersion: 2020 } }, + { code: "var v = a && (b ?? c)", parserOptions: { ecmaVersion: 2020 } } ], invalid: [ @@ -1293,6 +1324,316 @@ ruleTester.run("no-extra-parens", rule, { ] }, + // enforceForFunctionPrototypeMethods + { + code: "var foo = (function(){}).call()", + output: "var foo = function(){}.call()", + options: ["all"], + errors: [ + { + messageId: "unexpected", + type: "FunctionExpression" + } + ] + }, + { + code: "var foo = (function(){}.apply())", + output: "var foo = function(){}.apply()", + options: ["all"], + errors: [ + { + messageId: "unexpected", + type: "CallExpression" + } + ] + }, + { + code: "var foo = (function(){}).apply()", + output: "var foo = function(){}.apply()", + options: ["all", {}], + errors: [ + { + messageId: "unexpected", + type: "FunctionExpression" + } + ] + }, + { + code: "var foo = (function(){}.call())", + output: "var foo = function(){}.call()", + options: ["all", {}], + errors: [ + { + messageId: "unexpected", + type: "CallExpression" + } + ] + }, + { + code: "var foo = (function(){}).call()", + output: "var foo = function(){}.call()", + options: ["all", { enforceForFunctionPrototypeMethods: true }], + errors: [ + { + messageId: "unexpected", + type: "FunctionExpression" + } + ] + }, + { + code: "var foo = (function(){}).apply()", + output: "var foo = function(){}.apply()", + options: ["all", { enforceForFunctionPrototypeMethods: true }], + errors: [ + { + messageId: "unexpected", + type: "FunctionExpression" + } + ] + }, + { + code: "var foo = (function(){}.call())", + output: "var foo = function(){}.call()", + options: ["all", { enforceForFunctionPrototypeMethods: true }], + errors: [ + { + messageId: "unexpected", + type: "CallExpression" + } + ] + }, + { + code: "var foo = (function(){}.apply())", + output: "var foo = function(){}.apply()", + options: ["all", { enforceForFunctionPrototypeMethods: true }], + errors: [ + { + messageId: "unexpected", + type: "CallExpression" + } + ] + }, + { + code: "var foo = (function(){}.call)()", // removing these parens does not cause any conflicts with wrap-iife + output: "var foo = function(){}.call()", + options: ["all", { enforceForFunctionPrototypeMethods: false }], + errors: [ + { + messageId: "unexpected", + type: "MemberExpression" + } + ] + }, + { + code: "var foo = (function(){}.apply)()", // removing these parens does not cause any conflicts with wrap-iife + output: "var foo = function(){}.apply()", + options: ["all", { enforceForFunctionPrototypeMethods: false }], + errors: [ + { + messageId: "unexpected", + type: "MemberExpression" + } + ] + }, + { + code: "var foo = (function(){}).call", + output: "var foo = function(){}.call", + options: ["all", { enforceForFunctionPrototypeMethods: false }], + errors: [ + { + messageId: "unexpected", + type: "FunctionExpression" + } + ] + }, + { + code: "var foo = (function(){}.call)", + output: "var foo = function(){}.call", + options: ["all", { enforceForFunctionPrototypeMethods: false }], + errors: [ + { + messageId: "unexpected", + type: "MemberExpression" + } + ] + }, + { + code: "var foo = new (function(){}).call()", + output: "var foo = new function(){}.call()", + options: ["all", { enforceForFunctionPrototypeMethods: false }], + errors: [ + { + messageId: "unexpected", + type: "FunctionExpression" + } + ] + }, + { + code: "var foo = (new function(){}.call())", + output: "var foo = new function(){}.call()", + options: ["all", { enforceForFunctionPrototypeMethods: false }], + errors: [ + { + messageId: "unexpected", + type: "NewExpression" + } + ] + }, + { + code: "var foo = (function(){})[call]()", + output: "var foo = function(){}[call]()", + options: ["all", { enforceForFunctionPrototypeMethods: false }], + errors: [ + { + messageId: "unexpected", + type: "FunctionExpression" + } + ] + }, + { + code: "var foo = (function(){}[apply]())", + output: "var foo = function(){}[apply]()", + options: ["all", { enforceForFunctionPrototypeMethods: false }], + errors: [ + { + messageId: "unexpected", + type: "CallExpression" + } + ] + }, + { + code: "var foo = (function(){}).bar()", + output: "var foo = function(){}.bar()", + options: ["all", { enforceForFunctionPrototypeMethods: false }], + errors: [ + { + messageId: "unexpected", + type: "FunctionExpression" + } + ] + }, + { + code: "var foo = (function(){}.bar())", + output: "var foo = function(){}.bar()", + options: ["all", { enforceForFunctionPrototypeMethods: false }], + errors: [ + { + messageId: "unexpected", + type: "CallExpression" + } + ] + }, + { + code: "var foo = (function(){}).call.call()", + output: "var foo = function(){}.call.call()", + options: ["all", { enforceForFunctionPrototypeMethods: false }], + errors: [ + { + messageId: "unexpected", + type: "FunctionExpression" + } + ] + }, + { + code: "var foo = (function(){}.call.call())", + output: "var foo = function(){}.call.call()", + options: ["all", { enforceForFunctionPrototypeMethods: false }], + errors: [ + { + messageId: "unexpected", + type: "CallExpression" + } + ] + }, + { + code: "var foo = (call())", + output: "var foo = call()", + options: ["all", { enforceForFunctionPrototypeMethods: false }], + errors: [ + { + messageId: "unexpected", + type: "CallExpression" + } + ] + }, + { + code: "var foo = (apply())", + output: "var foo = apply()", + options: ["all", { enforceForFunctionPrototypeMethods: false }], + errors: [ + { + messageId: "unexpected", + type: "CallExpression" + } + ] + }, + { + code: "var foo = (bar).call()", + output: "var foo = bar.call()", + options: ["all", { enforceForFunctionPrototypeMethods: false }], + errors: [ + { + messageId: "unexpected", + type: "Identifier" + } + ] + }, + { + code: "var foo = (bar.call())", + output: "var foo = bar.call()", + options: ["all", { enforceForFunctionPrototypeMethods: false }], + errors: [ + { + messageId: "unexpected", + type: "CallExpression" + } + ] + }, + { + code: "((() => {}).call())", + output: "(() => {}).call()", + options: ["all", { enforceForFunctionPrototypeMethods: false }], + errors: [ + { + messageId: "unexpected", + type: "CallExpression" + } + ] + }, + { + code: "var foo = function(){}.call((a.b))", + output: "var foo = function(){}.call(a.b)", + options: ["all", { enforceForFunctionPrototypeMethods: false }], + errors: [ + { + messageId: "unexpected", + type: "MemberExpression" + } + ] + }, + { + code: "var foo = function(){}.call((a).b)", + output: "var foo = function(){}.call(a.b)", + options: ["all", { enforceForFunctionPrototypeMethods: false }], + errors: [ + { + messageId: "unexpected", + type: "Identifier" + } + ] + }, + { + code: "var foo = function(){}[('call')]()", + output: "var foo = function(){}['call']()", + options: ["all", { enforceForFunctionPrototypeMethods: false }], + errors: [ + { + messageId: "unexpected", + type: "Literal" + } + ] + }, + // https://github.com/eslint/eslint/issues/8175 invalid( "let a = [...(b)]", @@ -2288,6 +2629,75 @@ ruleTester.run("no-extra-parens", rule, { invalid("a+(/^b$/)", "a+/^b$/", "Literal"), invalid("a/(/**/b)", "a/ /**/b", "Identifier"), invalid("a/(//\nb)", "a/ //\nb", "Identifier"), - invalid("a/(/^b$/)", "a/ /^b$/", "Literal") + invalid("a/(/^b$/)", "a/ /^b$/", "Literal"), + + + // Nullish coalescing + { + code: "var v = ((a ?? b)) || c", + output: "var v = (a ?? b) || c", + parserOptions: { ecmaVersion: 2020 }, + errors: [{ messageId: "unexpected" }] + }, + { + code: "var v = a ?? ((b || c))", + output: "var v = a ?? (b || c)", + parserOptions: { ecmaVersion: 2020 }, + errors: [{ messageId: "unexpected" }] + }, + { + code: "var v = ((a ?? b)) && c", + output: "var v = (a ?? b) && c", + parserOptions: { ecmaVersion: 2020 }, + errors: [{ messageId: "unexpected" }] + }, + { + code: "var v = a ?? ((b && c))", + output: "var v = a ?? (b && c)", + parserOptions: { ecmaVersion: 2020 }, + errors: [{ messageId: "unexpected" }] + }, + { + code: "var v = ((a || b)) ?? c", + output: "var v = (a || b) ?? c", + parserOptions: { ecmaVersion: 2020 }, + errors: [{ messageId: "unexpected" }] + }, + { + code: "var v = a || ((b ?? c))", + output: "var v = a || (b ?? c)", + parserOptions: { ecmaVersion: 2020 }, + errors: [{ messageId: "unexpected" }] + }, + { + code: "var v = ((a && b)) ?? c", + output: "var v = (a && b) ?? c", + parserOptions: { ecmaVersion: 2020 }, + errors: [{ messageId: "unexpected" }] + }, + { + code: "var v = a && ((b ?? c))", + output: "var v = a && (b ?? c)", + parserOptions: { ecmaVersion: 2020 }, + errors: [{ messageId: "unexpected" }] + }, + { + code: "var v = (a ?? b) ? b : c", + output: "var v = a ?? b ? b : c", + parserOptions: { ecmaVersion: 2020 }, + errors: [{ messageId: "unexpected" }] + }, + { + code: "var v = (a | b) ?? c | d", + output: "var v = a | b ?? c | d", + parserOptions: { ecmaVersion: 2020 }, + errors: [{ messageId: "unexpected" }] + }, + { + code: "var v = a | b ?? (c | d)", + output: "var v = a | b ?? c | d", + parserOptions: { ecmaVersion: 2020 }, + errors: [{ messageId: "unexpected" }] + } ] }); diff --git a/eslint/tests/lib/rules/no-mixed-operators.js b/eslint/tests/lib/rules/no-mixed-operators.js index 0e79b56..3650cd0 100644 --- a/eslint/tests/lib/rules/no-mixed-operators.js +++ b/eslint/tests/lib/rules/no-mixed-operators.js @@ -363,6 +363,31 @@ ruleTester.run("no-mixed-operators", rule, { } } ] + }, + { + code: "a + b ?? c", + options: [{ groups: [["+", "??"]] }], + parserOptions: { ecmaVersion: 2020 }, + errors: [ + { + column: 3, + endColumn: 4, + messageId: "unexpectedMixedOperator", + data: { + leftOperator: "+", + rightOperator: "??" + } + }, + { + column: 7, + endColumn: 9, + messageId: "unexpectedMixedOperator", + data: { + leftOperator: "+", + rightOperator: "??" + } + } + ] } ] }); diff --git a/eslint/tests/lib/rules/no-mixed-spaces-and-tabs.js b/eslint/tests/lib/rules/no-mixed-spaces-and-tabs.js index 4e43870..4dd475d 100644 --- a/eslint/tests/lib/rules/no-mixed-spaces-and-tabs.js +++ b/eslint/tests/lib/rules/no-mixed-spaces-and-tabs.js @@ -20,8 +20,15 @@ const ruleTester = new RuleTester(); ruleTester.run("no-mixed-spaces-and-tabs", rule, { valid: [ + "foo", + "foo \t", + "foo\t ", "\tvar x = 5;", + "\t\tvar x = 5;", + " var x = 5;", " var x = 5;", + " foo\t", + "\tfoo ", "\t/*\n\t * Hello\n\t */", "// foo\n\t/**\n\t * Hello\n\t */", "/*\n\n \t \n*/", @@ -80,6 +87,50 @@ ruleTester.run("no-mixed-spaces-and-tabs", rule, { { code: "\tvar x = 5,\n\t y = 2;", options: ["smart-tabs"] + }, + { + code: "\t\t\t foo", + options: ["smart-tabs"] + }, + { + code: "foo", + options: ["smart-tabs"] + }, + { + code: "foo \t", + options: ["smart-tabs"] + }, + { + code: "foo\t ", + options: ["smart-tabs"] + }, + { + code: "\tfoo \t", + options: ["smart-tabs"] + }, + { + code: "\tvar x = 5;", + options: ["smart-tabs"] + }, + { + code: "\t\tvar x = 5;", + options: ["smart-tabs"] + }, + { + code: " var x = 5;", + options: ["smart-tabs"] + }, + { + code: " var x = 5;", + options: ["smart-tabs"] + }, + { + code: " foo\t", + options: ["smart-tabs"] + }, + { + code: "\tfoo ", + options: ["smart-tabs"] } ], @@ -90,7 +141,10 @@ ruleTester.run("no-mixed-spaces-and-tabs", rule, { { messageId: "mixedSpacesAndTabs", type: "Program", - line: 2 + line: 2, + column: 1, + endLine: 2, + endColumn: 3 } ] }, @@ -100,7 +154,10 @@ ruleTester.run("no-mixed-spaces-and-tabs", rule, { { messageId: "mixedSpacesAndTabs", type: "Program", - line: 1 + line: 1, + column: 1, + endLine: 1, + endColumn: 3 } ] }, @@ -110,7 +167,10 @@ ruleTester.run("no-mixed-spaces-and-tabs", rule, { { messageId: "mixedSpacesAndTabs", type: "Program", - line: 1 + line: 1, + column: 1, + endLine: 1, + endColumn: 3 } ] }, @@ -120,7 +180,10 @@ ruleTester.run("no-mixed-spaces-and-tabs", rule, { { messageId: "mixedSpacesAndTabs", type: "Program", - line: 1 + line: 1, + column: 1, + endLine: 1, + endColumn: 3 } ] }, @@ -130,7 +193,10 @@ ruleTester.run("no-mixed-spaces-and-tabs", rule, { { messageId: "mixedSpacesAndTabs", type: "Program", - line: 1 + line: 1, + column: 1, + endLine: 1, + endColumn: 3 } ] }, @@ -140,7 +206,10 @@ ruleTester.run("no-mixed-spaces-and-tabs", rule, { { messageId: "mixedSpacesAndTabs", type: "Program", - line: 1 + line: 1, + column: 1, + endLine: 1, + endColumn: 3 } ] }, @@ -150,7 +219,10 @@ ruleTester.run("no-mixed-spaces-and-tabs", rule, { { messageId: "mixedSpacesAndTabs", type: "Program", - line: 2 + line: 2, + column: 1, + endLine: 2, + endColumn: 3 } ] }, @@ -160,12 +232,18 @@ ruleTester.run("no-mixed-spaces-and-tabs", rule, { { messageId: "mixedSpacesAndTabs", type: "Program", - line: 1 + line: 1, + column: 1, + endLine: 1, + endColumn: 3 }, { messageId: "mixedSpacesAndTabs", type: "Program", - line: 3 + line: 3, + column: 1, + endLine: 3, + endColumn: 3 } ] }, @@ -176,7 +254,10 @@ ruleTester.run("no-mixed-spaces-and-tabs", rule, { { messageId: "mixedSpacesAndTabs", type: "Program", - line: 2 + line: 2, + column: 2, + endLine: 2, + endColumn: 4 } ] }, @@ -187,7 +268,10 @@ ruleTester.run("no-mixed-spaces-and-tabs", rule, { { messageId: "mixedSpacesAndTabs", type: "Program", - line: 2 + line: 2, + column: 2, + endLine: 2, + endColumn: 4 } ] }, @@ -200,7 +284,9 @@ ruleTester.run("no-mixed-spaces-and-tabs", rule, { messageId: "mixedSpacesAndTabs", type: "Program", line: 2, - column: 2 + column: 1, + endLine: 2, + endColumn: 3 } ] }, @@ -212,7 +298,9 @@ ruleTester.run("no-mixed-spaces-and-tabs", rule, { messageId: "mixedSpacesAndTabs", type: "Program", line: 2, - column: 2 + column: 1, + endLine: 2, + endColumn: 3 } ] }, @@ -222,7 +310,10 @@ ruleTester.run("no-mixed-spaces-and-tabs", rule, { { messageId: "mixedSpacesAndTabs", type: "Program", - line: 1 + line: 1, + column: 2, + endLine: 1, + endColumn: 4 } ] }, @@ -232,7 +323,64 @@ ruleTester.run("no-mixed-spaces-and-tabs", rule, { { messageId: "mixedSpacesAndTabs", type: "Program", - line: 2 + line: 2, + column: 1, + endLine: 2, + endColumn: 3 + } + ] + }, + { + code: " \tfoo", + errors: [ + { + messageId: "mixedSpacesAndTabs", + type: "Program", + line: 1, + column: 3, + endLine: 1, + endColumn: 5 + } + ] + }, + { + code: "\t\t\t foo", + errors: [ + { + messageId: "mixedSpacesAndTabs", + type: "Program", + line: 1, + column: 3, + endLine: 1, + endColumn: 5 + } + ] + }, + { + code: "\t \tfoo", + options: ["smart-tabs"], + errors: [ + { + messageId: "mixedSpacesAndTabs", + type: "Program", + line: 1, + column: 2, + endLine: 1, + endColumn: 4 + } + ] + }, + { + code: "\t\t\t \tfoo", + options: ["smart-tabs"], + errors: [ + { + messageId: "mixedSpacesAndTabs", + type: "Program", + line: 1, + column: 6, + endLine: 1, + endColumn: 8 } ] } diff --git a/eslint/tests/lib/rules/no-restricted-exports.js b/eslint/tests/lib/rules/no-restricted-exports.js index 6d0e693..31458f1 100644 --- a/eslint/tests/lib/rules/no-restricted-exports.js +++ b/eslint/tests/lib/rules/no-restricted-exports.js @@ -16,7 +16,7 @@ const { RuleTester } = require("../../../lib/rule-tester"); // Tests //------------------------------------------------------------------------------ -const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 2018, sourceType: "module" } }); +const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 2020, sourceType: "module" } }); ruleTester.run("no-restricted-exports", rule, { valid: [ @@ -73,6 +73,7 @@ ruleTester.run("no-restricted-exports", rule, { // does not check source in re-export declarations { code: "export { b } from 'a';", options: [{ restrictedNamedExports: ["a"] }] }, + { code: "export * as b from 'a';", options: [{ restrictedNamedExports: ["a"] }] }, // does not check non-export declarations { code: "var a;", options: [{ restrictedNamedExports: ["a"] }] }, @@ -332,6 +333,11 @@ ruleTester.run("no-restricted-exports", rule, { options: [{ restrictedNamedExports: ["a"] }], errors: [{ messageId: "restrictedNamed", data: { name: "a" }, type: "Identifier", column: 15 }] }, + { + code: "export * as a from 'a';", + options: [{ restrictedNamedExports: ["a"] }], + errors: [{ messageId: "restrictedNamed", data: { name: "a" }, type: "Identifier", column: 13 }] + }, // Note: duplicate identifiers in the same export declaration are a 'duplicate export' syntax error. Example: export var a, a; diff --git a/eslint/tests/lib/rules/no-restricted-imports.js b/eslint/tests/lib/rules/no-restricted-imports.js index 680bc13..3632297 100644 --- a/eslint/tests/lib/rules/no-restricted-imports.js +++ b/eslint/tests/lib/rules/no-restricted-imports.js @@ -16,7 +16,7 @@ const rule = require("../../../lib/rules/no-restricted-imports"), // Tests //------------------------------------------------------------------------------ -const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 6, sourceType: "module" } }); +const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 2020, sourceType: "module" } }); ruleTester.run("no-restricted-imports", rule, { valid: [ @@ -261,6 +261,16 @@ ruleTester.run("no-restricted-imports", rule, { column: 1, endColumn: 20 }] + }, { + code: "export * as ns from \"fs\";", + options: ["fs"], + errors: [{ + message: "'fs' import is restricted from being used.", + type: "ExportAllDeclaration", + line: 1, + column: 1, + endColumn: 26 + }] }, { code: "export {a} from \"fs\";", options: ["fs"], @@ -287,6 +297,22 @@ ruleTester.run("no-restricted-imports", rule, { column: 9, endColumn: 17 }] + }, { + code: "export * as ns from \"fs\";", + options: [{ + paths: [{ + name: "fs", + importNames: ["foo"], + message: "Don't import 'foo'." + }] + }], + errors: [{ + message: "* import is invalid because 'foo' from 'fs' is restricted. Don't import 'foo'.", + type: "ExportAllDeclaration", + line: 1, + column: 8, + endColumn: 9 + }] }, { code: "import withGitignores from \"foo\";", options: [{ diff --git a/eslint/tests/lib/rules/no-undef.js b/eslint/tests/lib/rules/no-undef.js index 13bca8c..8c9c053 100644 --- a/eslint/tests/lib/rules/no-undef.js +++ b/eslint/tests/lib/rules/no-undef.js @@ -71,13 +71,25 @@ ruleTester.run("no-undef", rule, { // new.target: https://github.com/eslint/eslint/issues/5420 { code: "class A { constructor() { new.target; } }", parserOptions: { ecmaVersion: 6 } }, - // Experimental, + // Rest property { code: "var {bacon, ...others} = stuff; foo(others)", parserOptions: { ecmaVersion: 2018 }, globals: { stuff: false, foo: false } + }, + + // export * as ns from "source" + { + code: 'export * as ns from "source"', + parserOptions: { ecmaVersion: 2020, sourceType: "module" } + }, + + // import.meta + { + code: "import.meta", + parserOptions: { ecmaVersion: 2020, sourceType: "module" } } ], invalid: [ diff --git a/eslint/tests/lib/rules/no-unneeded-ternary.js b/eslint/tests/lib/rules/no-unneeded-ternary.js index 25aab8a..82479a9 100644 --- a/eslint/tests/lib/rules/no-unneeded-ternary.js +++ b/eslint/tests/lib/rules/no-unneeded-ternary.js @@ -357,6 +357,18 @@ ruleTester.run("no-unneeded-ternary", rule, { line: 1, column: 15 }] + }, + { + code: "var a = foo ? foo : a ?? b;", + output: "var a = foo || (a ?? b);", + options: [{ defaultAssignment: false }], + parserOptions: { ecmaVersion: 2020 }, + errors: [{ + messageId: "unnecessaryConditionalAssignment", + type: "ConditionalExpression", + line: 1, + column: 15 + }] } ] }); diff --git a/eslint/tests/lib/rules/no-unused-expressions.js b/eslint/tests/lib/rules/no-unused-expressions.js index 34051da..8ef2028 100644 --- a/eslint/tests/lib/rules/no-unused-expressions.js +++ b/eslint/tests/lib/rules/no-unused-expressions.js @@ -70,6 +70,10 @@ ruleTester.run("no-unused-expressions", rule, { code: "shouldNotBeAffectedByAllowTemplateTagsOption()", options: [{ allowTaggedTemplates: true }], parserOptions: { ecmaVersion: 6 } + }, + { + code: "import(\"foo\")", + parserOptions: { ecmaVersion: 11 } } ], invalid: [ diff --git a/eslint/tests/lib/rules/no-unused-vars.js b/eslint/tests/lib/rules/no-unused-vars.js index ec23aca..061ac08 100644 --- a/eslint/tests/lib/rules/no-unused-vars.js +++ b/eslint/tests/lib/rules/no-unused-vars.js @@ -304,6 +304,18 @@ ruleTester.run("no-unused-vars", rule, { { code: "const a = () => () => { a(); }; a();", parserOptions: { ecmaVersion: 2015 } + }, + + // export * as ns from "source" + { + code: 'export * as ns from "source"', + parserOptions: { ecmaVersion: 2020, sourceType: "module" } + }, + + // import.meta + { + code: "import.meta", + parserOptions: { ecmaVersion: 2020, sourceType: "module" } } ], invalid: [ @@ -444,7 +456,7 @@ ruleTester.run("no-unused-vars", rule, { code: "(function(obj) { var name; for ( name in obj ) { i(); return; } })({});", errors: [{ line: 1, - column: 22, + column: 34, messageId: "unusedVar", data: { varName: "name", @@ -457,7 +469,7 @@ ruleTester.run("no-unused-vars", rule, { code: "(function(obj) { var name; for ( name in obj ) { } })({});", errors: [{ line: 1, - column: 22, + column: 34, messageId: "unusedVar", data: { varName: "name", @@ -1021,6 +1033,62 @@ ruleTester.run("no-unused-vars", rule, { code: "const a = () => () => { a(); };", parserOptions: { ecmaVersion: 2015 }, errors: [assignedError("a")] + }, + { + code: `let myArray = [1,2,3,4].filter((x) => x == 0); + myArray = myArray.filter((x) => x == 1);`, + parserOptions: { ecmaVersion: 2015 }, + errors: [{ ...assignedError("myArray"), line: 2, column: 15 }] + }, + { + code: "const a = 1; a += 1;", + parserOptions: { ecmaVersion: 2015 }, + errors: [{ ...assignedError("a"), line: 1, column: 14 }] + }, + { + code: "var a = function() { a(); };", + errors: [{ ...assignedError("a"), line: 1, column: 22 }] + }, + { + code: "var a = function(){ return function() { a(); } };", + errors: [{ ...assignedError("a"), line: 1, column: 41 }] + }, + { + code: "const a = () => { a(); };", + parserOptions: { ecmaVersion: 2015 }, + errors: [{ ...assignedError("a"), line: 1, column: 19 }] + }, + { + code: "const a = () => () => { a(); };", + parserOptions: { ecmaVersion: 2015 }, + errors: [{ ...assignedError("a"), line: 1, column: 25 }] + }, + { + + code: `let a = 'a'; + a = 10; + function foo(){ + a = 11; + a = () => { + a = 13 + } + }`, + parserOptions: { ecmaVersion: 2020 }, + errors: [{ ...definedError("foo"), line: 3, column: 22 }, { ...assignedError("a"), line: 6, column: 21 }] + }, + { + code: `let c = 'c' +c = 10 +function foo1() { + c = 11 + c = () => { + c = 13 + } +} + +c = foo1`, + parserOptions: { ecmaVersion: 2020 }, + errors: [{ ...assignedError("c"), line: 10, column: 1 }] } ] }); diff --git a/eslint/tests/lib/rules/operator-linebreak.js b/eslint/tests/lib/rules/operator-linebreak.js index 3910ac8..18a37e3 100644 --- a/eslint/tests/lib/rules/operator-linebreak.js +++ b/eslint/tests/lib/rules/operator-linebreak.js @@ -628,6 +628,16 @@ ruleTester.run("operator-linebreak", rule, { endLine: 1, endColumn: 14 }] + }, + { + code: "foo ??\n bar", + output: "foo\n ?? bar", + options: ["after", { overrides: { "??": "before" } }], + parserOptions: { ecmaVersion: 2020 }, + errors: [{ + messageId: "operatorAtBeginning", + data: { operator: "??" } + }] } ] }); diff --git a/eslint/tests/lib/rules/template-tag-spacing.js b/eslint/tests/lib/rules/template-tag-spacing.js index 0885936..f01dbdc 100644 --- a/eslint/tests/lib/rules/template-tag-spacing.js +++ b/eslint/tests/lib/rules/template-tag-spacing.js @@ -17,8 +17,6 @@ const rule = require("../../../lib/rules/template-tag-spacing"), //------------------------------------------------------------------------------ const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 6 } }); -const unexpectedError = { messageId: "unexpected" }; -const missingError = { messageId: "missing" }; ruleTester.run("template-tag-spacing", rule, { valid: [ @@ -55,167 +53,413 @@ ruleTester.run("template-tag-spacing", rule, { { code: "tag `name`", output: "tag`name`", - errors: [unexpectedError] + errors: [{ + messageId: "unexpected", + line: 1, + column: 4, + endLine: 1, + endColumn: 5 + }] }, { code: "tag `name`", output: "tag`name`", options: ["never"], - errors: [unexpectedError] + errors: [{ + messageId: "unexpected", + line: 1, + column: 4, + endLine: 1, + endColumn: 5 + }] }, { code: "tag`name`", output: "tag `name`", options: ["always"], - errors: [missingError] + errors: [{ + messageId: "missing", + line: 1, + column: 1, + endLine: 1, + endColumn: 4 + }] }, { code: "tag /*here's a comment*/`Hello world`", output: "tag/*here's a comment*/`Hello world`", options: ["never"], - errors: [unexpectedError] + errors: [{ + messageId: "unexpected", + line: 1, + column: 4, + endLine: 1, + endColumn: 25 + }] }, { code: "tag/*here's a comment*/ `Hello world`", output: "tag/*here's a comment*/`Hello world`", options: ["never"], - errors: [unexpectedError] + errors: [{ + messageId: "unexpected", + line: 1, + column: 4, + endLine: 1, + endColumn: 25 + }] }, { code: "tag/*here's a comment*/`Hello world`", output: "tag /*here's a comment*/`Hello world`", options: ["always"], - errors: [missingError] + errors: [{ + messageId: "missing", + line: 1, + column: 1, + endLine: 1, + endColumn: 24 + }] }, { code: "tag // here's a comment \n`bar`", output: null, - errors: [unexpectedError] + errors: [{ + messageId: "unexpected", + line: 1, + column: 4, + endLine: 2, + endColumn: 1 + }] }, { code: "tag // here's a comment \n`bar`", output: null, options: ["never"], - errors: [unexpectedError] + errors: [{ + messageId: "unexpected", + line: 1, + column: 4, + endLine: 2, + endColumn: 1 + }] }, { code: "tag `hello ${name}`", output: "tag`hello ${name}`", - errors: [unexpectedError] + errors: [{ + messageId: "unexpected", + line: 1, + column: 4, + endLine: 1, + endColumn: 5 + }] }, { code: "tag `hello ${name}`", output: "tag`hello ${name}`", options: ["never"], - errors: [unexpectedError] + errors: [{ + messageId: "unexpected", + line: 1, + column: 4, + endLine: 1, + endColumn: 5 + }] }, { code: "tag`hello ${name}`", output: "tag `hello ${name}`", options: ["always"], - errors: [missingError] + errors: [{ + messageId: "missing", + line: 1, + column: 1, + endLine: 1, + endColumn: 4 + }] }, { code: "new tag `name`", output: "new tag`name`", - errors: [unexpectedError] + errors: [{ + messageId: "unexpected", + line: 1, + column: 8, + endLine: 1, + endColumn: 9 + }] }, { code: "new tag `name`", output: "new tag`name`", options: ["never"], - errors: [unexpectedError] + errors: [{ + messageId: "unexpected", + line: 1, + column: 8, + endLine: 1, + endColumn: 9 + }] }, { code: "new tag`name`", output: "new tag `name`", options: ["always"], - errors: [missingError] + errors: [{ + messageId: "missing", + line: 1, + column: 5, + endLine: 1, + endColumn: 8 + }] }, { code: "new tag `hello ${name}`", output: "new tag`hello ${name}`", - errors: [unexpectedError] + errors: [{ + messageId: "unexpected", + line: 1, + column: 8, + endLine: 1, + endColumn: 9 + }] }, { code: "new tag `hello ${name}`", output: "new tag`hello ${name}`", options: ["never"], - errors: [unexpectedError] + errors: [{ + messageId: "unexpected", + line: 1, + column: 8, + endLine: 1, + endColumn: 9 + }] }, { code: "new tag`hello ${name}`", output: "new tag `hello ${name}`", options: ["always"], - errors: [missingError] + errors: [{ + messageId: "missing", + line: 1, + column: 5, + endLine: 1, + endColumn: 8 + }] }, { code: "(tag) `name`", output: "(tag)`name`", - errors: [unexpectedError] + errors: [{ + messageId: "unexpected", + line: 1, + column: 6, + endLine: 1, + endColumn: 7 + }] }, { code: "(tag) `name`", output: "(tag)`name`", options: ["never"], - errors: [unexpectedError] + errors: [{ + messageId: "unexpected", + line: 1, + column: 6, + endLine: 1, + endColumn: 7 + }] }, { code: "(tag)`name`", output: "(tag) `name`", options: ["always"], - errors: [missingError] + errors: [{ + messageId: "missing", + line: 1, + column: 1, + endLine: 1, + endColumn: 6 + }] }, { code: "(tag) `hello ${name}`", output: "(tag)`hello ${name}`", - errors: [unexpectedError] + errors: [{ + messageId: "unexpected", + line: 1, + column: 6, + endLine: 1, + endColumn: 7 + }] }, { code: "(tag) `hello ${name}`", output: "(tag)`hello ${name}`", options: ["never"], - errors: [unexpectedError] + errors: [{ + messageId: "unexpected", + line: 1, + column: 6, + endLine: 1, + endColumn: 7 + }] }, { code: "(tag)`hello ${name}`", output: "(tag) `hello ${name}`", options: ["always"], - errors: [missingError] + errors: [{ + messageId: "missing", + line: 1, + column: 1, + endLine: 1, + endColumn: 6 + }] }, { code: "new (tag) `name`", output: "new (tag)`name`", - errors: [unexpectedError] + errors: [{ + messageId: "unexpected", + line: 1, + column: 10, + endLine: 1, + endColumn: 11 + }] }, { code: "new (tag) `name`", output: "new (tag)`name`", options: ["never"], - errors: [unexpectedError] + errors: [{ + messageId: "unexpected", + line: 1, + column: 10, + endLine: 1, + endColumn: 11 + }] }, { code: "new (tag)`name`", output: "new (tag) `name`", options: ["always"], - errors: [missingError] + errors: [{ + messageId: "missing", + line: 1, + column: 5, + endLine: 1, + endColumn: 10 + }] }, { code: "new (tag) `hello ${name}`", output: "new (tag)`hello ${name}`", - errors: [unexpectedError] + errors: [{ + messageId: "unexpected", + line: 1, + column: 10, + endLine: 1, + endColumn: 11 + }] }, { code: "new (tag) `hello ${name}`", output: "new (tag)`hello ${name}`", options: ["never"], - errors: [unexpectedError] + errors: [{ + messageId: "unexpected", + line: 1, + column: 10, + endLine: 1, + endColumn: 11 + }] }, { code: "new (tag)`hello ${name}`", output: "new (tag) `hello ${name}`", options: ["always"], - errors: [missingError] + errors: [{ + messageId: "missing", + line: 1, + column: 5, + endLine: 1, + endColumn: 10 + }] + }, + { + code: "tag `name`", + output: "tag`name`", + options: ["never"], + errors: [{ + messageId: "unexpected", + line: 1, + column: 4, + endLine: 1, + endColumn: 7 + }] + }, + { + code: "tag\n`name`", + output: "tag`name`", + options: ["never"], + errors: [{ + messageId: "unexpected", + line: 1, + column: 4, + endLine: 2, + endColumn: 1 + }] + }, + { + code: "tag \n `name`", + output: "tag`name`", + options: ["never"], + errors: [{ + messageId: "unexpected", + line: 1, + column: 4, + endLine: 2, + endColumn: 3 + }] + }, + { + code: "tag\n\n`name`", + output: "tag`name`", + options: ["never"], + errors: [{ + messageId: "unexpected", + line: 1, + column: 4, + endLine: 3, + endColumn: 1 + }] + }, + { + code: "foo\n .bar`Hello world`", + output: "foo\n .bar `Hello world`", + options: ["always"], + errors: [{ + messageId: "missing", + line: 1, + column: 1, + endLine: 2, + endColumn: 7 + }] + }, + { + code: "foo(\n bar\n)`Hello world`", + output: "foo(\n bar\n) `Hello world`", + options: ["always"], + errors: [{ + messageId: "missing", + line: 1, + column: 1, + endLine: 3, + endColumn: 2 + }] } ] }); diff --git a/eslint/tools/code-sample-minimizer.js b/eslint/tools/code-sample-minimizer.js index 2954bf0..512b692 100644 --- a/eslint/tools/code-sample-minimizer.js +++ b/eslint/tools/code-sample-minimizer.js @@ -76,7 +76,7 @@ function reduceBadExampleSize({ function reproducesBadCase(updatedSourceText) { try { parser.parse(updatedSourceText); - } catch (err) { + } catch { return false; } diff --git a/src/eslint.js b/src/eslint.js index 0fa18d8..836b064 100755 --- a/src/eslint.js +++ b/src/eslint.js @@ -18968,7 +18968,7 @@ module.exports = { /* 383 */ /***/ (function(module) { -module.exports = JSON.parse("{\"_from\":\"estraverse@^4.1.1\",\"_id\":\"estraverse@4.3.0\",\"_inBundle\":false,\"_integrity\":\"sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==\",\"_location\":\"/estraverse\",\"_phantomChildren\":{},\"_requested\":{\"type\":\"range\",\"registry\":true,\"raw\":\"estraverse@^4.1.1\",\"name\":\"estraverse\",\"escapedName\":\"estraverse\",\"rawSpec\":\"^4.1.1\",\"saveSpec\":null,\"fetchSpec\":\"^4.1.1\"},\"_requiredBy\":[\"/babel-eslint/eslint-scope\",\"/eslint-scope\",\"/esrecurse\",\"/webpack/eslint-scope\"],\"_resolved\":\"https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz\",\"_shasum\":\"398ad3f3c5a24948be7725e83d11a7de28cdbd1d\",\"_spec\":\"estraverse@^4.1.1\",\"_where\":\"/root/sources/pve/pve-eslint/eslint-v7.1.0/node_modules/eslint-scope\",\"bugs\":{\"url\":\"https://github.com/estools/estraverse/issues\"},\"bundleDependencies\":false,\"deprecated\":false,\"description\":\"ECMAScript JS AST traversal functions\",\"devDependencies\":{\"babel-preset-env\":\"^1.6.1\",\"babel-register\":\"^6.3.13\",\"chai\":\"^2.1.1\",\"espree\":\"^1.11.0\",\"gulp\":\"^3.8.10\",\"gulp-bump\":\"^0.2.2\",\"gulp-filter\":\"^2.0.0\",\"gulp-git\":\"^1.0.1\",\"gulp-tag-version\":\"^1.3.0\",\"jshint\":\"^2.5.6\",\"mocha\":\"^2.1.0\"},\"engines\":{\"node\":\">=4.0\"},\"homepage\":\"https://github.com/estools/estraverse\",\"license\":\"BSD-2-Clause\",\"main\":\"estraverse.js\",\"maintainers\":[{\"name\":\"Yusuke Suzuki\",\"email\":\"utatane.tea@gmail.com\",\"url\":\"http://github.com/Constellation\"}],\"name\":\"estraverse\",\"repository\":{\"type\":\"git\",\"url\":\"git+ssh://git@github.com/estools/estraverse.git\"},\"scripts\":{\"lint\":\"jshint estraverse.js\",\"test\":\"npm run-script lint && npm run-script unit-test\",\"unit-test\":\"mocha --compilers js:babel-register\"},\"version\":\"4.3.0\"}"); +module.exports = JSON.parse("{\"_from\":\"estraverse@^4.1.1\",\"_id\":\"estraverse@4.3.0\",\"_inBundle\":false,\"_integrity\":\"sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==\",\"_location\":\"/estraverse\",\"_phantomChildren\":{},\"_requested\":{\"type\":\"range\",\"registry\":true,\"raw\":\"estraverse@^4.1.1\",\"name\":\"estraverse\",\"escapedName\":\"estraverse\",\"rawSpec\":\"^4.1.1\",\"saveSpec\":null,\"fetchSpec\":\"^4.1.1\"},\"_requiredBy\":[\"/babel-eslint/eslint-scope\",\"/eslint-scope\",\"/esrecurse\",\"/webpack/eslint-scope\"],\"_resolved\":\"https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz\",\"_shasum\":\"398ad3f3c5a24948be7725e83d11a7de28cdbd1d\",\"_spec\":\"estraverse@^4.1.1\",\"_where\":\"/root/sources/pve/pve-eslint/eslint-v7.2.0/node_modules/eslint-scope\",\"bugs\":{\"url\":\"https://github.com/estools/estraverse/issues\"},\"bundleDependencies\":false,\"deprecated\":false,\"description\":\"ECMAScript JS AST traversal functions\",\"devDependencies\":{\"babel-preset-env\":\"^1.6.1\",\"babel-register\":\"^6.3.13\",\"chai\":\"^2.1.1\",\"espree\":\"^1.11.0\",\"gulp\":\"^3.8.10\",\"gulp-bump\":\"^0.2.2\",\"gulp-filter\":\"^2.0.0\",\"gulp-git\":\"^1.0.1\",\"gulp-tag-version\":\"^1.3.0\",\"jshint\":\"^2.5.6\",\"mocha\":\"^2.1.0\"},\"engines\":{\"node\":\">=4.0\"},\"homepage\":\"https://github.com/estools/estraverse\",\"license\":\"BSD-2-Clause\",\"main\":\"estraverse.js\",\"maintainers\":[{\"name\":\"Yusuke Suzuki\",\"email\":\"utatane.tea@gmail.com\",\"url\":\"http://github.com/Constellation\"}],\"name\":\"estraverse\",\"repository\":{\"type\":\"git\",\"url\":\"git+ssh://git@github.com/estools/estraverse.git\"},\"scripts\":{\"lint\":\"jshint estraverse.js\",\"test\":\"npm run-script lint && npm run-script unit-test\",\"unit-test\":\"mocha --compilers js:babel-register\"},\"version\":\"4.3.0\"}"); /***/ }), /* 384 */ @@ -19871,17 +19871,27 @@ class Referencer extends esrecurse.Visitor { } this.visitChildren(node); - } + } // TODO: ExportDeclaration doesn't exist. for bc? + ExportDeclaration(node) { this.visitExportDeclaration(node); } + ExportAllDeclaration(node) { + this.visitExportDeclaration(node); + } + + ExportDefaultDeclaration(node) { + this.visitExportDeclaration(node); + } + ExportNamedDeclaration(node) { this.visitExportDeclaration(node); } ExportSpecifier(node) { + // TODO: `node.id` doesn't exist. for bc? const local = node.id || node.local; this.visit(local); } @@ -20027,7 +20037,7 @@ module.exports = Referencer; /* 389 */ /***/ (function(module) { -module.exports = JSON.parse("{\"_from\":\"esrecurse@^4.1.0\",\"_id\":\"esrecurse@4.2.1\",\"_inBundle\":false,\"_integrity\":\"sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==\",\"_location\":\"/esrecurse\",\"_phantomChildren\":{},\"_requested\":{\"type\":\"range\",\"registry\":true,\"raw\":\"esrecurse@^4.1.0\",\"name\":\"esrecurse\",\"escapedName\":\"esrecurse\",\"rawSpec\":\"^4.1.0\",\"saveSpec\":null,\"fetchSpec\":\"^4.1.0\"},\"_requiredBy\":[\"/babel-eslint/eslint-scope\",\"/eslint-scope\",\"/webpack/eslint-scope\"],\"_resolved\":\"https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz\",\"_shasum\":\"007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf\",\"_spec\":\"esrecurse@^4.1.0\",\"_where\":\"/root/sources/pve/pve-eslint/eslint-v7.1.0/node_modules/eslint-scope\",\"babel\":{\"presets\":[\"es2015\"]},\"bugs\":{\"url\":\"https://github.com/estools/esrecurse/issues\"},\"bundleDependencies\":false,\"dependencies\":{\"estraverse\":\"^4.1.0\"},\"deprecated\":false,\"description\":\"ECMAScript AST recursive visitor\",\"devDependencies\":{\"babel-cli\":\"^6.24.1\",\"babel-eslint\":\"^7.2.3\",\"babel-preset-es2015\":\"^6.24.1\",\"babel-register\":\"^6.24.1\",\"chai\":\"^4.0.2\",\"esprima\":\"^4.0.0\",\"gulp\":\"^3.9.0\",\"gulp-bump\":\"^2.7.0\",\"gulp-eslint\":\"^4.0.0\",\"gulp-filter\":\"^5.0.0\",\"gulp-git\":\"^2.4.1\",\"gulp-mocha\":\"^4.3.1\",\"gulp-tag-version\":\"^1.2.1\",\"jsdoc\":\"^3.3.0-alpha10\",\"minimist\":\"^1.1.0\"},\"engines\":{\"node\":\">=4.0\"},\"homepage\":\"https://github.com/estools/esrecurse\",\"license\":\"BSD-2-Clause\",\"main\":\"esrecurse.js\",\"maintainers\":[{\"name\":\"Yusuke Suzuki\",\"email\":\"utatane.tea@gmail.com\",\"url\":\"https://github.com/Constellation\"}],\"name\":\"esrecurse\",\"repository\":{\"type\":\"git\",\"url\":\"git+https://github.com/estools/esrecurse.git\"},\"scripts\":{\"lint\":\"gulp lint\",\"test\":\"gulp travis\",\"unit-test\":\"gulp test\"},\"version\":\"4.2.1\"}"); +module.exports = JSON.parse("{\"_from\":\"esrecurse@^4.1.0\",\"_id\":\"esrecurse@4.2.1\",\"_inBundle\":false,\"_integrity\":\"sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==\",\"_location\":\"/esrecurse\",\"_phantomChildren\":{},\"_requested\":{\"type\":\"range\",\"registry\":true,\"raw\":\"esrecurse@^4.1.0\",\"name\":\"esrecurse\",\"escapedName\":\"esrecurse\",\"rawSpec\":\"^4.1.0\",\"saveSpec\":null,\"fetchSpec\":\"^4.1.0\"},\"_requiredBy\":[\"/babel-eslint/eslint-scope\",\"/eslint-scope\",\"/webpack/eslint-scope\"],\"_resolved\":\"https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz\",\"_shasum\":\"007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf\",\"_spec\":\"esrecurse@^4.1.0\",\"_where\":\"/root/sources/pve/pve-eslint/eslint-v7.2.0/node_modules/eslint-scope\",\"babel\":{\"presets\":[\"es2015\"]},\"bugs\":{\"url\":\"https://github.com/estools/esrecurse/issues\"},\"bundleDependencies\":false,\"dependencies\":{\"estraverse\":\"^4.1.0\"},\"deprecated\":false,\"description\":\"ECMAScript AST recursive visitor\",\"devDependencies\":{\"babel-cli\":\"^6.24.1\",\"babel-eslint\":\"^7.2.3\",\"babel-preset-es2015\":\"^6.24.1\",\"babel-register\":\"^6.24.1\",\"chai\":\"^4.0.2\",\"esprima\":\"^4.0.0\",\"gulp\":\"^3.9.0\",\"gulp-bump\":\"^2.7.0\",\"gulp-eslint\":\"^4.0.0\",\"gulp-filter\":\"^5.0.0\",\"gulp-git\":\"^2.4.1\",\"gulp-mocha\":\"^4.3.1\",\"gulp-tag-version\":\"^1.2.1\",\"jsdoc\":\"^3.3.0-alpha10\",\"minimist\":\"^1.1.0\"},\"engines\":{\"node\":\">=4.0\"},\"homepage\":\"https://github.com/estools/esrecurse\",\"license\":\"BSD-2-Clause\",\"main\":\"esrecurse.js\",\"maintainers\":[{\"name\":\"Yusuke Suzuki\",\"email\":\"utatane.tea@gmail.com\",\"url\":\"https://github.com/Constellation\"}],\"name\":\"esrecurse\",\"repository\":{\"type\":\"git\",\"url\":\"git+https://github.com/estools/esrecurse.git\"},\"scripts\":{\"lint\":\"gulp lint\",\"test\":\"gulp travis\",\"unit-test\":\"gulp test\"},\"version\":\"4.2.1\"}"); /***/ }), /* 390 */ @@ -20178,7 +20188,7 @@ module.exports = PatternVisitor; /* 391 */ /***/ (function(module) { -module.exports = JSON.parse("{\"_from\":\"eslint-scope@^5.0.0\",\"_id\":\"eslint-scope@5.0.0\",\"_inBundle\":false,\"_integrity\":\"sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==\",\"_location\":\"/eslint-scope\",\"_phantomChildren\":{},\"_requested\":{\"type\":\"range\",\"registry\":true,\"raw\":\"eslint-scope@^5.0.0\",\"name\":\"eslint-scope\",\"escapedName\":\"eslint-scope\",\"rawSpec\":\"^5.0.0\",\"saveSpec\":null,\"fetchSpec\":\"^5.0.0\"},\"_requiredBy\":[\"/\",\"/eslint\"],\"_resolved\":\"https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz\",\"_shasum\":\"e87c8887c73e8d1ec84f1ca591645c358bfc8fb9\",\"_spec\":\"eslint-scope@^5.0.0\",\"_where\":\"/root/sources/pve/pve-eslint/eslint-v7.1.0\",\"bugs\":{\"url\":\"https://github.com/eslint/eslint-scope/issues\"},\"bundleDependencies\":false,\"dependencies\":{\"esrecurse\":\"^4.1.0\",\"estraverse\":\"^4.1.1\"},\"deprecated\":false,\"description\":\"ECMAScript scope analyzer for ESLint\",\"devDependencies\":{\"@typescript-eslint/parser\":\"^1.11.0\",\"chai\":\"^4.2.0\",\"eslint\":\"^6.0.1\",\"eslint-config-eslint\":\"^5.0.1\",\"eslint-plugin-node\":\"^9.1.0\",\"eslint-release\":\"^1.0.0\",\"espree\":\"^6.0.0\",\"istanbul\":\"^0.4.5\",\"mocha\":\"^6.1.4\",\"npm-license\":\"^0.3.3\",\"shelljs\":\"^0.8.3\",\"typescript\":\"^3.5.2\"},\"engines\":{\"node\":\">=8.0.0\"},\"files\":[\"LICENSE\",\"README.md\",\"lib\"],\"homepage\":\"http://github.com/eslint/eslint-scope\",\"license\":\"BSD-2-Clause\",\"main\":\"lib/index.js\",\"name\":\"eslint-scope\",\"repository\":{\"type\":\"git\",\"url\":\"git+https://github.com/eslint/eslint-scope.git\"},\"scripts\":{\"generate-alpharelease\":\"eslint-generate-prerelease alpha\",\"generate-betarelease\":\"eslint-generate-prerelease beta\",\"generate-rcrelease\":\"eslint-generate-prerelease rc\",\"generate-release\":\"eslint-generate-release\",\"lint\":\"node Makefile.js lint\",\"publish-release\":\"eslint-publish-release\",\"test\":\"node Makefile.js test\"},\"version\":\"5.0.0\"}"); +module.exports = JSON.parse("{\"_from\":\"eslint-scope@^5.1.0\",\"_id\":\"eslint-scope@5.1.0\",\"_inBundle\":false,\"_integrity\":\"sha512-iiGRvtxWqgtx5m8EyQUJihBloE4EnYeGE/bz1wSPwJE6tZuJUtHlhqDM4Xj2ukE8Dyy1+HCZ4hE0fzIVMzb58w==\",\"_location\":\"/eslint-scope\",\"_phantomChildren\":{},\"_requested\":{\"type\":\"range\",\"registry\":true,\"raw\":\"eslint-scope@^5.1.0\",\"name\":\"eslint-scope\",\"escapedName\":\"eslint-scope\",\"rawSpec\":\"^5.1.0\",\"saveSpec\":null,\"fetchSpec\":\"^5.1.0\"},\"_requiredBy\":[\"/\",\"/eslint\"],\"_resolved\":\"https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.0.tgz\",\"_shasum\":\"d0f971dfe59c69e0cada684b23d49dbf82600ce5\",\"_spec\":\"eslint-scope@^5.1.0\",\"_where\":\"/root/sources/pve/pve-eslint/eslint-v7.2.0\",\"bugs\":{\"url\":\"https://github.com/eslint/eslint-scope/issues\"},\"bundleDependencies\":false,\"dependencies\":{\"esrecurse\":\"^4.1.0\",\"estraverse\":\"^4.1.1\"},\"deprecated\":false,\"description\":\"ECMAScript scope analyzer for ESLint\",\"devDependencies\":{\"@typescript-eslint/parser\":\"^1.11.0\",\"chai\":\"^4.2.0\",\"eslint\":\"^6.0.1\",\"eslint-config-eslint\":\"^5.0.1\",\"eslint-plugin-node\":\"^9.1.0\",\"eslint-release\":\"^1.0.0\",\"eslint-visitor-keys\":\"^1.2.0\",\"espree\":\"^7.1.0\",\"istanbul\":\"^0.4.5\",\"mocha\":\"^6.1.4\",\"npm-license\":\"^0.3.3\",\"shelljs\":\"^0.8.3\",\"typescript\":\"^3.5.2\"},\"engines\":{\"node\":\">=8.0.0\"},\"files\":[\"LICENSE\",\"README.md\",\"lib\"],\"homepage\":\"http://github.com/eslint/eslint-scope\",\"license\":\"BSD-2-Clause\",\"main\":\"lib/index.js\",\"name\":\"eslint-scope\",\"repository\":{\"type\":\"git\",\"url\":\"git+https://github.com/eslint/eslint-scope.git\"},\"scripts\":{\"generate-alpharelease\":\"eslint-generate-prerelease alpha\",\"generate-betarelease\":\"eslint-generate-prerelease beta\",\"generate-rcrelease\":\"eslint-generate-prerelease rc\",\"generate-release\":\"eslint-generate-release\",\"lint\":\"node Makefile.js lint\",\"publish-release\":\"eslint-publish-release\",\"test\":\"node Makefile.js test\"},\"version\":\"5.1.0\"}"); /***/ }), /* 392 */ @@ -20266,7 +20276,7 @@ module.exports = Object.freeze({ /* 393 */ /***/ (function(module) { -module.exports = JSON.parse("{\"AssignmentExpression\":[\"left\",\"right\"],\"AssignmentPattern\":[\"left\",\"right\"],\"ArrayExpression\":[\"elements\"],\"ArrayPattern\":[\"elements\"],\"ArrowFunctionExpression\":[\"params\",\"body\"],\"AwaitExpression\":[\"argument\"],\"BlockStatement\":[\"body\"],\"BinaryExpression\":[\"left\",\"right\"],\"BreakStatement\":[\"label\"],\"CallExpression\":[\"callee\",\"arguments\"],\"CatchClause\":[\"param\",\"body\"],\"ClassBody\":[\"body\"],\"ClassDeclaration\":[\"id\",\"superClass\",\"body\"],\"ClassExpression\":[\"id\",\"superClass\",\"body\"],\"ConditionalExpression\":[\"test\",\"consequent\",\"alternate\"],\"ContinueStatement\":[\"label\"],\"DebuggerStatement\":[],\"DoWhileStatement\":[\"body\",\"test\"],\"EmptyStatement\":[],\"ExportAllDeclaration\":[\"source\"],\"ExportDefaultDeclaration\":[\"declaration\"],\"ExportNamedDeclaration\":[\"declaration\",\"specifiers\",\"source\"],\"ExportSpecifier\":[\"exported\",\"local\"],\"ExpressionStatement\":[\"expression\"],\"ExperimentalRestProperty\":[\"argument\"],\"ExperimentalSpreadProperty\":[\"argument\"],\"ForStatement\":[\"init\",\"test\",\"update\",\"body\"],\"ForInStatement\":[\"left\",\"right\",\"body\"],\"ForOfStatement\":[\"left\",\"right\",\"body\"],\"FunctionDeclaration\":[\"id\",\"params\",\"body\"],\"FunctionExpression\":[\"id\",\"params\",\"body\"],\"Identifier\":[],\"IfStatement\":[\"test\",\"consequent\",\"alternate\"],\"ImportDeclaration\":[\"specifiers\",\"source\"],\"ImportDefaultSpecifier\":[\"local\"],\"ImportExpression\":[\"source\"],\"ImportNamespaceSpecifier\":[\"local\"],\"ImportSpecifier\":[\"imported\",\"local\"],\"JSXAttribute\":[\"name\",\"value\"],\"JSXClosingElement\":[\"name\"],\"JSXElement\":[\"openingElement\",\"children\",\"closingElement\"],\"JSXEmptyExpression\":[],\"JSXExpressionContainer\":[\"expression\"],\"JSXIdentifier\":[],\"JSXMemberExpression\":[\"object\",\"property\"],\"JSXNamespacedName\":[\"namespace\",\"name\"],\"JSXOpeningElement\":[\"name\",\"attributes\"],\"JSXSpreadAttribute\":[\"argument\"],\"JSXText\":[],\"JSXFragment\":[\"openingFragment\",\"children\",\"closingFragment\"],\"Literal\":[],\"LabeledStatement\":[\"label\",\"body\"],\"LogicalExpression\":[\"left\",\"right\"],\"MemberExpression\":[\"object\",\"property\"],\"MetaProperty\":[\"meta\",\"property\"],\"MethodDefinition\":[\"key\",\"value\"],\"NewExpression\":[\"callee\",\"arguments\"],\"ObjectExpression\":[\"properties\"],\"ObjectPattern\":[\"properties\"],\"Program\":[\"body\"],\"Property\":[\"key\",\"value\"],\"RestElement\":[\"argument\"],\"ReturnStatement\":[\"argument\"],\"SequenceExpression\":[\"expressions\"],\"SpreadElement\":[\"argument\"],\"Super\":[],\"SwitchStatement\":[\"discriminant\",\"cases\"],\"SwitchCase\":[\"test\",\"consequent\"],\"TaggedTemplateExpression\":[\"tag\",\"quasi\"],\"TemplateElement\":[],\"TemplateLiteral\":[\"quasis\",\"expressions\"],\"ThisExpression\":[],\"ThrowStatement\":[\"argument\"],\"TryStatement\":[\"block\",\"handler\",\"finalizer\"],\"UnaryExpression\":[\"argument\"],\"UpdateExpression\":[\"argument\"],\"VariableDeclaration\":[\"declarations\"],\"VariableDeclarator\":[\"id\",\"init\"],\"WhileStatement\":[\"test\",\"body\"],\"WithStatement\":[\"object\",\"body\"],\"YieldExpression\":[\"argument\"]}"); +module.exports = JSON.parse("{\"AssignmentExpression\":[\"left\",\"right\"],\"AssignmentPattern\":[\"left\",\"right\"],\"ArrayExpression\":[\"elements\"],\"ArrayPattern\":[\"elements\"],\"ArrowFunctionExpression\":[\"params\",\"body\"],\"AwaitExpression\":[\"argument\"],\"BlockStatement\":[\"body\"],\"BinaryExpression\":[\"left\",\"right\"],\"BreakStatement\":[\"label\"],\"CallExpression\":[\"callee\",\"arguments\"],\"CatchClause\":[\"param\",\"body\"],\"ClassBody\":[\"body\"],\"ClassDeclaration\":[\"id\",\"superClass\",\"body\"],\"ClassExpression\":[\"id\",\"superClass\",\"body\"],\"ConditionalExpression\":[\"test\",\"consequent\",\"alternate\"],\"ContinueStatement\":[\"label\"],\"DebuggerStatement\":[],\"DoWhileStatement\":[\"body\",\"test\"],\"EmptyStatement\":[],\"ExportAllDeclaration\":[\"exported\",\"source\"],\"ExportDefaultDeclaration\":[\"declaration\"],\"ExportNamedDeclaration\":[\"declaration\",\"specifiers\",\"source\"],\"ExportSpecifier\":[\"exported\",\"local\"],\"ExpressionStatement\":[\"expression\"],\"ExperimentalRestProperty\":[\"argument\"],\"ExperimentalSpreadProperty\":[\"argument\"],\"ForStatement\":[\"init\",\"test\",\"update\",\"body\"],\"ForInStatement\":[\"left\",\"right\",\"body\"],\"ForOfStatement\":[\"left\",\"right\",\"body\"],\"FunctionDeclaration\":[\"id\",\"params\",\"body\"],\"FunctionExpression\":[\"id\",\"params\",\"body\"],\"Identifier\":[],\"IfStatement\":[\"test\",\"consequent\",\"alternate\"],\"ImportDeclaration\":[\"specifiers\",\"source\"],\"ImportDefaultSpecifier\":[\"local\"],\"ImportExpression\":[\"source\"],\"ImportNamespaceSpecifier\":[\"local\"],\"ImportSpecifier\":[\"imported\",\"local\"],\"JSXAttribute\":[\"name\",\"value\"],\"JSXClosingElement\":[\"name\"],\"JSXElement\":[\"openingElement\",\"children\",\"closingElement\"],\"JSXEmptyExpression\":[],\"JSXExpressionContainer\":[\"expression\"],\"JSXIdentifier\":[],\"JSXMemberExpression\":[\"object\",\"property\"],\"JSXNamespacedName\":[\"namespace\",\"name\"],\"JSXOpeningElement\":[\"name\",\"attributes\"],\"JSXSpreadAttribute\":[\"argument\"],\"JSXText\":[],\"JSXFragment\":[\"openingFragment\",\"children\",\"closingFragment\"],\"Literal\":[],\"LabeledStatement\":[\"label\",\"body\"],\"LogicalExpression\":[\"left\",\"right\"],\"MemberExpression\":[\"object\",\"property\"],\"MetaProperty\":[\"meta\",\"property\"],\"MethodDefinition\":[\"key\",\"value\"],\"NewExpression\":[\"callee\",\"arguments\"],\"ObjectExpression\":[\"properties\"],\"ObjectPattern\":[\"properties\"],\"Program\":[\"body\"],\"Property\":[\"key\",\"value\"],\"RestElement\":[\"argument\"],\"ReturnStatement\":[\"argument\"],\"SequenceExpression\":[\"expressions\"],\"SpreadElement\":[\"argument\"],\"Super\":[],\"SwitchStatement\":[\"discriminant\",\"cases\"],\"SwitchCase\":[\"test\",\"consequent\"],\"TaggedTemplateExpression\":[\"tag\",\"quasi\"],\"TemplateElement\":[],\"TemplateLiteral\":[\"quasis\",\"expressions\"],\"ThisExpression\":[],\"ThrowStatement\":[\"argument\"],\"TryStatement\":[\"block\",\"handler\",\"finalizer\"],\"UnaryExpression\":[\"argument\"],\"UpdateExpression\":[\"argument\"],\"VariableDeclaration\":[\"declarations\"],\"VariableDeclarator\":[\"id\",\"init\"],\"WhileStatement\":[\"test\",\"body\"],\"WithStatement\":[\"object\",\"body\"],\"YieldExpression\":[\"argument\"]}"); /***/ }), /* 394 */ @@ -28593,7 +28603,7 @@ module.exports = { /* 402 */ /***/ (function(module) { -module.exports = JSON.parse("{\"_from\":\"espree@^7.0.0\",\"_id\":\"espree@7.0.0\",\"_inBundle\":false,\"_integrity\":\"sha512-/r2XEx5Mw4pgKdyb7GNLQNsu++asx/dltf/CI8RFi9oGHxmQFgvLbc5Op4U6i8Oaj+kdslhJtVlEZeAqH5qOTw==\",\"_location\":\"/espree\",\"_phantomChildren\":{},\"_requested\":{\"type\":\"range\",\"registry\":true,\"raw\":\"espree@^7.0.0\",\"name\":\"espree\",\"escapedName\":\"espree\",\"rawSpec\":\"^7.0.0\",\"saveSpec\":null,\"fetchSpec\":\"^7.0.0\"},\"_requiredBy\":[\"/\",\"/eslint\"],\"_resolved\":\"https://registry.npmjs.org/espree/-/espree-7.0.0.tgz\",\"_shasum\":\"8a7a60f218e69f120a842dc24c5a88aa7748a74e\",\"_spec\":\"espree@^7.0.0\",\"_where\":\"/root/sources/pve/pve-eslint/eslint-v7.1.0\",\"author\":{\"name\":\"Nicholas C. Zakas\",\"email\":\"nicholas+npm@nczconsulting.com\"},\"bugs\":{\"url\":\"http://github.com/eslint/espree.git\"},\"bundleDependencies\":false,\"dependencies\":{\"acorn\":\"^7.1.1\",\"acorn-jsx\":\"^5.2.0\",\"eslint-visitor-keys\":\"^1.1.0\"},\"deprecated\":false,\"description\":\"An Esprima-compatible JavaScript parser built on Acorn\",\"devDependencies\":{\"browserify\":\"^16.5.0\",\"chai\":\"^4.2.0\",\"eslint\":\"^6.0.1\",\"eslint-config-eslint\":\"^5.0.1\",\"eslint-plugin-node\":\"^9.1.0\",\"eslint-release\":\"^1.0.0\",\"esprima\":\"latest\",\"esprima-fb\":\"^8001.2001.0-dev-harmony-fb\",\"json-diff\":\"^0.5.4\",\"leche\":\"^2.3.0\",\"mocha\":\"^6.2.0\",\"nyc\":\"^14.1.1\",\"regenerate\":\"^1.4.0\",\"shelljs\":\"^0.3.0\",\"shelljs-nodecli\":\"^0.1.1\",\"unicode-6.3.0\":\"^0.7.5\"},\"engines\":{\"node\":\"^10.12.0 || >=12.0.0\"},\"files\":[\"lib\",\"espree.js\"],\"homepage\":\"https://github.com/eslint/espree\",\"keywords\":[\"ast\",\"ecmascript\",\"javascript\",\"parser\",\"syntax\",\"acorn\"],\"license\":\"BSD-2-Clause\",\"main\":\"espree.js\",\"name\":\"espree\",\"repository\":{\"type\":\"git\",\"url\":\"git+https://github.com/eslint/espree.git\"},\"scripts\":{\"browserify\":\"node Makefile.js browserify\",\"generate-alpharelease\":\"eslint-generate-prerelease alpha\",\"generate-betarelease\":\"eslint-generate-prerelease beta\",\"generate-rcrelease\":\"eslint-generate-prerelease rc\",\"generate-regex\":\"node tools/generate-identifier-regex.js\",\"generate-release\":\"eslint-generate-release\",\"lint\":\"node Makefile.js lint\",\"publish-release\":\"eslint-publish-release\",\"sync-docs\":\"node Makefile.js docs\",\"test\":\"npm run-script lint && node Makefile.js test\"},\"version\":\"7.0.0\"}"); +module.exports = JSON.parse("{\"_from\":\"espree@^7.1.0\",\"_id\":\"espree@7.1.0\",\"_inBundle\":false,\"_integrity\":\"sha512-dcorZSyfmm4WTuTnE5Y7MEN1DyoPYy1ZR783QW1FJoenn7RailyWFsq/UL6ZAAA7uXurN9FIpYyUs3OfiIW+Qw==\",\"_location\":\"/espree\",\"_phantomChildren\":{},\"_requested\":{\"type\":\"range\",\"registry\":true,\"raw\":\"espree@^7.1.0\",\"name\":\"espree\",\"escapedName\":\"espree\",\"rawSpec\":\"^7.1.0\",\"saveSpec\":null,\"fetchSpec\":\"^7.1.0\"},\"_requiredBy\":[\"/\",\"/eslint\"],\"_resolved\":\"https://registry.npmjs.org/espree/-/espree-7.1.0.tgz\",\"_shasum\":\"a9c7f18a752056735bf1ba14cb1b70adc3a5ce1c\",\"_spec\":\"espree@^7.1.0\",\"_where\":\"/root/sources/pve/pve-eslint/eslint-v7.2.0\",\"author\":{\"name\":\"Nicholas C. Zakas\",\"email\":\"nicholas+npm@nczconsulting.com\"},\"bugs\":{\"url\":\"http://github.com/eslint/espree.git\"},\"bundleDependencies\":false,\"dependencies\":{\"acorn\":\"^7.2.0\",\"acorn-jsx\":\"^5.2.0\",\"eslint-visitor-keys\":\"^1.2.0\"},\"deprecated\":false,\"description\":\"An Esprima-compatible JavaScript parser built on Acorn\",\"devDependencies\":{\"browserify\":\"^16.5.0\",\"chai\":\"^4.2.0\",\"eslint\":\"^6.0.1\",\"eslint-config-eslint\":\"^5.0.1\",\"eslint-plugin-node\":\"^9.1.0\",\"eslint-release\":\"^1.0.0\",\"esprima\":\"latest\",\"esprima-fb\":\"^8001.2001.0-dev-harmony-fb\",\"json-diff\":\"^0.5.4\",\"leche\":\"^2.3.0\",\"mocha\":\"^6.2.0\",\"nyc\":\"^14.1.1\",\"regenerate\":\"^1.4.0\",\"shelljs\":\"^0.3.0\",\"shelljs-nodecli\":\"^0.1.1\",\"unicode-6.3.0\":\"^0.7.5\"},\"engines\":{\"node\":\"^10.12.0 || >=12.0.0\"},\"files\":[\"lib\",\"espree.js\"],\"homepage\":\"https://github.com/eslint/espree\",\"keywords\":[\"ast\",\"ecmascript\",\"javascript\",\"parser\",\"syntax\",\"acorn\"],\"license\":\"BSD-2-Clause\",\"main\":\"espree.js\",\"name\":\"espree\",\"repository\":{\"type\":\"git\",\"url\":\"git+https://github.com/eslint/espree.git\"},\"scripts\":{\"browserify\":\"node Makefile.js browserify\",\"fixlint\":\"node Makefile.js lint --fix\",\"generate-alpharelease\":\"eslint-generate-prerelease alpha\",\"generate-betarelease\":\"eslint-generate-prerelease beta\",\"generate-rcrelease\":\"eslint-generate-prerelease rc\",\"generate-regex\":\"node tools/generate-identifier-regex.js\",\"generate-release\":\"eslint-generate-release\",\"lint\":\"node Makefile.js lint\",\"publish-release\":\"eslint-publish-release\",\"sync-docs\":\"node Makefile.js docs\",\"test\":\"npm run-script lint && node Makefile.js test\"},\"version\":\"7.1.0\"}"); /***/ }), /* 403 */ @@ -45929,7 +45939,7 @@ module.exports = JSON.parse("{\"builtin\":{\"Array\":false,\"ArrayBuffer\":false /* 408 */ /***/ (function(module) { -module.exports = JSON.parse("{\"name\":\"eslint\",\"version\":\"7.1.0\",\"author\":\"Nicholas C. Zakas \",\"description\":\"An AST-based pattern checker for JavaScript.\",\"bin\":{\"eslint\":\"./bin/eslint.js\"},\"main\":\"./lib/api.js\",\"scripts\":{\"test\":\"node Makefile.js test\",\"test:cli\":\"mocha\",\"lint\":\"node Makefile.js lint\",\"fix\":\"node Makefile.js lint -- fix\",\"fuzz\":\"node Makefile.js fuzz\",\"generate-release\":\"node Makefile.js generateRelease\",\"generate-alpharelease\":\"node Makefile.js generatePrerelease -- alpha\",\"generate-betarelease\":\"node Makefile.js generatePrerelease -- beta\",\"generate-rcrelease\":\"node Makefile.js generatePrerelease -- rc\",\"publish-release\":\"node Makefile.js publishRelease\",\"docs\":\"node Makefile.js docs\",\"gensite\":\"node Makefile.js gensite\",\"webpack\":\"node Makefile.js webpack\",\"perf\":\"node Makefile.js perf\"},\"gitHooks\":{\"pre-commit\":\"lint-staged\"},\"lint-staged\":{\"*.js\":[\"eslint --fix\",\"git add\"],\"*.md\":\"markdownlint\"},\"files\":[\"LICENSE\",\"README.md\",\"bin\",\"conf\",\"lib\",\"messages\"],\"repository\":\"eslint/eslint\",\"funding\":\"https://opencollective.com/eslint\",\"homepage\":\"https://eslint.org\",\"bugs\":\"https://github.com/eslint/eslint/issues/\",\"dependencies\":{\"@babel/code-frame\":\"^7.0.0\",\"ajv\":\"^6.10.0\",\"chalk\":\"^4.0.0\",\"cross-spawn\":\"^7.0.2\",\"debug\":\"^4.0.1\",\"doctrine\":\"^3.0.0\",\"eslint-scope\":\"^5.0.0\",\"eslint-utils\":\"^2.0.0\",\"eslint-visitor-keys\":\"^1.1.0\",\"espree\":\"^7.0.0\",\"esquery\":\"^1.2.0\",\"esutils\":\"^2.0.2\",\"file-entry-cache\":\"^5.0.1\",\"functional-red-black-tree\":\"^1.0.1\",\"glob-parent\":\"^5.0.0\",\"globals\":\"^12.1.0\",\"ignore\":\"^4.0.6\",\"import-fresh\":\"^3.0.0\",\"imurmurhash\":\"^0.1.4\",\"inquirer\":\"^7.0.0\",\"is-glob\":\"^4.0.0\",\"js-yaml\":\"^3.13.1\",\"json-stable-stringify-without-jsonify\":\"^1.0.1\",\"levn\":\"^0.4.1\",\"lodash\":\"^4.17.14\",\"minimatch\":\"^3.0.4\",\"natural-compare\":\"^1.4.0\",\"optionator\":\"^0.9.1\",\"progress\":\"^2.0.0\",\"regexpp\":\"^3.1.0\",\"semver\":\"^7.2.1\",\"strip-ansi\":\"^6.0.0\",\"strip-json-comments\":\"^3.1.0\",\"table\":\"^5.2.3\",\"text-table\":\"^0.2.0\",\"v8-compile-cache\":\"^2.0.3\"},\"devDependencies\":{\"@babel/core\":\"^7.4.3\",\"@babel/preset-env\":\"^7.4.3\",\"acorn\":\"^7.1.1\",\"babel-loader\":\"^8.0.5\",\"chai\":\"^4.0.1\",\"cheerio\":\"^0.22.0\",\"common-tags\":\"^1.8.0\",\"core-js\":\"^3.1.3\",\"dateformat\":\"^3.0.3\",\"ejs\":\"^3.0.2\",\"escape-string-regexp\":\"^3.0.0\",\"eslint\":\"file:.\",\"eslint-config-eslint\":\"file:packages/eslint-config-eslint\",\"eslint-plugin-eslint-plugin\":\"^2.2.1\",\"eslint-plugin-internal-rules\":\"file:tools/internal-rules\",\"eslint-plugin-jsdoc\":\"^22.1.0\",\"eslint-plugin-node\":\"^11.1.0\",\"eslint-release\":\"^2.0.0\",\"eslump\":\"^2.0.0\",\"esprima\":\"^4.0.1\",\"glob\":\"^7.1.6\",\"jsdoc\":\"^3.5.5\",\"karma\":\"^4.0.1\",\"karma-chrome-launcher\":\"^3.1.0\",\"karma-mocha\":\"^1.3.0\",\"karma-mocha-reporter\":\"^2.2.3\",\"karma-webpack\":\"^4.0.0-rc.6\",\"leche\":\"^2.2.3\",\"lint-staged\":\"^10.1.2\",\"load-perf\":\"^0.2.0\",\"markdownlint\":\"^0.19.0\",\"markdownlint-cli\":\"^0.22.0\",\"memfs\":\"^3.0.1\",\"mocha\":\"^7.1.1\",\"mocha-junit-reporter\":\"^1.23.0\",\"npm-license\":\"^0.3.3\",\"nyc\":\"^15.0.1\",\"proxyquire\":\"^2.0.1\",\"puppeteer\":\"^2.1.1\",\"recast\":\"^0.19.0\",\"regenerator-runtime\":\"^0.13.2\",\"shelljs\":\"^0.8.2\",\"sinon\":\"^9.0.1\",\"temp\":\"^0.9.0\",\"webpack\":\"^4.35.0\",\"webpack-cli\":\"^3.3.5\",\"yorkie\":\"^2.0.0\"},\"keywords\":[\"ast\",\"lint\",\"javascript\",\"ecmascript\",\"espree\"],\"license\":\"MIT\",\"engines\":{\"node\":\"^10.12.0 || >=12.0.0\"}}"); +module.exports = JSON.parse("{\"name\":\"eslint\",\"version\":\"7.2.0\",\"author\":\"Nicholas C. Zakas \",\"description\":\"An AST-based pattern checker for JavaScript.\",\"bin\":{\"eslint\":\"./bin/eslint.js\"},\"main\":\"./lib/api.js\",\"scripts\":{\"test\":\"node Makefile.js test\",\"test:cli\":\"mocha\",\"lint\":\"node Makefile.js lint\",\"fix\":\"node Makefile.js lint -- fix\",\"fuzz\":\"node Makefile.js fuzz\",\"generate-release\":\"node Makefile.js generateRelease\",\"generate-alpharelease\":\"node Makefile.js generatePrerelease -- alpha\",\"generate-betarelease\":\"node Makefile.js generatePrerelease -- beta\",\"generate-rcrelease\":\"node Makefile.js generatePrerelease -- rc\",\"publish-release\":\"node Makefile.js publishRelease\",\"docs\":\"node Makefile.js docs\",\"gensite\":\"node Makefile.js gensite\",\"webpack\":\"node Makefile.js webpack\",\"perf\":\"node Makefile.js perf\"},\"gitHooks\":{\"pre-commit\":\"lint-staged\"},\"lint-staged\":{\"*.js\":[\"eslint --fix\",\"git add\"],\"*.md\":\"markdownlint\"},\"files\":[\"LICENSE\",\"README.md\",\"bin\",\"conf\",\"lib\",\"messages\"],\"repository\":\"eslint/eslint\",\"funding\":\"https://opencollective.com/eslint\",\"homepage\":\"https://eslint.org\",\"bugs\":\"https://github.com/eslint/eslint/issues/\",\"dependencies\":{\"@babel/code-frame\":\"^7.0.0\",\"ajv\":\"^6.10.0\",\"chalk\":\"^4.0.0\",\"cross-spawn\":\"^7.0.2\",\"debug\":\"^4.0.1\",\"doctrine\":\"^3.0.0\",\"eslint-scope\":\"^5.1.0\",\"eslint-utils\":\"^2.0.0\",\"eslint-visitor-keys\":\"^1.2.0\",\"espree\":\"^7.1.0\",\"esquery\":\"^1.2.0\",\"esutils\":\"^2.0.2\",\"file-entry-cache\":\"^5.0.1\",\"functional-red-black-tree\":\"^1.0.1\",\"glob-parent\":\"^5.0.0\",\"globals\":\"^12.1.0\",\"ignore\":\"^4.0.6\",\"import-fresh\":\"^3.0.0\",\"imurmurhash\":\"^0.1.4\",\"inquirer\":\"^7.0.0\",\"is-glob\":\"^4.0.0\",\"js-yaml\":\"^3.13.1\",\"json-stable-stringify-without-jsonify\":\"^1.0.1\",\"levn\":\"^0.4.1\",\"lodash\":\"^4.17.14\",\"minimatch\":\"^3.0.4\",\"natural-compare\":\"^1.4.0\",\"optionator\":\"^0.9.1\",\"progress\":\"^2.0.0\",\"regexpp\":\"^3.1.0\",\"semver\":\"^7.2.1\",\"strip-ansi\":\"^6.0.0\",\"strip-json-comments\":\"^3.1.0\",\"table\":\"^5.2.3\",\"text-table\":\"^0.2.0\",\"v8-compile-cache\":\"^2.0.3\"},\"devDependencies\":{\"@babel/core\":\"^7.4.3\",\"@babel/preset-env\":\"^7.4.3\",\"acorn\":\"^7.2.0\",\"babel-loader\":\"^8.0.5\",\"chai\":\"^4.0.1\",\"cheerio\":\"^0.22.0\",\"common-tags\":\"^1.8.0\",\"core-js\":\"^3.1.3\",\"dateformat\":\"^3.0.3\",\"ejs\":\"^3.0.2\",\"escape-string-regexp\":\"^3.0.0\",\"eslint\":\"file:.\",\"eslint-config-eslint\":\"file:packages/eslint-config-eslint\",\"eslint-plugin-eslint-plugin\":\"^2.2.1\",\"eslint-plugin-internal-rules\":\"file:tools/internal-rules\",\"eslint-plugin-jsdoc\":\"^22.1.0\",\"eslint-plugin-node\":\"^11.1.0\",\"eslint-release\":\"^2.0.0\",\"eslump\":\"^2.0.0\",\"esprima\":\"^4.0.1\",\"glob\":\"^7.1.6\",\"jsdoc\":\"^3.5.5\",\"karma\":\"^4.0.1\",\"karma-chrome-launcher\":\"^3.1.0\",\"karma-mocha\":\"^1.3.0\",\"karma-mocha-reporter\":\"^2.2.3\",\"karma-webpack\":\"^4.0.0-rc.6\",\"leche\":\"^2.2.3\",\"lint-staged\":\"^10.1.2\",\"load-perf\":\"^0.2.0\",\"markdownlint\":\"^0.19.0\",\"markdownlint-cli\":\"^0.22.0\",\"memfs\":\"^3.0.1\",\"mocha\":\"^7.1.1\",\"mocha-junit-reporter\":\"^1.23.0\",\"npm-license\":\"^0.3.3\",\"nyc\":\"^15.0.1\",\"proxyquire\":\"^2.0.1\",\"puppeteer\":\"^2.1.1\",\"recast\":\"^0.19.0\",\"regenerator-runtime\":\"^0.13.2\",\"shelljs\":\"^0.8.2\",\"sinon\":\"^9.0.1\",\"temp\":\"^0.9.0\",\"webpack\":\"^4.35.0\",\"webpack-cli\":\"^3.3.5\",\"yorkie\":\"^2.0.0\"},\"keywords\":[\"ast\",\"lint\",\"javascript\",\"ecmascript\",\"espree\"],\"license\":\"MIT\",\"engines\":{\"node\":\"^10.12.0 || >=12.0.0\"}}"); /***/ }), /* 409 */ @@ -48734,6 +48744,50 @@ function equalTokens(left, right, sourceCode) { } return true; +} +/** + * Check if the given node is a true logical expression or not. + * + * The three binary expressions logical-or (`||`), logical-and (`&&`), and + * coalesce (`??`) are known as `ShortCircuitExpression`. + * But ESTree represents those by `LogicalExpression` node. + * + * This function rejects coalesce expressions of `LogicalExpression` node. + * @param {ASTNode} node The node to check. + * @returns {boolean} `true` if the node is `&&` or `||`. + * @see https://tc39.es/ecma262/#prod-ShortCircuitExpression + */ + + +function isLogicalExpression(node) { + return node.type === "LogicalExpression" && (node.operator === "&&" || node.operator === "||"); +} +/** + * Check if the given node is a nullish coalescing expression or not. + * + * The three binary expressions logical-or (`||`), logical-and (`&&`), and + * coalesce (`??`) are known as `ShortCircuitExpression`. + * But ESTree represents those by `LogicalExpression` node. + * + * This function finds only coalesce expressions of `LogicalExpression` node. + * @param {ASTNode} node The node to check. + * @returns {boolean} `true` if the node is `??`. + */ + + +function isCoalesceExpression(node) { + return node.type === "LogicalExpression" && node.operator === "??"; +} +/** + * Check if given two nodes are the pair of a logical expression and a coalesce expression. + * @param {ASTNode} left A node to check. + * @param {ASTNode} right Another node to check. + * @returns {boolean} `true` if the two nodes are the pair of a logical expression and a coalesce expression. + */ + + +function isMixedLogicalAndCoalesceExpressions(left, right) { + return isLogicalExpression(left) && isCoalesceExpression(right) || isCoalesceExpression(left) && isLogicalExpression(right); } //------------------------------------------------------------------------------ // Public Interface //------------------------------------------------------------------------------ @@ -49071,6 +49125,7 @@ module.exports = { case "LogicalExpression": switch (node.operator) { case "||": + case "??": return 4; case "&&": @@ -49697,7 +49752,7 @@ module.exports = { try { tokens = espree.tokenize(leftValue, espreeOptions); - } catch (e) { + } catch (_unused) { return false; } @@ -49726,7 +49781,7 @@ module.exports = { try { tokens = espree.tokenize(rightValue, espreeOptions); - } catch (e) { + } catch (_unused2) { return false; } @@ -49810,8 +49865,11 @@ module.exports = { */ hasOctalEscapeSequence(rawString) { return OCTAL_ESCAPE_PATTERN.test(rawString); - } + }, + isLogicalExpression, + isCoalesceExpression, + isMixedLogicalAndCoalesceExpressions }; /***/ }), @@ -56731,7 +56789,13 @@ module.exports = { if (never && hasWhitespace) { context.report({ node, - loc: leftToken.loc.start, + loc: { + start: leftToken.loc.end, + end: { + line: rightToken.loc.start.line, + column: rightToken.loc.start.column - 1 + } + }, messageId: "unexpectedWhitespace", fix(fixer) { @@ -56750,7 +56814,13 @@ module.exports = { } else if (!never && !hasWhitespace) { context.report({ node, - loc: leftToken.loc.start, + loc: { + start: { + line: leftToken.loc.end.line, + column: leftToken.loc.end.column - 1 + }, + end: rightToken.loc.start + }, messageId: "missing", fix(fixer) { @@ -56761,7 +56831,10 @@ module.exports = { } else if (!never && !allowNewlines && hasNewline) { context.report({ node, - loc: leftToken.loc.start, + loc: { + start: leftToken.loc.end, + end: rightToken.loc.start + }, messageId: "unexpectedNewline", fix(fixer) { @@ -63931,7 +64004,10 @@ module.exports = { if (prevToken && (CHECK_TYPE.test(prevToken.type) || pattern.test(prevToken.value)) && !isOpenParenOfTemplate(prevToken) && astUtils.isTokenOnSameLine(prevToken, token) && sourceCode.isSpaceBetweenTokens(prevToken, token)) { context.report({ - loc: token.loc.start, + loc: { + start: prevToken.loc.end, + end: token.loc.start + }, messageId: "unexpectedBefore", data: token, @@ -63979,7 +64055,10 @@ module.exports = { if (nextToken && (CHECK_TYPE.test(nextToken.type) || pattern.test(nextToken.value)) && !isCloseParenOfTemplate(nextToken) && astUtils.isTokenOnSameLine(token, nextToken) && sourceCode.isSpaceBetweenTokens(token, nextToken)) { context.report({ - loc: token.loc.start, + loc: { + start: token.loc.end, + end: nextToken.loc.start + }, messageId: "unexpectedAfter", data: token, @@ -64228,6 +64307,11 @@ module.exports = { checkSpacingAround(sourceCode.getTokenAfter(firstToken)); } + if (node.type === "ExportAllDeclaration" && node.exported) { + const asToken = sourceCode.getTokenBefore(node.exported); + checkSpacingBefore(asToken, PREV_TOKEN_M); + } + if (node.source) { const fromToken = sourceCode.getTokenBefore(node.source); checkSpacingBefore(fromToken, PREV_TOKEN_M); @@ -67354,41 +67438,44 @@ module.exports = { create(context) { const option = context.options[0]; const multiline = option !== "never"; - const allowSingleLine = option === "always-multiline"; //-------------------------------------------------------------------------- - // Helpers - //-------------------------------------------------------------------------- - - /** - * Tests whether node is preceded by supplied tokens - * @param {ASTNode} node node to check - * @param {ASTNode} parentNode parent of node to report - * @param {boolean} expected whether newline was expected or not - * @returns {void} - * @private - */ - - function reportError(node, parentNode, expected) { - context.report({ - node, - messageId: "".concat(expected ? "expected" : "unexpected").concat(node === parentNode.test ? "TestCons" : "ConsAlt") - }); - } //-------------------------------------------------------------------------- + const allowSingleLine = option === "always-multiline"; + const sourceCode = context.getSourceCode(); //-------------------------------------------------------------------------- // Public //-------------------------------------------------------------------------- - return { ConditionalExpression(node) { - const areTestAndConsequentOnSameLine = astUtils.isTokenOnSameLine(node.test, node.consequent); - const areConsequentAndAlternateOnSameLine = astUtils.isTokenOnSameLine(node.consequent, node.alternate); + const questionToken = sourceCode.getTokenAfter(node.test, astUtils.isNotClosingParenToken); + const colonToken = sourceCode.getTokenAfter(node.consequent, astUtils.isNotClosingParenToken); + const firstTokenOfTest = sourceCode.getFirstToken(node); + const lastTokenOfTest = sourceCode.getTokenBefore(questionToken); + const firstTokenOfConsequent = sourceCode.getTokenAfter(questionToken); + const lastTokenOfConsequent = sourceCode.getTokenBefore(colonToken); + const firstTokenOfAlternate = sourceCode.getTokenAfter(colonToken); + const areTestAndConsequentOnSameLine = astUtils.isTokenOnSameLine(lastTokenOfTest, firstTokenOfConsequent); + const areConsequentAndAlternateOnSameLine = astUtils.isTokenOnSameLine(lastTokenOfConsequent, firstTokenOfAlternate); if (!multiline) { if (!areTestAndConsequentOnSameLine) { - reportError(node.test, node, false); + context.report({ + node: node.test, + loc: { + start: firstTokenOfTest.loc.start, + end: lastTokenOfTest.loc.end + }, + messageId: "unexpectedTestCons" + }); } if (!areConsequentAndAlternateOnSameLine) { - reportError(node.consequent, node, false); + context.report({ + node: node.consequent, + loc: { + start: firstTokenOfConsequent.loc.start, + end: lastTokenOfConsequent.loc.end + }, + messageId: "unexpectedConsAlt" + }); } } else { if (allowSingleLine && node.loc.start.line === node.loc.end.line) { @@ -67396,11 +67483,25 @@ module.exports = { } if (areTestAndConsequentOnSameLine) { - reportError(node.test, node, true); + context.report({ + node: node.test, + loc: { + start: firstTokenOfTest.loc.start, + end: lastTokenOfTest.loc.end + }, + messageId: "expectedTestCons" + }); } if (areConsequentAndAlternateOnSameLine) { - reportError(node.consequent, node, true); + context.report({ + node: node.consequent, + loc: { + start: firstTokenOfConsequent.loc.start, + end: lastTokenOfConsequent.loc.end + }, + messageId: "expectedConsAlt" + }); } } } @@ -69978,7 +70079,7 @@ const collector = new class { this._validator.validatePattern(regexpStr); // Call onCharacter hook - } catch (err) {// Ignore syntax errors in RegExp. + } catch (_unused) {// Ignore syntax errors in RegExp. } return this._controlChars; @@ -75048,6 +75149,10 @@ module.exports = { return precedence(node) < precedence(parent); case "LogicalExpression": + if (astUtils.isMixedLogicalAndCoalesceExpressions(node, parent)) { + return true; + } + if (previousNode === parent.left) { return precedence(node) < precedence(parent); } @@ -77251,6 +77356,9 @@ module.exports = { }, enforceForNewInMemberExpressions: { type: "boolean" + }, + enforceForFunctionPrototypeMethods: { + type: "boolean" } }, additionalProperties: false @@ -77276,6 +77384,7 @@ module.exports = { const IGNORE_ARROW_CONDITIONALS = ALL_NODES && context.options[1] && context.options[1].enforceForArrowConditionals === false; const IGNORE_SEQUENCE_EXPRESSIONS = ALL_NODES && context.options[1] && context.options[1].enforceForSequenceExpressions === false; const IGNORE_NEW_IN_MEMBER_EXPR = ALL_NODES && context.options[1] && context.options[1].enforceForNewInMemberExpressions === false; + const IGNORE_FUNCTION_PROTOTYPE_METHODS = ALL_NODES && context.options[1] && context.options[1].enforceForFunctionPrototypeMethods === false; const PRECEDENCE_OF_ASSIGNMENT_EXPR = precedence({ type: "AssignmentExpression" }); @@ -77283,6 +77392,17 @@ module.exports = { type: "UpdateExpression" }); let reportsBuffer; + /** + * Determines whether the given node is a `call` or `apply` method call, invoked directly on a `FunctionExpression` node. + * Example: function(){}.call() + * @param {ASTNode} node The node to be checked. + * @returns {boolean} True if the node is an immediate `call` or `apply` method call. + * @private + */ + + function isImmediateFunctionPrototypeMethodCall(node) { + return node.type === "CallExpression" && node.callee.type === "MemberExpression" && node.callee.object.type === "FunctionExpression" && ["call", "apply"].includes(astUtils.getStaticPropertyName(node.callee)); + } /** * Determines if this rule should be enforced for a node given the current configuration. * @param {ASTNode} node The node to be checked. @@ -77290,6 +77410,7 @@ module.exports = { * @private */ + function ruleApplies(node) { if (node.type === "JSXElement" || node.type === "JSXFragment") { const isSingleLine = node.loc.start.line === node.loc.end.line; @@ -77318,6 +77439,10 @@ module.exports = { return false; } + if (isImmediateFunctionPrototypeMethodCall(node) && IGNORE_FUNCTION_PROTOTYPE_METHODS) { + return false; + } + return ALL_NODES || node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression"; } /** @@ -77670,13 +77795,13 @@ module.exports = { const shouldSkipRight = NESTED_BINARY && (node.right.type === "BinaryExpression" || node.right.type === "LogicalExpression"); if (!shouldSkipLeft && hasExcessParens(node.left)) { - if (!(node.left.type === "UnaryExpression" && isExponentiation) && (leftPrecedence > prec || leftPrecedence === prec && !isExponentiation) || isParenthesisedTwice(node.left)) { + if (!(node.left.type === "UnaryExpression" && isExponentiation) && !astUtils.isMixedLogicalAndCoalesceExpressions(node.left, node) && (leftPrecedence > prec || leftPrecedence === prec && !isExponentiation) || isParenthesisedTwice(node.left)) { report(node.left); } } if (!shouldSkipRight && hasExcessParens(node.right)) { - if (rightPrecedence > prec || rightPrecedence === prec && isExponentiation || isParenthesisedTwice(node.right)) { + if (!astUtils.isMixedLogicalAndCoalesceExpressions(node.right, node) && (rightPrecedence > prec || rightPrecedence === prec && isExponentiation) || isParenthesisedTwice(node.right)) { report(node.right); } } @@ -78093,7 +78218,7 @@ module.exports = { LogicalExpression: checkBinaryLogical, MemberExpression(node) { - const nodeObjHasExcessParens = hasExcessParens(node.object); + const nodeObjHasExcessParens = hasExcessParens(node.object) && !(isImmediateFunctionPrototypeMethodCall(node.parent) && node.parent.callee === node && IGNORE_FUNCTION_PROTOTYPE_METHODS); if (nodeObjHasExcessParens && precedence(node.object) >= precedence(node) && (node.computed || !(astUtils.isDecimalInteger(node.object) || // RegExp literal is allowed to have parens (#1589) node.object.type === "Literal" && node.object.regex))) { @@ -79756,7 +79881,7 @@ module.exports = { try { validator.validateFlags(flags); return null; - } catch (err) { + } catch (_unused) { return "Invalid flags supplied to RegExp constructor '".concat(flags, "'"); } } @@ -81397,7 +81522,7 @@ module.exports = { try { patternNode = parser.parsePattern(pattern, 0, pattern.length, flags.includes("u")); - } catch (e) { + } catch (_unused) { // Ignore regular expressions with syntax errors return; } @@ -81578,7 +81703,8 @@ const COMPARISON_OPERATORS = ["==", "!=", "===", "!==", ">", ">=", "<", "<="]; const LOGICAL_OPERATORS = ["&&", "||"]; const RELATIONAL_OPERATORS = ["in", "instanceof"]; const TERNARY_OPERATOR = ["?:"]; -const ALL_OPERATORS = [].concat(ARITHMETIC_OPERATORS, BITWISE_OPERATORS, COMPARISON_OPERATORS, LOGICAL_OPERATORS, RELATIONAL_OPERATORS, TERNARY_OPERATOR); +const COALESCE_OPERATOR = ["??"]; +const ALL_OPERATORS = [].concat(ARITHMETIC_OPERATORS, BITWISE_OPERATORS, COMPARISON_OPERATORS, LOGICAL_OPERATORS, RELATIONAL_OPERATORS, TERNARY_OPERATOR, COALESCE_OPERATOR); const DEFAULT_GROUPS = [ARITHMETIC_OPERATORS, BITWISE_OPERATORS, COMPARISON_OPERATORS, LOGICAL_OPERATORS, RELATIONAL_OPERATORS]; const TARGET_NODE_TYPE = /^(?:Binary|Logical|Conditional)Expression$/u; /** @@ -82038,29 +82164,34 @@ module.exports = { * characters begin. */ - let regex = /^(?=[\t ]*(\t | \t))/u; + let regex = /^(?=( +|\t+))\1(?:\t| )/u; if (smartTabs) { /* * At least one space followed by a tab * before non-tab/-space characters begin. */ - regex = /^(?=[\t ]* \t)/u; + regex = /^(?=(\t*))\1(?=( +))\2\t/u; } lines.forEach((line, i) => { const match = regex.exec(line); if (match) { - const lineNumber = i + 1, - column = match.index + 1, - loc = { - line: lineNumber, - column + const lineNumber = i + 1; + const loc = { + start: { + line: lineNumber, + column: match[0].length - 2 + }, + end: { + line: lineNumber, + column: match[0].length + } }; if (!ignoredCommentLines.has(lineNumber)) { - const containingNode = sourceCode.getNodeByRangeIndex(sourceCode.getIndexFromLoc(loc)); + const containingNode = sourceCode.getNodeByRangeIndex(sourceCode.getIndexFromLoc(loc.start)); if (!(containingNode && ["Literal", "TemplateElement"].includes(containingNode.type))) { context.report({ @@ -84084,7 +84215,7 @@ module.exports = { try { regExpAST = regExpParser.parsePattern(pattern, 0, pattern.length, flags.includes("u")); - } catch (e) { + } catch (_unused) { // Ignore regular expressions with syntax errors return; } @@ -84244,6 +84375,12 @@ module.exports = { } return { + ExportAllDeclaration(node) { + if (node.exported) { + checkExportedName(node.exported); + } + }, + ExportNamedDeclaration(node) { const declaration = node.declaration; @@ -88646,7 +88783,7 @@ module.exports = { loc: node.consequent.loc.start, messageId: "unnecessaryConditionalAssignment", fix: fixer => { - const shouldParenthesizeAlternate = astUtils.getPrecedence(node.alternate) < OR_PRECEDENCE && !astUtils.isParenthesised(sourceCode, node.alternate); + const shouldParenthesizeAlternate = (astUtils.getPrecedence(node.alternate) < OR_PRECEDENCE || astUtils.isCoalesceExpression(node.alternate)) && !astUtils.isParenthesised(sourceCode, node.alternate); const alternateText = shouldParenthesizeAlternate ? "(".concat(sourceCode.getText(node.alternate), ")") : astUtils.getParenthesisedText(sourceCode, node.alternate); const testText = astUtils.getParenthesisedText(sourceCode, node.test); return fixer.replaceText(node, "".concat(testText, " || ").concat(alternateText)); @@ -89245,7 +89382,7 @@ module.exports = { return true; } - return /^(?:Assignment|Call|New|Update|Yield|Await)Expression$/u.test(node.type) || node.type === "UnaryExpression" && ["delete", "void"].indexOf(node.operator) >= 0; + return /^(?:Assignment|Call|New|Update|Yield|Await|Import)Expression$/u.test(node.type) || node.type === "UnaryExpression" && ["delete", "void"].indexOf(node.operator) >= 0; } return { @@ -89953,7 +90090,7 @@ module.exports = { if (unusedVar.defs.length > 0) { context.report({ - node: unusedVar.identifiers[0], + node: unusedVar.references.length ? unusedVar.references[unusedVar.references.length - 1].identifier : unusedVar.identifiers[0], 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. @@ -90314,7 +90451,7 @@ module.exports = { try { regExpAST = parser.parsePattern(pattern, 0, pattern.length, flags.includes("u")); - } catch (e) { + } catch (_unused) { // Ignore regular expressions with syntax errors return; } @@ -96987,7 +97124,7 @@ module.exports = { try { ast = parser.parsePattern(pattern, 0, pattern.length, uFlag); - } catch (_) { + } catch (_unused) { // ignore regex syntax errors return; } @@ -98456,7 +98593,7 @@ module.exports = { try { tokens = espree.tokenize(key.value); - } catch (e) { + } catch (_unused) { return; } @@ -98549,7 +98686,7 @@ module.exports = { try { tokens = espree.tokenize(key.value); - } catch (e) { + } catch (_unused2) { necessaryQuotes = true; return; } @@ -103439,7 +103576,10 @@ module.exports = { if (never && hasWhitespace) { context.report({ node, - loc: tagToken.loc.start, + loc: { + start: tagToken.loc.end, + end: literalToken.loc.start + }, messageId: "unexpected", fix(fixer) { @@ -103456,7 +103596,10 @@ module.exports = { } else if (!never && !hasWhitespace) { context.report({ node, - loc: tagToken.loc.start, + loc: { + start: node.loc.start, + end: literalToken.loc.start + }, messageId: "missing", fix(fixer) { @@ -106720,7 +106863,7 @@ module.exports = { /* 720 */ /***/ (function(module) { -module.exports = JSON.parse("{\"_from\":\"doctrine@^3.0.0\",\"_id\":\"doctrine@3.0.0\",\"_inBundle\":false,\"_integrity\":\"sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==\",\"_location\":\"/doctrine\",\"_phantomChildren\":{},\"_requested\":{\"type\":\"range\",\"registry\":true,\"raw\":\"doctrine@^3.0.0\",\"name\":\"doctrine\",\"escapedName\":\"doctrine\",\"rawSpec\":\"^3.0.0\",\"saveSpec\":null,\"fetchSpec\":\"^3.0.0\"},\"_requiredBy\":[\"/\",\"/eslint\"],\"_resolved\":\"https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz\",\"_shasum\":\"addebead72a6574db783639dc87a121773973961\",\"_spec\":\"doctrine@^3.0.0\",\"_where\":\"/root/sources/pve/pve-eslint/eslint-v7.1.0\",\"bugs\":{\"url\":\"https://github.com/eslint/doctrine/issues\"},\"bundleDependencies\":false,\"dependencies\":{\"esutils\":\"^2.0.2\"},\"deprecated\":false,\"description\":\"JSDoc parser\",\"devDependencies\":{\"coveralls\":\"^3.0.1\",\"dateformat\":\"^1.0.11\",\"eslint\":\"^1.10.3\",\"eslint-release\":\"^1.0.0\",\"linefix\":\"^0.1.1\",\"mocha\":\"^3.4.2\",\"npm-license\":\"^0.3.1\",\"nyc\":\"^10.3.2\",\"semver\":\"^5.0.3\",\"shelljs\":\"^0.5.3\",\"shelljs-nodecli\":\"^0.1.1\",\"should\":\"^5.0.1\"},\"directories\":{\"lib\":\"./lib\"},\"engines\":{\"node\":\">=6.0.0\"},\"files\":[\"lib\"],\"homepage\":\"https://github.com/eslint/doctrine\",\"license\":\"Apache-2.0\",\"main\":\"lib/doctrine.js\",\"maintainers\":[{\"name\":\"Nicholas C. Zakas\",\"email\":\"nicholas+npm@nczconsulting.com\",\"url\":\"https://www.nczonline.net\"},{\"name\":\"Yusuke Suzuki\",\"email\":\"utatane.tea@gmail.com\",\"url\":\"https://github.com/Constellation\"}],\"name\":\"doctrine\",\"repository\":{\"type\":\"git\",\"url\":\"git+https://github.com/eslint/doctrine.git\"},\"scripts\":{\"coveralls\":\"nyc report --reporter=text-lcov | coveralls\",\"generate-alpharelease\":\"eslint-generate-prerelease alpha\",\"generate-betarelease\":\"eslint-generate-prerelease beta\",\"generate-rcrelease\":\"eslint-generate-prerelease rc\",\"generate-release\":\"eslint-generate-release\",\"lint\":\"eslint lib/\",\"pretest\":\"npm run lint\",\"publish-release\":\"eslint-publish-release\",\"test\":\"nyc mocha\"},\"version\":\"3.0.0\"}"); +module.exports = JSON.parse("{\"_from\":\"doctrine@^3.0.0\",\"_id\":\"doctrine@3.0.0\",\"_inBundle\":false,\"_integrity\":\"sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==\",\"_location\":\"/doctrine\",\"_phantomChildren\":{},\"_requested\":{\"type\":\"range\",\"registry\":true,\"raw\":\"doctrine@^3.0.0\",\"name\":\"doctrine\",\"escapedName\":\"doctrine\",\"rawSpec\":\"^3.0.0\",\"saveSpec\":null,\"fetchSpec\":\"^3.0.0\"},\"_requiredBy\":[\"/\",\"/eslint\"],\"_resolved\":\"https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz\",\"_shasum\":\"addebead72a6574db783639dc87a121773973961\",\"_spec\":\"doctrine@^3.0.0\",\"_where\":\"/root/sources/pve/pve-eslint/eslint-v7.2.0\",\"bugs\":{\"url\":\"https://github.com/eslint/doctrine/issues\"},\"bundleDependencies\":false,\"dependencies\":{\"esutils\":\"^2.0.2\"},\"deprecated\":false,\"description\":\"JSDoc parser\",\"devDependencies\":{\"coveralls\":\"^3.0.1\",\"dateformat\":\"^1.0.11\",\"eslint\":\"^1.10.3\",\"eslint-release\":\"^1.0.0\",\"linefix\":\"^0.1.1\",\"mocha\":\"^3.4.2\",\"npm-license\":\"^0.3.1\",\"nyc\":\"^10.3.2\",\"semver\":\"^5.0.3\",\"shelljs\":\"^0.5.3\",\"shelljs-nodecli\":\"^0.1.1\",\"should\":\"^5.0.1\"},\"directories\":{\"lib\":\"./lib\"},\"engines\":{\"node\":\">=6.0.0\"},\"files\":[\"lib\"],\"homepage\":\"https://github.com/eslint/doctrine\",\"license\":\"Apache-2.0\",\"main\":\"lib/doctrine.js\",\"maintainers\":[{\"name\":\"Nicholas C. Zakas\",\"email\":\"nicholas+npm@nczconsulting.com\",\"url\":\"https://www.nczonline.net\"},{\"name\":\"Yusuke Suzuki\",\"email\":\"utatane.tea@gmail.com\",\"url\":\"https://github.com/Constellation\"}],\"name\":\"doctrine\",\"repository\":{\"type\":\"git\",\"url\":\"git+https://github.com/eslint/doctrine.git\"},\"scripts\":{\"coveralls\":\"nyc report --reporter=text-lcov | coveralls\",\"generate-alpharelease\":\"eslint-generate-prerelease alpha\",\"generate-betarelease\":\"eslint-generate-prerelease beta\",\"generate-rcrelease\":\"eslint-generate-prerelease rc\",\"generate-release\":\"eslint-generate-release\",\"lint\":\"eslint lib/\",\"pretest\":\"npm run lint\",\"publish-release\":\"eslint-publish-release\",\"test\":\"nyc mocha\"},\"version\":\"3.0.0\"}"); /***/ }), /* 721 */ @@ -117829,12 +117972,12 @@ function isCaseNode(node) { * Checks whether the given logical operator is taken into account for the code * path analysis. * @param {string} operator The operator found in the LogicalExpression node - * @returns {boolean} `true` if the operator is "&&" or "||" + * @returns {boolean} `true` if the operator is "&&" or "||" or "??" */ function isHandledLogicalOperator(operator) { - return operator === "&&" || operator === "||"; + return operator === "&&" || operator === "||" || operator === "??"; } /** * Gets the label if the parent node of a given node is a LabeledStatement. @@ -118925,6 +119068,7 @@ function finalizeTestSegmentsOfFor(context, choiceContext, head) { if (!choiceContext.processed) { choiceContext.trueForkContext.add(head); choiceContext.falseForkContext.add(head); + choiceContext.qqForkContext.add(head); } if (context.test !== true) { @@ -119072,6 +119216,7 @@ class CodePathState { isForkingAsResult, trueForkContext: ForkContext.newEmpty(this.forkContext), falseForkContext: ForkContext.newEmpty(this.forkContext), + qqForkContext: ForkContext.newEmpty(this.forkContext), processed: false }; } @@ -119090,6 +119235,7 @@ class CodePathState { switch (context.kind) { case "&&": case "||": + case "??": /* * If any result were not transferred from child contexts, * this sets the head segments to both cases. @@ -119098,6 +119244,7 @@ class CodePathState { if (!context.processed) { context.trueForkContext.add(headSegments); context.falseForkContext.add(headSegments); + context.qqForkContext.add(headSegments); } /* * Transfers results to upper context if this context is in @@ -119109,6 +119256,7 @@ class CodePathState { const parentContext = this.choiceContext; parentContext.trueForkContext.addAll(context.trueForkContext); parentContext.falseForkContext.addAll(context.falseForkContext); + parentContext.qqForkContext.addAll(context.qqForkContext); parentContext.processed = true; return context; } @@ -119170,9 +119318,28 @@ class CodePathState { * This got segments already from the child choice context. * Creates the next path from own true/false fork context. */ - const prevForkContext = context.kind === "&&" ? context.trueForkContext - /* kind === "||" */ - : context.falseForkContext; + let prevForkContext; + + switch (context.kind) { + case "&&": + // if true then go to the right-hand side. + prevForkContext = context.trueForkContext; + break; + + case "||": + // if false then go to the right-hand side. + prevForkContext = context.falseForkContext; + break; + + case "??": + // Both true/false can short-circuit, so needs the third path to go to the right-hand side. That's qqForkContext. + prevForkContext = context.qqForkContext; + break; + + default: + throw new Error("unreachable"); + } + forkContext.replaceHead(prevForkContext.makeNext(0, -1)); prevForkContext.clear(); context.processed = false; @@ -119182,12 +119349,25 @@ class CodePathState { * So addresses the head segments. * The head segments are the path of the left-hand operand. */ - if (context.kind === "&&") { - // The path does short-circuit if false. - context.falseForkContext.add(forkContext.head); - } else { - // The path does short-circuit if true. - context.trueForkContext.add(forkContext.head); + switch (context.kind) { + case "&&": + // the false path can short-circuit. + context.falseForkContext.add(forkContext.head); + break; + + case "||": + // the true path can short-circuit. + context.trueForkContext.add(forkContext.head); + break; + + case "??": + // both can short-circuit. + context.trueForkContext.add(forkContext.head); + context.falseForkContext.add(forkContext.head); + break; + + default: + throw new Error("unreachable"); } forkContext.replaceHead(forkContext.makeNext(-1, -1)); @@ -119211,6 +119391,7 @@ class CodePathState { if (!context.processed) { context.trueForkContext.add(forkContext.head); context.falseForkContext.add(forkContext.head); + context.qqForkContext.add(forkContext.head); } context.processed = false; // Creates new path from the `true` case. @@ -121074,7 +121255,7 @@ module.exports = class ConfigCommentParser { config: items }; } - } catch (ex) { + } catch (_unused) { debug("Levn parsing failed; falling back to manual parsing."); // ignore to parse the string by a fallback. } /* @@ -127214,7 +127395,7 @@ function getCacheFile(cacheFile, cwd) { try { fileStats = fs.lstatSync(resolvedCacheFile); - } catch (ex) { + } catch (_unused) { fileStats = null; } /* @@ -127769,7 +127950,7 @@ class CLIEngine { try { const npmFormat = naming.normalizePackageName(normalizedFormatName, "eslint-formatter"); formatterPath = ModuleResolver.resolve(npmFormat, path.join(cwd, "__placeholder__.js")); - } catch (e) { + } catch (_unused2) { formatterPath = path.resolve(__dirname, "formatters", normalizedFormatName); } } @@ -129039,7 +129220,7 @@ class ConfigArrayFactory { try { loadPackageJSONConfigFile(filePath); return filePath; - } catch (error) { + } catch (_unused) { /* ignore */ } } else {