diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e35b145164..fd0313ef6f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,36 @@ +v6.4.0 - September 13, 2019 + +* [`e915fff`](https://github.com/eslint/eslint/commit/e915fffb6089a23ff1cae926cc607f9b87dc1819) Docs: Improve examples and clarify default option (#12067) (Yuping Zuo) +* [`540296f`](https://github.com/eslint/eslint/commit/540296fcecd232a09dc873a5a22f5839b59b7842) Update: enforceForClassMembers option to accessor-pairs (fixes #12063) (#12192) (Milos Djermanovic) +* [`d3c2334`](https://github.com/eslint/eslint/commit/d3c2334646eae9287d5be9e457d041e445efb512) Update: flag nested block with declaration as error (#12193) (David Waller) +* [`b2498d2`](https://github.com/eslint/eslint/commit/b2498d284b9c30ed1543429c2f45d9014e12fe22) Update: Fix handling of property names in no-self-assign (#12105) (Milos Djermanovic) +* [`1ee61b0`](https://github.com/eslint/eslint/commit/1ee61b06715fcc750be2c923034a1e59ba663287) Update: enforceForClassMembers computed-property-spacing (fixes #12049) (#12214) (Milos Djermanovic) +* [`520c922`](https://github.com/eslint/eslint/commit/520c92270eed6e90c1a796e8af275980f01705e0) Docs: Added naming convention details to plugin usage (#12202) (Henrique Barcelos) +* [`f826eab`](https://github.com/eslint/eslint/commit/f826eabbeecddb047f58f4e7308a14c18148d369) Fix: Allow line comment exception in object-curly-spacing (fixes #11902) (#12216) (Milos Djermanovic) +* [`db2a29b`](https://github.com/eslint/eslint/commit/db2a29beb0fa28183f65bf9e659c66c03a8918b5) Update: indentation of comment followed by semicolon (fixes #12232) (#12243) (Kai Cataldo) +* [`ae17d1c`](https://github.com/eslint/eslint/commit/ae17d1ca59dd466aa64da0680ec2453c2dc3b80d) Fix: no-sequences is reporting incorrect locations (#12241) (Milos Djermanovic) +* [`365331a`](https://github.com/eslint/eslint/commit/365331a42e22af5a77ac9cfa9673d6a8f653eb5a) Fix: object-shorthand providing invalid fixes for typescript (#12260) (Brad Zacher) +* [`1c921c6`](https://github.com/eslint/eslint/commit/1c921c6dfd7ddfb0308c8103e53d32c1241475f0) New: add no-import-assign (fixes #12237) (#12252) (Toru Nagashima) +* [`3be04fd`](https://github.com/eslint/eslint/commit/3be04fd6a4e7b3f5a5ecb845a29cf29b71fe2dfb) New: Add prefer-regex-literals rule (fixes #12238) (#12254) (Milos Djermanovic) +* [`37c0fde`](https://github.com/eslint/eslint/commit/37c0fdeb87b92a0b779b125adf45535b79b65757) Update: Report global Atomics calls in no-obj-calls (fixes #12234) (#12258) (Milos Djermanovic) +* [`985c9e5`](https://github.com/eslint/eslint/commit/985c9e5eba351965a8a1491a41dbdcc78154b8f4) Fix: space-before-function-paren autofix removes comments (fixes #12259) (#12264) (Milos Djermanovic) +* [`01da7d0`](https://github.com/eslint/eslint/commit/01da7d04c4e5a7376cf241ec02db7971726a1bf9) Fix: eqeqeq rule reports incorrect locations (#12265) (Milos Djermanovic) +* [`319e4d8`](https://github.com/eslint/eslint/commit/319e4d8386ea846928f0f906c251b46043a53491) Docs: adding finally example (#12256) (Jens Melgaard) +* [`d52328f`](https://github.com/eslint/eslint/commit/d52328f012f3704c7d1ce39427e63f80531c7979) Docs: fix no-sequences `with` examples (#12239) (Milos Djermanovic) +* [`a41fdc0`](https://github.com/eslint/eslint/commit/a41fdc07404a7675d14183fab245fb8f49dcb858) Fix: Remove autofixer for no-unsafe-negation (#12157) (Milos Djermanovic) +* [`e38f5fd`](https://github.com/eslint/eslint/commit/e38f5fdfc786363a3eae642f1a69a8725600aa61) Update: fix no-octal-escape false negatives after \0 (#12079) (Milos Djermanovic) +* [`9418fbe`](https://github.com/eslint/eslint/commit/9418fbe0eb31cace3debe27b620709628df2fad7) Sponsors: Sync README with website (ESLint Jenkins) +* [`acc5ec5`](https://github.com/eslint/eslint/commit/acc5ec5082aed466a29899f651e6767b39155aec) Sponsors: Sync README with website (ESLint Jenkins) +* [`460c5ad`](https://github.com/eslint/eslint/commit/460c5ad176eaf39ff579cd96b3bcbe0539093f8f) Sponsors: Sync README with website (ESLint Jenkins) +* [`0313441`](https://github.com/eslint/eslint/commit/0313441d016c8aa0674c135f9da67a676e766ec5) New: add rule default-param-last (fixes #11361) (#12188) (Chiawen Chen) +* [`7621f5d`](https://github.com/eslint/eslint/commit/7621f5d2aa7d87e798b75ca47d6889c280597e99) Update: add more specific linting messages to space-in-parens (#11121) (Che Fisher) +* [`21eb904`](https://github.com/eslint/eslint/commit/21eb9044135c01b6c12188517bba840614483fc6) Fix: basePath of OverrideTester (fixes #12032) (#12205) (Toru Nagashima) +* [`86e5e65`](https://github.com/eslint/eslint/commit/86e5e657ea3fbf12b10524abcbc197afd215a060) Sponsors: Sync README with website (ESLint Jenkins) +* [`2b1a13f`](https://github.com/eslint/eslint/commit/2b1a13fa0de8360586857f3ced8da514c971297d) Fix: no-extra-boolean-cast reports wrong negation node (fixes #11324) (#12197) (Milos Djermanovic) +* [`ba8c2aa`](https://github.com/eslint/eslint/commit/ba8c2aa0154561fbeca33db0343cb39a7fbd9b4f) Sponsors: Sync README with website (ESLint Jenkins) +* [`a0a9746`](https://github.com/eslint/eslint/commit/a0a9746724ccd22c721ddc1b25c566aa9acea154) Docs: Fix link in no-irregular-whitespace.md (#12196) (Timo Tijhof) +* [`e10eeba`](https://github.com/eslint/eslint/commit/e10eebab4abd193dee697c4de7fb2d95bbab2d8c) Fix: quotes autofix produces syntax error with octal escape sequences (#12118) (Milos Djermanovic) + v6.3.0 - August 30, 2019 * [`0acdefb`](https://github.com/eslint/eslint/commit/0acdefb97f35bb09db2910540c70dc377a01ad62) Chore: refactor code (#12113) (James George) diff --git a/README.md b/README.md index 134c991d81d..9b3e925c3e7 100644 --- a/README.md +++ b/README.md @@ -210,11 +210,6 @@ Toru Nagashima Gyandeep Singh - -
-Kai Cataldo -
-
Teddy Katz @@ -241,6 +236,11 @@ The people who review and implement new features. The people who review and fix bugs and help triage issues.
+ +
+Kai Cataldo +
+

Pig Fang @@ -262,9 +262,9 @@ The following companies, organizations, and individuals support ESLint's ongoing

Gold Sponsors

-

Shopify Salesforce Badoo Airbnb Facebook Open Source

Silver Sponsors

+

Shopify Salesforce Badoo Airbnb Facebook Open Source

Silver Sponsors

AMP Project

Bronze Sponsors

-

VPS Server Free Icons by Icons8 UI UX Design Agencies clay Discord ThemeIsle TekHattan Marfeel Fire Stick Tricks JSHeroes

+

Discord MONEYPUG Free Icons by Icons8 UI UX Design Agencies clay VPS Server ThemeIsle TekHattan Marfeel Fire Stick Tricks JSHeroes

## Technology Sponsors diff --git a/docs/developer-guide/working-with-plugins.md b/docs/developer-guide/working-with-plugins.md index 5a8fd764b38..a2b238cc936 100644 --- a/docs/developer-guide/working-with-plugins.md +++ b/docs/developer-guide/working-with-plugins.md @@ -1,6 +1,6 @@ # Working with Plugins -Each plugin is an npm module with a name in the format of `eslint-plugin-`, such as `eslint-plugin-jquery`. You can also use scoped packages in the format of `@/eslint-plugin-` such as `@jquery/eslint-plugin-jquery`. +Each plugin is an npm module with a name in the format of `eslint-plugin-`, such as `eslint-plugin-jquery`. You can also use scoped packages in the format of `@/eslint-plugin-` such as `@jquery/eslint-plugin-jquery` or even `@/eslint-plugin` such as `@jquery/eslint-plugin`. ## Create a Plugin diff --git a/docs/rules/accessor-pairs.md b/docs/rules/accessor-pairs.md index 183bc42b6e6..43a14cc18b6 100644 --- a/docs/rules/accessor-pairs.md +++ b/docs/rules/accessor-pairs.md @@ -1,4 +1,4 @@ -# Enforces getter/setter pairs in objects (accessor-pairs) +# Enforces getter/setter pairs in objects and classes (accessor-pairs) It's a common mistake in JavaScript to create an object with just a setter for a property but never have a corresponding getter defined for it. Without a getter, you cannot read the property, so it ends up not being used. @@ -32,10 +32,14 @@ This rule enforces a style where it requires to have a getter for every property By activating the option `getWithoutSet` it enforces the presence of a setter for every property which has a getter defined. +By default, this rule checks only object literals and property descriptors. If you want this rule +to also check class declarations and class expressions, activate the option `enforceForClassMembers`. + ## Options * `setWithoutGet` set to `true` will warn for setters without getters (Default `true`). * `getWithoutSet` set to `true` will warn for getters without setters (Default `false`). +* `enforceForClassMembers` set to `true` additionally applies this rule to class getters/setters (Default `false`). ### setWithoutGet @@ -143,6 +147,61 @@ Object.defineProperty(o, 'c', { ``` +### enforceForClassMembers + +By default, this rule does not enforce getter/setter pairs in class declarations and class expressions, +as the default value for `enforceForClassMembers` is `false`. + +When `enforceForClassMembers` is set to `true`: + +* `"getWithoutSet": true` will also warn for getters without setters in classes. +* `"setWithoutGet": true` will also warn for setters without getters in classes. + +Examples of **incorrect** code for `{ "getWithoutSet": true, "enforceForClassMembers": true }`: + +```js +/*eslint accessor-pairs: ["error", { "getWithoutSet": true, "enforceForClassMembers": true }]*/ + +class Foo { + get a() { + return this.val; + } +} + +class Bar { + static get a() { + return this.val; + } +} + +const Baz = class { + get a() { + return this.val; + } + static set a(value) { + this.val = value; + } +} +``` + +Examples of **incorrect** code for `{ "setWithoutGet": true, "enforceForClassMembers": true }`: + +```js +/*eslint accessor-pairs: ["error", { "setWithoutGet": true, "enforceForClassMembers": true }]*/ + +class Foo { + set a(value) { + this.val = value; + } +} + +const Bar = class { + static set a(value) { + this.val = value; + } +} +``` + ## Known Limitations Due to the limits of static analysis, this rule does not account for possible side effects and in certain cases @@ -164,7 +223,7 @@ var o = { }; ``` -Also, this rule does not disallow duplicate keys in object literals, and in certain cases with duplicate keys +Also, this rule does not disallow duplicate keys in object literals and class definitions, and in certain cases with duplicate keys might not report a missing pair for a getter/setter, like in the following example: ```js @@ -186,6 +245,8 @@ The code above creates an object with just a setter for the property `"a"`. See [no-dupe-keys](no-dupe-keys.md) if you also want to disallow duplicate keys in object literals. +See [no-dupe-class-members](no-dupe-class-members.md) if you also want to disallow duplicate names in class definitions. + ## When Not To Use It You can turn this rule off if you are not concerned with the simultaneous presence of setters and getters on objects. diff --git a/docs/rules/computed-property-spacing.md b/docs/rules/computed-property-spacing.md index 89b1c775e06..9641ee089e5 100644 --- a/docs/rules/computed-property-spacing.md +++ b/docs/rules/computed-property-spacing.md @@ -25,11 +25,17 @@ This rule does not apply to brackets that are separated from the adjacent value ## Options -This rule has a string option: +This rule has two options, a string option and an object option. + +String option: * `"never"` (default) disallows spaces inside computed property brackets * `"always"` requires one or more spaces inside computed property brackets +Object option: + +* `"enforceForClassMembers": true` additionally applies this rule to class members (default is `false`) + ### never Examples of **incorrect** code for this rule with the default `"never"` option: @@ -84,6 +90,53 @@ var x = {[ b ]: a} obj[ foo[ bar ] ] ``` +#### enforceForClassMembers + +By default, this rule does not check class declarations and class expressions, +as the default value for `enforceForClassMembers` is `false`. + +When `enforceForClassMembers` is set to `true`, the rule will also disallow/enforce spaces inside of +computed keys of class methods, getters and setters. + +Examples of **incorrect** code for this rule with `"never"` and `{ "enforceForClassMembers": true }`: + +```js +/*eslint computed-property-spacing: ["error", "never", { "enforceForClassMembers": true }]*/ +/*eslint-env es6*/ + +class Foo { + [a ]() {} + get [b ]() {} + set [b ](value) {} +} + +const Bar = class { + [ a](){} + static [ b]() {} + static get [ c ]() {} + static set [ c ](value) {} +} +``` + +Examples of **correct** code for this rule with `"never"` and `{ "enforceForClassMembers": true }`: + +```js +/*eslint computed-property-spacing: ["error", "never", { "enforceForClassMembers": true }]*/ +/*eslint-env es6*/ + +class Foo { + [a]() {} + get [b]() {} + set [b](value) {} +} + +const Bar = class { + [a](){} + static [b]() {} + static get [c]() {} + static set [c](value) {} +} +``` ## When Not To Use It diff --git a/docs/rules/no-import-assign.md b/docs/rules/no-import-assign.md new file mode 100644 index 00000000000..78b228dd828 --- /dev/null +++ b/docs/rules/no-import-assign.md @@ -0,0 +1,44 @@ +# disallow assigning to imported bindings (no-import-assign) + +The updates of imported bindings by ES Modules cause runtime errors. + +## Rule Details + +This rule warns the assignments, increments, and decrements of imported bindings. + +Examples of **incorrect** code for this rule: + +```js +/*eslint no-import-assign: "error"*/ + +import mod, { named } from "./mod.mjs" +import * as mod_ns from "./mod.mjs" + +mod = 1 // ERROR: 'mod' is readonly. +named = 2 // ERROR: 'named' is readonly. +mod_ns.named = 3 // ERROR: the members of 'mod_ns' is readonly. +mod_ns = {} // ERROR: 'mod_ns' is readonly. +``` + +Examples of **correct** code for this rule: + +```js +/*eslint no-import-assign: "error"*/ + +import mod, { named } from "./mod.mjs" +import * as mod_ns from "./mod.mjs" + +mod.prop = 1 +named.prop = 2 +mod_ns.named.prop = 3 + +// Known Limitation +function test(obj) { + obj.named = 4 // Not errored because 'obj' is not namespace objects. +} +test(mod_ns) // Not errored because it doesn't know that 'test' updates the member of the argument. +``` + +## When Not To Use It + +If you don't want to be notified about modifying imported bindings, you can disable this rule. diff --git a/docs/rules/no-obj-calls.md b/docs/rules/no-obj-calls.md index 9484eb73688..cfd5576eae5 100644 --- a/docs/rules/no-obj-calls.md +++ b/docs/rules/no-obj-calls.md @@ -6,13 +6,17 @@ The [ECMAScript 5 specification](https://es5.github.io/#x15.8) makes it clear th > The Math object does not have a `[[Call]]` internal property; it is not possible to invoke the Math object as a function. -And the [ECMAScript 2015 specification](https://www.ecma-international.org/ecma-262/6.0/index.html#sec-reflect-object) makes it clear that `Reflect` cannot be invoked: +The [ECMAScript 2015 specification](https://www.ecma-international.org/ecma-262/6.0/index.html#sec-reflect-object) makes it clear that `Reflect` cannot be invoked: > The Reflect object also does not have a `[[Call]]` internal method; it is not possible to invoke the Reflect object as a function. +And the [ECMAScript 2017 specification](https://www.ecma-international.org/ecma-262/8.0/index.html#sec-atomics-object) makes it clear that `Atomics` cannot be invoked: + +> The Atomics object does not have a [[Call]] internal method; it is not possible to invoke the Atomics object as a function. + ## Rule Details -This rule disallows calling the `Math`, `JSON` and `Reflect` objects as functions. +This rule disallows calling the `Math`, `JSON`, `Reflect` and `Atomics` objects as functions. Examples of **incorrect** code for this rule: @@ -22,6 +26,7 @@ Examples of **incorrect** code for this rule: var math = Math(); var json = JSON(); var reflect = Reflect(); +var atomics = Atomics(); ``` Examples of **correct** code for this rule: @@ -34,6 +39,7 @@ function area(r) { } var object = JSON.parse("{}"); var value = Reflect.get({ x: 1, y: 2 }, "x"); +var first = Atomics.load(foo, 0); ``` ## Further Reading diff --git a/docs/rules/no-sequences.md b/docs/rules/no-sequences.md index f1f4afea0ac..602a412f16a 100644 --- a/docs/rules/no-sequences.md +++ b/docs/rules/no-sequences.md @@ -60,7 +60,7 @@ switch ((val = foo(), val)) {} while ((val = foo(), val < 42)); -// with ((doSomething(), val)) {} +with ((doSomething(), val)) {} ``` ## When Not To Use It diff --git a/docs/rules/no-useless-catch.md b/docs/rules/no-useless-catch.md index d320e561d07..0562063f634 100644 --- a/docs/rules/no-useless-catch.md +++ b/docs/rules/no-useless-catch.md @@ -43,6 +43,12 @@ try { } catch (e) { handleError(e); } + +try { + doSomethingThatMightThrow(); +} finally { + cleanUp(); +} ``` ## When Not To Use It diff --git a/docs/rules/operator-linebreak.md b/docs/rules/operator-linebreak.md index e2a69a1fdc6..3b1986e0fff 100644 --- a/docs/rules/operator-linebreak.md +++ b/docs/rules/operator-linebreak.md @@ -38,7 +38,7 @@ The default configuration is `"after", { "overrides": { "?": "before", ":": "bef ### after -Examples of **incorrect** code for this rule with the default `"after"` option: +Examples of **incorrect** code for this rule with the `"after"` option: ```js /*eslint operator-linebreak: ["error", "after"]*/ @@ -62,7 +62,7 @@ answer = everything : foo; ``` -Examples of **correct** code for this rule with the default `"after"` option: +Examples of **correct** code for this rule with the `"after"` option: ```js /*eslint operator-linebreak: ["error", "after"]*/ @@ -175,6 +175,16 @@ answer = everything ? 42 : foo; ### overrides +Examples of additional **incorrect** code for this rule with the `{ "overrides": { "+=": "before" } }` option: + +```js +/*eslint operator-linebreak: ["error", "after", { "overrides": { "+=": "before" } }]*/ + +var thing = 'thing'; +thing += + 's'; +``` + Examples of additional **correct** code for this rule with the `{ "overrides": { "+=": "before" } }` option: ```js @@ -201,6 +211,52 @@ answer = everything foo; ``` +Examples of **incorrect** code for this rule with the default `"after", { "overrides": { "?": "before", ":": "before" } }` option: + +```js +/*eslint operator-linebreak: ["error", "after", { "overrides": { "?": "before", ":": "before" } }]*/ + +foo = 1 ++ +2; + +foo = 1 + + 2; + +foo + = 5; + +if (someCondition + || otherCondition) { +} + +answer = everything ? + 42 : + foo; +``` + +Examples of **correct** code for this rule with the default `"after", { "overrides": { "?": "before", ":": "before" } }` option: + +```js +/*eslint operator-linebreak: ["error", "after", { "overrides": { "?": "before", ":": "before" } }]*/ + +foo = 1 + 2; + +foo = 1 + + 2; + +foo = + 5; + +if (someCondition || + otherCondition) { +} + +answer = everything + ? 42 + : foo; +``` + ## When Not To Use It If your project will not be using a common operator line break style, turn this rule off. diff --git a/docs/rules/prefer-regex-literals.md b/docs/rules/prefer-regex-literals.md new file mode 100644 index 00000000000..01d4149cf20 --- /dev/null +++ b/docs/rules/prefer-regex-literals.md @@ -0,0 +1,90 @@ +# Disallow use of the `RegExp` constructor in favor of regular expression literals (prefer-regex-literals) + +There are two ways to create a regular expression: + +* Regular expression literals, e.g., `/abc/u`. +* The `RegExp` constructor function, e.g., `new RegExp("abc", "u")` or `RegExp("abc", "u")`. + +The constructor function is particularly useful when you want to dynamically generate the pattern, +because it takes string arguments. + +When using the constructor function with string literals, don't forget that the string escaping rules still apply. +If you want to put a backslash in the pattern, you need to escape it in the string literal. +Thus, the following are equivalent: + +```js +new RegExp("^\\d\\.$"); + +/^\d\.$/; + +// matches "0.", "1.", "2." ... "9." +``` + +In the above example, the regular expression literal is easier to read and reason about. +Also, it's a common mistake to omit the extra `\` in the string literal, which would produce a completely different regular expression: + +```js +new RegExp("^\d\.$"); + +// equivalent to /^d.$/, matches "d1", "d2", "da", "db" ... +``` + +When a regular expression is known in advance, it is considered a best practice to avoid the string literal notation on top +of the regular expression notation, and use regular expression literals instead of the constructor function. + +## Rule Details + +This rule disallows the use of the `RegExp` constructor function with string literals as its arguments. + +This rule also disallows the use of the `RegExp` constructor function with template literals without expressions +and `String.raw` tagged template literals without expressions. + +The rule does not disallow all use of the `RegExp` constructor. It should be still used for +dynamically generated regular expressions. + +Examples of **incorrect** code for this rule: + +```js +new RegExp("abc"); + +new RegExp("abc", "u"); + +RegExp("abc"); + +RegExp("abc", "u"); + +new RegExp("\\d\\d\\.\\d\\d\\.\\d\\d\\d\\d"); + +RegExp(`^\\d\\.$`); + +new RegExp(String.raw`^\d\.$`); +``` + +Examples of **correct** code for this rule: + +```js +/abc/; + +/abc/u; + +/\d\d\.\d\d\.\d\d\d\d/; + +/^\d\.$/; + +// RegExp constructor is allowed for dynamically generated regular expressions + +new RegExp(pattern); + +RegExp("abc", flags); + +new RegExp(prefix + "abc"); + +RegExp(`${prefix}abc`); + +new RegExp(String.raw`^\d\. ${sufix}`); +``` + +## Further Reading + +* [MDN: Regular Expressions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions) +* [MDN: RegExp Constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp) diff --git a/docs/user-guide/configuring.md b/docs/user-guide/configuring.md index 3f46231fcf5..aca8b01cf3b 100644 --- a/docs/user-guide/configuring.md +++ b/docs/user-guide/configuring.md @@ -323,6 +323,71 @@ And in YAML: **Note:** Plugins are resolved relative to the current working directory of the ESLint process. In other words, ESLint will load the same plugin as a user would obtain by running `require('eslint-plugin-pluginname')` in a Node REPL from their project root. +### Naming Convention + +#### Include a Plugin + +The `eslint-plugin-` prefix can be omitted for non-scoped packages + +```js +{ + // ... + "plugins": [ + "jquery", // means eslint-plugin-jquery + ] + // ... +} +``` + +The same rule does apply to scoped packages: + +```js +{ + // ... + "plugins": [ + "@jquery/jquery", // means @jquery/eslint-plugin-jquery + "@foobar" // means @foobar/eslint-plugin + ] + // ... +} +``` + +#### Use a Plugin + +When using rules, environments or configs defined by plugins, they must be referenced following the convention: + +* `eslint-plugin-foo` → `foo/a-rule` +* `@foo/eslint-plugin` → `@foo/a-config` +* `@foo/eslint-plugin-bar` → `@foo/bar/a-environment` + +For example: + +```js +{ + // ... + "plugins": [ + "jquery", // eslint-plugin-jquery + "@foo/foo", // @foo/eslint-plugin-foo + "@bar" // @bar/eslint-plugin + ], + "extends": [ + "plugin:@foo/foo/recommended", + "plugin:@bar/recommended" + ], + "rules": [ + "jquery/a-rule": "error", + "@foo/foo/some-rule": "error", + "@bar/another-rule": "error" + ], + "env": { + "jquery/jquery": true, + "@foo/foo/env-foo": true, + "@bar/env-bar": true, + } + // ... +} +``` + ## Configuring Rules ESLint comes with a large number of rules. You can modify which rules your project uses either using configuration comments or configuration files. To change a rule setting, you must set the rule ID equal to one of these values: diff --git a/lib/rules/accessor-pairs.js b/lib/rules/accessor-pairs.js index 9c78bdc70e0..a33d1f32f2e 100644 --- a/lib/rules/accessor-pairs.js +++ b/lib/rules/accessor-pairs.js @@ -152,7 +152,7 @@ module.exports = { type: "suggestion", docs: { - description: "enforce getter and setter pairs in objects", + description: "enforce getter and setter pairs in objects and classes", category: "Best Practices", recommended: false, url: "https://eslint.org/docs/rules/accessor-pairs" @@ -168,6 +168,10 @@ module.exports = { setWithoutGet: { type: "boolean", default: true + }, + enforceForClassMembers: { + type: "boolean", + default: false } }, additionalProperties: false @@ -177,13 +181,16 @@ module.exports = { missingGetterInPropertyDescriptor: "Getter is not present in property descriptor.", missingSetterInPropertyDescriptor: "Setter is not present in property descriptor.", missingGetterInObjectLiteral: "Getter is not present for {{ name }}.", - missingSetterInObjectLiteral: "Setter is not present for {{ name }}." + missingSetterInObjectLiteral: "Setter is not present for {{ name }}.", + missingGetterInClass: "Getter is not present for class {{ name }}.", + missingSetterInClass: "Setter is not present for class {{ name }}." } }, create(context) { const config = context.options[0] || {}; const checkGetWithoutSet = config.getWithoutSet === true; const checkSetWithoutGet = config.setWithoutGet !== false; + const enforceForClassMembers = config.enforceForClassMembers === true; const sourceCode = context.getSourceCode(); /** @@ -201,6 +208,13 @@ module.exports = { loc: astUtils.getFunctionHeadLoc(node.value, sourceCode), data: { name: astUtils.getFunctionNameWithKind(node.value) } }); + } else if (node.type === "MethodDefinition") { + context.report({ + node, + messageId: `${messageKind}InClass`, + loc: astUtils.getFunctionHeadLoc(node.value, sourceCode), + data: { name: astUtils.getFunctionNameWithKind(node.value) } + }); } else { context.report({ node, @@ -313,15 +327,41 @@ module.exports = { } } - return { - ObjectExpression(node) { - if (checkSetWithoutGet || checkGetWithoutSet) { - checkObjectLiteral(node); - if (isPropertyDescriptor(node)) { - checkPropertyDescriptor(node); - } - } + /** + * Checks the given object expression as an object literal and as a possible property descriptor. + * @param {ASTNode} node `ObjectExpression` node to check. + * @returns {void} + * @private + */ + function checkObjectExpression(node) { + checkObjectLiteral(node); + if (isPropertyDescriptor(node)) { + checkPropertyDescriptor(node); } - }; + } + + /** + * Checks the given class body. + * @param {ASTNode} node `ClassBody` node to check. + * @returns {void} + * @private + */ + function checkClassBody(node) { + const methodDefinitions = node.body.filter(m => m.type === "MethodDefinition"); + + checkList(methodDefinitions.filter(m => m.static)); + checkList(methodDefinitions.filter(m => !m.static)); + } + + const listeners = {}; + + if (checkSetWithoutGet || checkGetWithoutSet) { + listeners.ObjectExpression = checkObjectExpression; + if (enforceForClassMembers) { + listeners.ClassBody = checkClassBody; + } + } + + return listeners; } }; diff --git a/lib/rules/capitalized-comments.js b/lib/rules/capitalized-comments.js index 47477743598..dd7ef145648 100644 --- a/lib/rules/capitalized-comments.js +++ b/lib/rules/capitalized-comments.js @@ -59,7 +59,7 @@ const DEFAULTS = { * @param {string} which Either "line" or "block". * @returns {Object} The normalized options. */ -function getNormalizedOptions(rawOptions = {}, which) { +function getNormalizedOptions(rawOptions, which) { return Object.assign({}, DEFAULTS, rawOptions[which] || rawOptions); } @@ -70,7 +70,7 @@ function getNormalizedOptions(rawOptions = {}, which) { * @returns {Object} An object with "Line" and "Block" keys and corresponding * normalized options objects. */ -function getAllNormalizedOptions(rawOptions) { +function getAllNormalizedOptions(rawOptions = {}) { return { Line: getNormalizedOptions(rawOptions, "line"), Block: getNormalizedOptions(rawOptions, "block") diff --git a/lib/rules/computed-property-spacing.js b/lib/rules/computed-property-spacing.js index 91b7d28963f..33f7c9401a9 100644 --- a/lib/rules/computed-property-spacing.js +++ b/lib/rules/computed-property-spacing.js @@ -26,6 +26,16 @@ module.exports = { schema: [ { enum: ["always", "never"] + }, + { + type: "object", + properties: { + enforceForClassMembers: { + type: "boolean", + default: false + } + }, + additionalProperties: false } ], @@ -41,6 +51,7 @@ module.exports = { create(context) { const sourceCode = context.getSourceCode(); const propertyNameMustBeSpaced = context.options[0] === "always"; // default is "never" + const enforceForClassMembers = context.options[1] && context.options[1].enforceForClassMembers; //-------------------------------------------------------------------------- // Helpers @@ -178,10 +189,16 @@ module.exports = { // Public //-------------------------------------------------------------------------- - return { + const listeners = { Property: checkSpacing("key"), MemberExpression: checkSpacing("property") }; + if (enforceForClassMembers) { + listeners.MethodDefinition = checkSpacing("key"); + } + + return listeners; + } }; diff --git a/lib/rules/eqeqeq.js b/lib/rules/eqeqeq.js index 58ff9030dbb..57926dbed0e 100644 --- a/lib/rules/eqeqeq.js +++ b/lib/rules/eqeqeq.js @@ -116,18 +116,6 @@ module.exports = { return astUtils.isNullLiteral(node.right) || astUtils.isNullLiteral(node.left); } - /** - * Gets the location (line and column) of the binary expression's operator - * @param {ASTNode} node The binary expression node to check - * @returns {Object} { line, column } location of operator - * @private - */ - function getOperatorLocation(node) { - const opToken = sourceCode.getTokenAfter(node.left); - - return { line: opToken.loc.start.line, column: opToken.loc.start.column }; - } - /** * Reports a message for this rule. * @param {ASTNode} node The binary expression node that was checked @@ -136,21 +124,21 @@ module.exports = { * @private */ function report(node, expectedOperator) { + const operatorToken = sourceCode.getFirstTokenBetween( + node.left, + node.right, + token => token.value === node.operator + ); + context.report({ node, - loc: getOperatorLocation(node), + loc: operatorToken.loc, messageId: "unexpected", data: { expectedOperator, actualOperator: node.operator }, fix(fixer) { // If the comparison is a `typeof` comparison or both sides are literals with the same type, then it's safe to fix. if (isTypeOfBinary(node) || areLiteralsAndSameType(node)) { - const operatorToken = sourceCode.getFirstTokenBetween( - node.left, - node.right, - token => token.value === node.operator - ); - return fixer.replaceText(operatorToken, expectedOperator); } return null; diff --git a/lib/rules/indent.js b/lib/rules/indent.js index 79b1063137e..f44eafa715c 100644 --- a/lib/rules/indent.js +++ b/lib/rules/indent.js @@ -1588,18 +1588,23 @@ module.exports = { return; } - // If the token matches the expected expected indentation, don't report it. - if (validateTokenIndent(firstTokenOfLine, offsets.getDesiredIndent(firstTokenOfLine))) { - return; - } - if (astUtils.isCommentToken(firstTokenOfLine)) { const tokenBefore = precedingTokens.get(firstTokenOfLine); const tokenAfter = tokenBefore ? sourceCode.getTokenAfter(tokenBefore) : sourceCode.ast.tokens[0]; - const mayAlignWithBefore = tokenBefore && !hasBlankLinesBetween(tokenBefore, firstTokenOfLine); const mayAlignWithAfter = tokenAfter && !hasBlankLinesBetween(firstTokenOfLine, tokenAfter); + /* + * If a comment precedes a line that begins with a semicolon token, align to that token, i.e. + * + * let foo + * // comment + * ;(async () => {})() + */ + if (tokenAfter && astUtils.isSemicolonToken(tokenAfter) && !astUtils.isTokenOnSameLine(firstTokenOfLine, tokenAfter)) { + offsets.setDesiredOffset(firstTokenOfLine, tokenAfter, 0); + } + // If a comment matches the expected indentation of the token immediately before or after, don't report it. if ( mayAlignWithBefore && validateTokenIndent(firstTokenOfLine, offsets.getDesiredIndent(tokenBefore)) || @@ -1609,6 +1614,11 @@ module.exports = { } } + // If the token matches the expected indentation, don't report it. + if (validateTokenIndent(firstTokenOfLine, offsets.getDesiredIndent(firstTokenOfLine))) { + return; + } + // Otherwise, report the token/comment. report(firstTokenOfLine, offsets.getDesiredIndent(firstTokenOfLine)); }); diff --git a/lib/rules/index.js b/lib/rules/index.js index 51d224d219f..8b0abc4ee7a 100644 --- a/lib/rules/index.js +++ b/lib/rules/index.js @@ -132,6 +132,7 @@ module.exports = new LazyLoadingRuleMap(Object.entries({ "no-implicit-coercion": () => require("./no-implicit-coercion"), "no-implicit-globals": () => require("./no-implicit-globals"), "no-implied-eval": () => require("./no-implied-eval"), + "no-import-assign": () => require("./no-import-assign"), "no-inline-comments": () => require("./no-inline-comments"), "no-inner-declarations": () => require("./no-inner-declarations"), "no-invalid-regexp": () => require("./no-invalid-regexp"), @@ -242,6 +243,7 @@ module.exports = new LazyLoadingRuleMap(Object.entries({ "prefer-object-spread": () => require("./prefer-object-spread"), "prefer-promise-reject-errors": () => require("./prefer-promise-reject-errors"), "prefer-reflect": () => require("./prefer-reflect"), + "prefer-regex-literals": () => require("./prefer-regex-literals"), "prefer-rest-params": () => require("./prefer-rest-params"), "prefer-spread": () => require("./prefer-spread"), "prefer-template": () => require("./prefer-template"), diff --git a/lib/rules/no-import-assign.js b/lib/rules/no-import-assign.js new file mode 100644 index 00000000000..0865cf9a977 --- /dev/null +++ b/lib/rules/no-import-assign.js @@ -0,0 +1,238 @@ +/** + * @fileoverview Rule to flag updates of imported bindings. + * @author Toru Nagashima + */ + +"use strict"; + +//------------------------------------------------------------------------------ +// Helpers +//------------------------------------------------------------------------------ + +const { findVariable, getPropertyName } = require("eslint-utils"); + +const MutationMethods = { + Object: new Set([ + "assign", "defineProperties", "defineProperty", "freeze", + "setPrototypeOf" + ]), + Reflect: new Set([ + "defineProperty", "deleteProperty", "set", "setPrototypeOf" + ]) +}; + +/** + * Check if a given node is LHS of an assignment node. + * @param {ASTNode} node The node to check. + * @returns {boolean} `true` if the node is LHS. + */ +function isAssignmentLeft(node) { + const { parent } = node; + + return ( + ( + parent.type === "AssignmentExpression" && + parent.left === node + ) || + + // Destructuring assignments + parent.type === "ArrayPattern" || + ( + parent.type === "Property" && + parent.value === node && + parent.parent.type === "ObjectPattern" + ) || + parent.type === "RestElement" || + ( + parent.type === "AssignmentPattern" && + parent.left === node + ) + ); +} + +/** + * Check if a given node is the operand of mutation unary operator. + * @param {ASTNode} node The node to check. + * @returns {boolean} `true` if the node is the operand of mutation unary operator. + */ +function isOperandOfMutationUnaryOperator(node) { + const { parent } = node; + + return ( + ( + parent.type === "UpdateExpression" && + parent.argument === node + ) || + ( + parent.type === "UnaryExpression" && + parent.operator === "delete" && + parent.argument === node + ) + ); +} + +/** + * Check if a given node is the iteration variable of `for-in`/`for-of` syntax. + * @param {ASTNode} node The node to check. + * @returns {boolean} `true` if the node is the iteration variable. + */ +function isIterationVariable(node) { + const { parent } = node; + + return ( + ( + parent.type === "ForInStatement" && + parent.left === node + ) || + ( + parent.type === "ForOfStatement" && + parent.left === node + ) + ); +} + +/** + * Check if a given node is the iteration variable of `for-in`/`for-of` syntax. + * @param {ASTNode} node The node to check. + * @param {Scope} scope A `escope.Scope` object to find variable (whichever). + * @returns {boolean} `true` if the node is the iteration variable. + */ +function isArgumentOfWellKnownMutationFunction(node, scope) { + const { parent } = node; + + if ( + parent.type === "CallExpression" && + parent.arguments[0] === node && + parent.callee.type === "MemberExpression" && + parent.callee.object.type === "Identifier" + ) { + const { callee } = parent; + const { object } = callee; + + if (Object.keys(MutationMethods).includes(object.name)) { + const variable = findVariable(scope, object); + + return ( + variable !== null && + variable.scope.type === "global" && + MutationMethods[object.name].has(getPropertyName(callee, scope)) + ); + } + } + + return false; +} + +/** + * Check if the identifier node is placed at to update members. + * @param {ASTNode} id The Identifier node to check. + * @param {Scope} scope A `escope.Scope` object to find variable (whichever). + * @returns {boolean} `true` if the member of `id` was updated. + */ +function isMemberWrite(id, scope) { + const { parent } = id; + + return ( + ( + parent.type === "MemberExpression" && + parent.object === id && + ( + isAssignmentLeft(parent) || + isOperandOfMutationUnaryOperator(parent) || + isIterationVariable(parent) + ) + ) || + isArgumentOfWellKnownMutationFunction(id, scope) + ); +} + +/** + * Get the mutation node. + * @param {ASTNode} id The Identifier node to get. + * @returns {ASTNode} The mutation node. + */ +function getWriteNode(id) { + let node = id.parent; + + while ( + node && + node.type !== "AssignmentExpression" && + node.type !== "UpdateExpression" && + node.type !== "UnaryExpression" && + node.type !== "CallExpression" && + node.type !== "ForInStatement" && + node.type !== "ForOfStatement" + ) { + node = node.parent; + } + + return node || id; +} + +//------------------------------------------------------------------------------ +// Rule Definition +//------------------------------------------------------------------------------ + +module.exports = { + meta: { + type: "problem", + + docs: { + description: "disallow assigning to imported bindings", + category: "Possible Errors", + recommended: false, + url: "https://eslint.org/docs/rules/no-import-assign" + }, + + schema: [], + + messages: { + readonly: "'{{name}}' is read-only.", + readonlyMember: "The members of '{{name}}' are read-only." + } + }, + + create(context) { + return { + ImportDeclaration(node) { + const scope = context.getScope(); + + for (const variable of context.getDeclaredVariables(node)) { + const shouldCheckMembers = variable.defs.some( + d => d.node.type === "ImportNamespaceSpecifier" + ); + let prevIdNode = null; + + for (const reference of variable.references) { + const idNode = reference.identifier; + + /* + * AssignmentPattern (e.g. `[a = 0] = b`) makes two write + * references for the same identifier. This should skip + * the one of the two in order to prevent redundant reports. + */ + if (idNode === prevIdNode) { + continue; + } + prevIdNode = idNode; + + if (reference.isWrite()) { + context.report({ + node: getWriteNode(idNode), + messageId: "readonly", + data: { name: idNode.name } + }); + } else if (shouldCheckMembers && isMemberWrite(idNode, scope)) { + context.report({ + node: getWriteNode(idNode), + messageId: "readonlyMember", + data: { name: idNode.name } + }); + } + } + } + } + }; + + } +}; diff --git a/lib/rules/no-lone-blocks.js b/lib/rules/no-lone-blocks.js index 6b51795863b..4365b047861 100644 --- a/lib/rules/no-lone-blocks.js +++ b/lib/rules/no-lone-blocks.js @@ -79,7 +79,7 @@ module.exports = { } }; - // ES6: report blocks without block-level bindings + // ES6: report blocks without block-level bindings, or that's only child of another block if (context.parserOptions.ecmaVersion >= 6) { ruleDef = { BlockStatement(node) { @@ -91,6 +91,11 @@ module.exports = { if (loneBlocks.length > 0 && loneBlocks[loneBlocks.length - 1] === node) { loneBlocks.pop(); report(node); + } else if ( + node.parent.type === "BlockStatement" && + node.parent.body.length === 1 + ) { + report(node); } } }; diff --git a/lib/rules/no-obj-calls.js b/lib/rules/no-obj-calls.js index 92492b7a26e..5102d559494 100644 --- a/lib/rules/no-obj-calls.js +++ b/lib/rules/no-obj-calls.js @@ -5,6 +5,18 @@ "use strict"; +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const { CALL, ReferenceTracker } = require("eslint-utils"); + +//------------------------------------------------------------------------------ +// Helpers +//------------------------------------------------------------------------------ + +const nonCallableGlobals = ["Atomics", "JSON", "Math", "Reflect"]; + //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ @@ -20,23 +32,31 @@ module.exports = { url: "https://eslint.org/docs/rules/no-obj-calls" }, - schema: [] + schema: [], + + messages: { + unexpectedCall: "'{{name}}' is not a function." + } }, create(context) { return { - CallExpression(node) { - - if (node.callee.type === "Identifier") { - const name = node.callee.name; + Program() { + const scope = context.getScope(); + const tracker = new ReferenceTracker(scope); + const traceMap = {}; + + for (const global of nonCallableGlobals) { + traceMap[global] = { + [CALL]: true + }; + } - if (name === "Math" || name === "JSON" || name === "Reflect") { - context.report({ node, message: "'{{name}}' is not a function.", data: { name } }); - } + for (const { node } of tracker.iterateGlobalReferences(traceMap)) { + context.report({ node, messageId: "unexpectedCall", data: { name: node.callee.name } }); } } }; - } }; diff --git a/lib/rules/no-octal-escape.js b/lib/rules/no-octal-escape.js index a2860ca5bf8..7f6845ec70f 100644 --- a/lib/rules/no-octal-escape.js +++ b/lib/rules/no-octal-escape.js @@ -20,7 +20,11 @@ module.exports = { url: "https://eslint.org/docs/rules/no-octal-escape" }, - schema: [] + schema: [], + + messages: { + octalEscapeSequence: "Don't use octal: '\\{{sequence}}'. Use '\\u....' instead." + } }, create(context) { @@ -32,15 +36,17 @@ module.exports = { return; } - const match = node.raw.match(/^([^\\]|\\[^0-7])*\\([0-3][0-7]{1,2}|[4-7][0-7]|[0-7])/u); + // \0 represents a valid NULL character if it isn't followed by a digit. + const match = node.raw.match( + /^(?:[^\\]|\\.)*?\\([0-3][0-7]{1,2}|[4-7][0-7]|[1-7])/u + ); if (match) { - const octalDigit = match[2]; - - // \0 is actually not considered an octal - if (match[2] !== "0" || typeof match[3] !== "undefined") { - context.report({ node, message: "Don't use octal: '\\{{octalDigit}}'. Use '\\u....' instead.", data: { octalDigit } }); - } + context.report({ + node, + messageId: "octalEscapeSequence", + data: { sequence: match[1] } + }); } } diff --git a/lib/rules/no-self-assign.js b/lib/rules/no-self-assign.js index dc8bf90147b..6ebd1925e49 100644 --- a/lib/rules/no-self-assign.js +++ b/lib/rules/no-self-assign.js @@ -152,13 +152,14 @@ function eachSelfAssignment(left, right, props, report) { } else if ( left.type === "Property" && right.type === "Property" && - !left.computed && - !right.computed && right.kind === "init" && - !right.method && - left.key.name === right.key.name + !right.method ) { - eachSelfAssignment(left.value, right.value, props, report); + const leftName = astUtils.getStaticPropertyName(left); + + if (leftName !== null && leftName === astUtils.getStaticPropertyName(right)) { + eachSelfAssignment(left.value, right.value, props, report); + } } else if ( props && left.type === "MemberExpression" && diff --git a/lib/rules/no-sequences.js b/lib/rules/no-sequences.js index 71317c2f792..39d147b69be 100644 --- a/lib/rules/no-sequences.js +++ b/lib/rules/no-sequences.js @@ -105,9 +105,9 @@ module.exports = { } } - const child = sourceCode.getTokenAfter(node.expressions[0]); + const firstCommaToken = sourceCode.getTokenAfter(node.expressions[0], astUtils.isCommaToken); - context.report({ node, loc: child.loc.start, message: "Unexpected use of comma operator." }); + context.report({ node, loc: firstCommaToken.loc, message: "Unexpected use of comma operator." }); } }; diff --git a/lib/rules/no-unsafe-negation.js b/lib/rules/no-unsafe-negation.js index f394f674259..717e5f6be39 100644 --- a/lib/rules/no-unsafe-negation.js +++ b/lib/rules/no-unsafe-negation.js @@ -51,7 +51,7 @@ module.exports = { }, schema: [], - fixable: "code", + fixable: null, messages: { unexpected: "Unexpected negating the left operand of '{{operator}}' operator." } @@ -70,15 +70,7 @@ module.exports = { node, loc: node.left.loc, messageId: "unexpected", - data: { operator: node.operator }, - - fix(fixer) { - const negationToken = sourceCode.getFirstToken(node.left); - const fixRange = [negationToken.range[1], node.range[1]]; - const text = sourceCode.text.slice(fixRange[0], fixRange[1]); - - return fixer.replaceTextRange(fixRange, `(${text})`); - } + data: { operator: node.operator } }); } } diff --git a/lib/rules/object-curly-spacing.js b/lib/rules/object-curly-spacing.js index 079cf5707db..48a7dd953b7 100644 --- a/lib/rules/object-curly-spacing.js +++ b/lib/rules/object-curly-spacing.js @@ -167,7 +167,7 @@ module.exports = { if (options.spaced && !firstSpaced) { reportRequiredBeginningSpace(node, first); } - if (!options.spaced && firstSpaced) { + if (!options.spaced && firstSpaced && second.type !== "Line") { reportNoBeginningSpace(node, first); } } diff --git a/lib/rules/object-shorthand.js b/lib/rules/object-shorthand.js index bff7c717a0d..df302b5e872 100644 --- a/lib/rules/object-shorthand.js +++ b/lib/rules/object-shorthand.js @@ -244,6 +244,7 @@ module.exports = { const keyText = sourceCode.text.slice(firstKeyToken.range[0], lastKeyToken.range[1]); let keyPrefix = ""; + // key: /* */ () => {} if (sourceCode.commentsExistBetween(lastKeyToken, node.value)) { return null; } @@ -255,24 +256,49 @@ module.exports = { keyPrefix += "*"; } + const fixRange = [firstKeyToken.range[0], node.range[1]]; + const methodPrefix = keyPrefix + keyText; + if (node.value.type === "FunctionExpression") { const functionToken = sourceCode.getTokens(node.value).find(token => token.type === "Keyword" && token.value === "function"); const tokenBeforeParams = node.value.generator ? sourceCode.getTokenAfter(functionToken) : functionToken; return fixer.replaceTextRange( - [firstKeyToken.range[0], node.range[1]], - keyPrefix + keyText + sourceCode.text.slice(tokenBeforeParams.range[1], node.value.range[1]) + fixRange, + methodPrefix + sourceCode.text.slice(tokenBeforeParams.range[1], node.value.range[1]) ); } - const arrowToken = sourceCode.getTokenBefore(node.value.body, { filter: token => token.value === "=>" }); - const tokenBeforeArrow = sourceCode.getTokenBefore(arrowToken); - const hasParensAroundParameters = tokenBeforeArrow.type === "Punctuator" && tokenBeforeArrow.value === ")"; - const oldParamText = sourceCode.text.slice(sourceCode.getFirstToken(node.value, node.value.async ? 1 : 0).range[0], tokenBeforeArrow.range[1]); - const newParamText = hasParensAroundParameters ? oldParamText : `(${oldParamText})`; + + const arrowToken = sourceCode.getTokenBefore(node.value.body, astUtils.isArrowToken); + const fnBody = sourceCode.text.slice(arrowToken.range[1], node.value.range[1]); + + let shouldAddParensAroundParameters = false; + let tokenBeforeParams; + + if (node.value.params.length === 0) { + tokenBeforeParams = sourceCode.getFirstToken(node.value, astUtils.isOpeningParenToken); + } else { + tokenBeforeParams = sourceCode.getTokenBefore(node.value.params[0]); + } + + if (node.value.params.length === 1) { + const hasParen = astUtils.isOpeningParenToken(tokenBeforeParams); + const isTokenOutsideNode = tokenBeforeParams.range[0] < node.range[0]; + + shouldAddParensAroundParameters = !hasParen || isTokenOutsideNode; + } + + const sliceStart = shouldAddParensAroundParameters + ? node.value.params[0].range[0] + : tokenBeforeParams.range[0]; + const sliceEnd = sourceCode.getTokenBefore(arrowToken).range[1]; + + const oldParamText = sourceCode.text.slice(sliceStart, sliceEnd); + const newParamText = shouldAddParensAroundParameters ? `(${oldParamText})` : oldParamText; return fixer.replaceTextRange( - [firstKeyToken.range[0], node.range[1]], - keyPrefix + keyText + newParamText + sourceCode.text.slice(arrowToken.range[1], node.value.range[1]) + fixRange, + methodPrefix + newParamText + fnBody ); } diff --git a/lib/rules/prefer-regex-literals.js b/lib/rules/prefer-regex-literals.js new file mode 100644 index 00000000000..47b2b090f82 --- /dev/null +++ b/lib/rules/prefer-regex-literals.js @@ -0,0 +1,125 @@ +/** + * @fileoverview Rule to disallow use of the `RegExp` constructor in favor of regular expression literals + * @author Milos Djermanovic + */ + +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const astUtils = require("./utils/ast-utils"); +const { CALL, CONSTRUCT, ReferenceTracker, findVariable } = require("eslint-utils"); + +//------------------------------------------------------------------------------ +// Helpers +//------------------------------------------------------------------------------ + +/** + * Determines whether the given node is a string literal. + * @param {ASTNode} node Node to check. + * @returns {boolean} True if the node is a string literal. + */ +function isStringLiteral(node) { + return node.type === "Literal" && typeof node.value === "string"; +} + +/** + * Determines whether the given node is a template literal without expressions. + * @param {ASTNode} node Node to check. + * @returns {boolean} True if the node is a template literal without expressions. + */ +function isStaticTemplateLiteral(node) { + return node.type === "TemplateLiteral" && node.expressions.length === 0; +} + + +//------------------------------------------------------------------------------ +// Rule Definition +//------------------------------------------------------------------------------ + +module.exports = { + meta: { + type: "suggestion", + + docs: { + description: "disallow use of the `RegExp` constructor in favor of regular expression literals", + category: "Best Practices", + recommended: false, + url: "https://eslint.org/docs/rules/prefer-regex-literals" + }, + + schema: [], + + messages: { + unexpectedRegExp: "Use a regular expression literal instead of the 'RegExp' constructor." + } + }, + + create(context) { + + /** + * Determines whether the given identifier node is a reference to a global variable. + * @param {ASTNode} node `Identifier` node to check. + * @returns {boolean} True if the identifier is a reference to a global variable. + */ + function isGlobalReference(node) { + const scope = context.getScope(); + const variable = findVariable(scope, node); + + return variable !== null && variable.scope.type === "global" && variable.defs.length === 0; + } + + /** + * Determines whether the given node is a String.raw`` tagged template expression + * with a static template literal. + * @param {ASTNode} node Node to check. + * @returns {boolean} True if the node is String.raw`` with a static template. + */ + function isStringRawTaggedStaticTemplateLiteral(node) { + return node.type === "TaggedTemplateExpression" && + node.tag.type === "MemberExpression" && + node.tag.object.type === "Identifier" && + node.tag.object.name === "String" && + isGlobalReference(node.tag.object) && + astUtils.getStaticPropertyName(node.tag) === "raw" && + isStaticTemplateLiteral(node.quasi); + } + + /** + * Determines whether the given node is considered to be a static string by the logic of this rule. + * @param {ASTNode} node Node to check. + * @returns {boolean} True if the node is a static string. + */ + function isStaticString(node) { + return isStringLiteral(node) || + isStaticTemplateLiteral(node) || + isStringRawTaggedStaticTemplateLiteral(node); + } + + return { + Program() { + const scope = context.getScope(); + const tracker = new ReferenceTracker(scope); + const traceMap = { + RegExp: { + [CALL]: true, + [CONSTRUCT]: true + } + }; + + for (const { node } of tracker.iterateGlobalReferences(traceMap)) { + const args = node.arguments; + + if ( + (args.length === 1 || args.length === 2) && + args.every(isStaticString) + ) { + context.report({ node, messageId: "unexpectedRegExp" }); + } + } + } + }; + } +}; diff --git a/lib/rules/space-before-function-paren.js b/lib/rules/space-before-function-paren.js index ca20dbc4abf..3a6d430f362 100644 --- a/lib/rules/space-before-function-paren.js +++ b/lib/rules/space-before-function-paren.js @@ -124,7 +124,18 @@ module.exports = { node, loc: leftToken.loc.end, message: "Unexpected space before function parentheses.", - fix: fixer => fixer.removeRange([leftToken.range[1], rightToken.range[0]]) + fix(fixer) { + const comments = sourceCode.getCommentsBefore(rightToken); + + // Don't fix anything if there's a single line comment between the left and the right token + if (comments.some(comment => comment.type === "Line")) { + return null; + } + return fixer.replaceTextRange( + [leftToken.range[1], rightToken.range[0]], + comments.reduce((text, comment) => text + sourceCode.getText(comment), "") + ); + } }); } else if (!hasSpacing && functionConfig === "always") { context.report({ diff --git a/package.json b/package.json index b1490aeed39..9ce1c59b0d9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "eslint", - "version": "6.3.0", + "version": "6.4.0", "author": "Nicholas C. Zakas ", "description": "An AST-based pattern checker for JavaScript.", "bin": { diff --git a/packages/eslint-config-eslint/default.yml b/packages/eslint-config-eslint/default.yml index 8e8c8c57ad6..526ce5600ef 100644 --- a/packages/eslint-config-eslint/default.yml +++ b/packages/eslint-config-eslint/default.yml @@ -20,6 +20,7 @@ rules: consistent-return: "error" curly: ["error", "all"] default-case: "error" + default-param-last: "error" dot-location: ["error", "property"] dot-notation: ["error", { allowKeywords: true }] eol-last: "error" diff --git a/tests/fixtures/parsers/typescript-parsers/object-with-arrow-fn-props.js b/tests/fixtures/parsers/typescript-parsers/object-with-arrow-fn-props.js new file mode 100644 index 00000000000..9177aa46717 --- /dev/null +++ b/tests/fixtures/parsers/typescript-parsers/object-with-arrow-fn-props.js @@ -0,0 +1,8935 @@ +'use strict'; + +/* + * Parsed on astexplorer.net using @typescript-eslint/parser@1.13.0 + * + * Source: +const test = { + key: (): void => {x()}, + key: ( (): void => {x()} ), + key: ( (): (void) => {x()} ), + + key: (arg: t): void => {x()}, + key: ( (arg: t): void => {x()} ), + key: ( (arg: t): (void) => {x()} ), + + key: (arg: t, arg2: t): void => {x()}, + key: ( (arg: t, arg2: t): void => {x()} ), + key: ( (arg: t, arg2: t): (void) => {x()} ), + + key: async (): void => {x()}, + key: ( async (): void => {x()} ), + key: ( async (): (void) => {x()} ), + + key: async (arg: t): void => {x()}, + key: ( async (arg: t): void => {x()} ), + key: ( async (arg: t): (void) => {x()} ), + + key: async (arg: t, arg2: t): void => {x()}, + key: ( async (arg: t, arg2: t): void => {x()} ), + key: ( async (arg: t, arg2: t): (void) => {x()} ), +} + */ + +exports.parse = () => ({ + type: 'Program', + body: [ + { + type: 'VariableDeclaration', + declarations: [ + { + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'test', + range: [6, 10], + loc: { + start: { + line: 1, + column: 6, + }, + end: { + line: 1, + column: 10, + }, + }, + }, + init: { + type: 'ObjectExpression', + properties: [ + { + type: 'Property', + key: { + type: 'Identifier', + name: 'key', + range: [19, 22], + loc: { + start: { + line: 2, + column: 4, + }, + end: { + line: 2, + column: 7, + }, + }, + }, + value: { + type: 'ArrowFunctionExpression', + generator: false, + id: null, + params: [], + body: { + type: 'BlockStatement', + body: [ + { + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'x', + range: [37, 38], + loc: { + start: { + line: 2, + column: 22, + }, + end: { + line: 2, + column: 23, + }, + }, + }, + arguments: [], + range: [37, 40], + loc: { + start: { + line: 2, + column: 22, + }, + end: { + line: 2, + column: 25, + }, + }, + }, + range: [37, 40], + loc: { + start: { + line: 2, + column: 22, + }, + end: { + line: 2, + column: 25, + }, + }, + }, + ], + range: [36, 41], + loc: { + start: { + line: 2, + column: 21, + }, + end: { + line: 2, + column: 26, + }, + }, + }, + async: false, + expression: false, + range: [24, 41], + loc: { + start: { + line: 2, + column: 9, + }, + end: { + line: 2, + column: 26, + }, + }, + returnType: { + type: 'TSTypeAnnotation', + loc: { + start: { + line: 2, + column: 11, + }, + end: { + line: 2, + column: 17, + }, + }, + range: [26, 32], + typeAnnotation: { + type: 'TSVoidKeyword', + range: [28, 32], + loc: { + start: { + line: 2, + column: 13, + }, + end: { + line: 2, + column: 17, + }, + }, + }, + }, + }, + computed: false, + method: false, + shorthand: false, + kind: 'init', + range: [19, 41], + loc: { + start: { + line: 2, + column: 4, + }, + end: { + line: 2, + column: 26, + }, + }, + }, + { + type: 'Property', + key: { + type: 'Identifier', + name: 'key', + range: [47, 50], + loc: { + start: { + line: 3, + column: 4, + }, + end: { + line: 3, + column: 7, + }, + }, + }, + value: { + type: 'ArrowFunctionExpression', + generator: false, + id: null, + params: [], + body: { + type: 'BlockStatement', + body: [ + { + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'x', + range: [67, 68], + loc: { + start: { + line: 3, + column: 24, + }, + end: { + line: 3, + column: 25, + }, + }, + }, + arguments: [], + range: [67, 70], + loc: { + start: { + line: 3, + column: 24, + }, + end: { + line: 3, + column: 27, + }, + }, + }, + range: [67, 70], + loc: { + start: { + line: 3, + column: 24, + }, + end: { + line: 3, + column: 27, + }, + }, + }, + ], + range: [66, 71], + loc: { + start: { + line: 3, + column: 23, + }, + end: { + line: 3, + column: 28, + }, + }, + }, + async: false, + expression: false, + range: [54, 71], + loc: { + start: { + line: 3, + column: 11, + }, + end: { + line: 3, + column: 28, + }, + }, + returnType: { + type: 'TSTypeAnnotation', + loc: { + start: { + line: 3, + column: 13, + }, + end: { + line: 3, + column: 19, + }, + }, + range: [56, 62], + typeAnnotation: { + type: 'TSVoidKeyword', + range: [58, 62], + loc: { + start: { + line: 3, + column: 15, + }, + end: { + line: 3, + column: 19, + }, + }, + }, + }, + }, + computed: false, + method: false, + shorthand: false, + kind: 'init', + range: [47, 73], + loc: { + start: { + line: 3, + column: 4, + }, + end: { + line: 3, + column: 30, + }, + }, + }, + { + type: 'Property', + key: { + type: 'Identifier', + name: 'key', + range: [79, 82], + loc: { + start: { + line: 4, + column: 4, + }, + end: { + line: 4, + column: 7, + }, + }, + }, + value: { + type: 'ArrowFunctionExpression', + generator: false, + id: null, + params: [], + body: { + type: 'BlockStatement', + body: [ + { + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'x', + range: [101, 102], + loc: { + start: { + line: 4, + column: 26, + }, + end: { + line: 4, + column: 27, + }, + }, + }, + arguments: [], + range: [101, 104], + loc: { + start: { + line: 4, + column: 26, + }, + end: { + line: 4, + column: 29, + }, + }, + }, + range: [101, 104], + loc: { + start: { + line: 4, + column: 26, + }, + end: { + line: 4, + column: 29, + }, + }, + }, + ], + range: [100, 105], + loc: { + start: { + line: 4, + column: 25, + }, + end: { + line: 4, + column: 30, + }, + }, + }, + async: false, + expression: false, + range: [86, 105], + loc: { + start: { + line: 4, + column: 11, + }, + end: { + line: 4, + column: 30, + }, + }, + returnType: { + type: 'TSTypeAnnotation', + loc: { + start: { + line: 4, + column: 13, + }, + end: { + line: 4, + column: 21, + }, + }, + range: [88, 96], + typeAnnotation: { + type: 'TSParenthesizedType', + typeAnnotation: { + type: 'TSVoidKeyword', + range: [91, 95], + loc: { + start: { + line: 4, + column: 16, + }, + end: { + line: 4, + column: 20, + }, + }, + }, + range: [90, 96], + loc: { + start: { + line: 4, + column: 15, + }, + end: { + line: 4, + column: 21, + }, + }, + }, + }, + }, + computed: false, + method: false, + shorthand: false, + kind: 'init', + range: [79, 107], + loc: { + start: { + line: 4, + column: 4, + }, + end: { + line: 4, + column: 32, + }, + }, + }, + { + type: 'Property', + key: { + type: 'Identifier', + name: 'key', + range: [114, 117], + loc: { + start: { + line: 6, + column: 4, + }, + end: { + line: 6, + column: 7, + }, + }, + }, + value: { + type: 'ArrowFunctionExpression', + generator: false, + id: null, + params: [ + { + type: 'Identifier', + name: 'arg', + range: [120, 126], + loc: { + start: { + line: 6, + column: 10, + }, + end: { + line: 6, + column: 16, + }, + }, + typeAnnotation: { + type: 'TSTypeAnnotation', + loc: { + start: { + line: 6, + column: 13, + }, + end: { + line: 6, + column: 16, + }, + }, + range: [123, 126], + typeAnnotation: { + type: 'TSTypeReference', + typeName: { + type: 'Identifier', + name: 't', + range: [125, 126], + loc: { + start: { + line: 6, + column: 15, + }, + end: { + line: 6, + column: 16, + }, + }, + }, + range: [125, 126], + loc: { + start: { + line: 6, + column: 15, + }, + end: { + line: 6, + column: 16, + }, + }, + }, + }, + }, + ], + body: { + type: 'BlockStatement', + body: [ + { + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'x', + range: [138, 139], + loc: { + start: { + line: 6, + column: 28, + }, + end: { + line: 6, + column: 29, + }, + }, + }, + arguments: [], + range: [138, 141], + loc: { + start: { + line: 6, + column: 28, + }, + end: { + line: 6, + column: 31, + }, + }, + }, + range: [138, 141], + loc: { + start: { + line: 6, + column: 28, + }, + end: { + line: 6, + column: 31, + }, + }, + }, + ], + range: [137, 142], + loc: { + start: { + line: 6, + column: 27, + }, + end: { + line: 6, + column: 32, + }, + }, + }, + async: false, + expression: false, + range: [119, 142], + loc: { + start: { + line: 6, + column: 9, + }, + end: { + line: 6, + column: 32, + }, + }, + returnType: { + type: 'TSTypeAnnotation', + loc: { + start: { + line: 6, + column: 17, + }, + end: { + line: 6, + column: 23, + }, + }, + range: [127, 133], + typeAnnotation: { + type: 'TSVoidKeyword', + range: [129, 133], + loc: { + start: { + line: 6, + column: 19, + }, + end: { + line: 6, + column: 23, + }, + }, + }, + }, + }, + computed: false, + method: false, + shorthand: false, + kind: 'init', + range: [114, 142], + loc: { + start: { + line: 6, + column: 4, + }, + end: { + line: 6, + column: 32, + }, + }, + }, + { + type: 'Property', + key: { + type: 'Identifier', + name: 'key', + range: [148, 151], + loc: { + start: { + line: 7, + column: 4, + }, + end: { + line: 7, + column: 7, + }, + }, + }, + value: { + type: 'ArrowFunctionExpression', + generator: false, + id: null, + params: [ + { + type: 'Identifier', + name: 'arg', + range: [156, 162], + loc: { + start: { + line: 7, + column: 12, + }, + end: { + line: 7, + column: 18, + }, + }, + typeAnnotation: { + type: 'TSTypeAnnotation', + loc: { + start: { + line: 7, + column: 15, + }, + end: { + line: 7, + column: 18, + }, + }, + range: [159, 162], + typeAnnotation: { + type: 'TSTypeReference', + typeName: { + type: 'Identifier', + name: 't', + range: [161, 162], + loc: { + start: { + line: 7, + column: 17, + }, + end: { + line: 7, + column: 18, + }, + }, + }, + range: [161, 162], + loc: { + start: { + line: 7, + column: 17, + }, + end: { + line: 7, + column: 18, + }, + }, + }, + }, + }, + ], + body: { + type: 'BlockStatement', + body: [ + { + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'x', + range: [174, 175], + loc: { + start: { + line: 7, + column: 30, + }, + end: { + line: 7, + column: 31, + }, + }, + }, + arguments: [], + range: [174, 177], + loc: { + start: { + line: 7, + column: 30, + }, + end: { + line: 7, + column: 33, + }, + }, + }, + range: [174, 177], + loc: { + start: { + line: 7, + column: 30, + }, + end: { + line: 7, + column: 33, + }, + }, + }, + ], + range: [173, 178], + loc: { + start: { + line: 7, + column: 29, + }, + end: { + line: 7, + column: 34, + }, + }, + }, + async: false, + expression: false, + range: [155, 178], + loc: { + start: { + line: 7, + column: 11, + }, + end: { + line: 7, + column: 34, + }, + }, + returnType: { + type: 'TSTypeAnnotation', + loc: { + start: { + line: 7, + column: 19, + }, + end: { + line: 7, + column: 25, + }, + }, + range: [163, 169], + typeAnnotation: { + type: 'TSVoidKeyword', + range: [165, 169], + loc: { + start: { + line: 7, + column: 21, + }, + end: { + line: 7, + column: 25, + }, + }, + }, + }, + }, + computed: false, + method: false, + shorthand: false, + kind: 'init', + range: [148, 180], + loc: { + start: { + line: 7, + column: 4, + }, + end: { + line: 7, + column: 36, + }, + }, + }, + { + type: 'Property', + key: { + type: 'Identifier', + name: 'key', + range: [186, 189], + loc: { + start: { + line: 8, + column: 4, + }, + end: { + line: 8, + column: 7, + }, + }, + }, + value: { + type: 'ArrowFunctionExpression', + generator: false, + id: null, + params: [ + { + type: 'Identifier', + name: 'arg', + range: [194, 200], + loc: { + start: { + line: 8, + column: 12, + }, + end: { + line: 8, + column: 18, + }, + }, + typeAnnotation: { + type: 'TSTypeAnnotation', + loc: { + start: { + line: 8, + column: 15, + }, + end: { + line: 8, + column: 18, + }, + }, + range: [197, 200], + typeAnnotation: { + type: 'TSTypeReference', + typeName: { + type: 'Identifier', + name: 't', + range: [199, 200], + loc: { + start: { + line: 8, + column: 17, + }, + end: { + line: 8, + column: 18, + }, + }, + }, + range: [199, 200], + loc: { + start: { + line: 8, + column: 17, + }, + end: { + line: 8, + column: 18, + }, + }, + }, + }, + }, + ], + body: { + type: 'BlockStatement', + body: [ + { + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'x', + range: [214, 215], + loc: { + start: { + line: 8, + column: 32, + }, + end: { + line: 8, + column: 33, + }, + }, + }, + arguments: [], + range: [214, 217], + loc: { + start: { + line: 8, + column: 32, + }, + end: { + line: 8, + column: 35, + }, + }, + }, + range: [214, 217], + loc: { + start: { + line: 8, + column: 32, + }, + end: { + line: 8, + column: 35, + }, + }, + }, + ], + range: [213, 218], + loc: { + start: { + line: 8, + column: 31, + }, + end: { + line: 8, + column: 36, + }, + }, + }, + async: false, + expression: false, + range: [193, 218], + loc: { + start: { + line: 8, + column: 11, + }, + end: { + line: 8, + column: 36, + }, + }, + returnType: { + type: 'TSTypeAnnotation', + loc: { + start: { + line: 8, + column: 19, + }, + end: { + line: 8, + column: 27, + }, + }, + range: [201, 209], + typeAnnotation: { + type: 'TSParenthesizedType', + typeAnnotation: { + type: 'TSVoidKeyword', + range: [204, 208], + loc: { + start: { + line: 8, + column: 22, + }, + end: { + line: 8, + column: 26, + }, + }, + }, + range: [203, 209], + loc: { + start: { + line: 8, + column: 21, + }, + end: { + line: 8, + column: 27, + }, + }, + }, + }, + }, + computed: false, + method: false, + shorthand: false, + kind: 'init', + range: [186, 220], + loc: { + start: { + line: 8, + column: 4, + }, + end: { + line: 8, + column: 38, + }, + }, + }, + { + type: 'Property', + key: { + type: 'Identifier', + name: 'key', + range: [227, 230], + loc: { + start: { + line: 10, + column: 4, + }, + end: { + line: 10, + column: 7, + }, + }, + }, + value: { + type: 'ArrowFunctionExpression', + generator: false, + id: null, + params: [ + { + type: 'Identifier', + name: 'arg', + range: [233, 239], + loc: { + start: { + line: 10, + column: 10, + }, + end: { + line: 10, + column: 16, + }, + }, + typeAnnotation: { + type: 'TSTypeAnnotation', + loc: { + start: { + line: 10, + column: 13, + }, + end: { + line: 10, + column: 16, + }, + }, + range: [236, 239], + typeAnnotation: { + type: 'TSTypeReference', + typeName: { + type: 'Identifier', + name: 't', + range: [238, 239], + loc: { + start: { + line: 10, + column: 15, + }, + end: { + line: 10, + column: 16, + }, + }, + }, + range: [238, 239], + loc: { + start: { + line: 10, + column: 15, + }, + end: { + line: 10, + column: 16, + }, + }, + }, + }, + }, + { + type: 'Identifier', + name: 'arg2', + range: [241, 248], + loc: { + start: { + line: 10, + column: 18, + }, + end: { + line: 10, + column: 25, + }, + }, + typeAnnotation: { + type: 'TSTypeAnnotation', + loc: { + start: { + line: 10, + column: 22, + }, + end: { + line: 10, + column: 25, + }, + }, + range: [245, 248], + typeAnnotation: { + type: 'TSTypeReference', + typeName: { + type: 'Identifier', + name: 't', + range: [247, 248], + loc: { + start: { + line: 10, + column: 24, + }, + end: { + line: 10, + column: 25, + }, + }, + }, + range: [247, 248], + loc: { + start: { + line: 10, + column: 24, + }, + end: { + line: 10, + column: 25, + }, + }, + }, + }, + }, + ], + body: { + type: 'BlockStatement', + body: [ + { + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'x', + range: [260, 261], + loc: { + start: { + line: 10, + column: 37, + }, + end: { + line: 10, + column: 38, + }, + }, + }, + arguments: [], + range: [260, 263], + loc: { + start: { + line: 10, + column: 37, + }, + end: { + line: 10, + column: 40, + }, + }, + }, + range: [260, 263], + loc: { + start: { + line: 10, + column: 37, + }, + end: { + line: 10, + column: 40, + }, + }, + }, + ], + range: [259, 264], + loc: { + start: { + line: 10, + column: 36, + }, + end: { + line: 10, + column: 41, + }, + }, + }, + async: false, + expression: false, + range: [232, 264], + loc: { + start: { + line: 10, + column: 9, + }, + end: { + line: 10, + column: 41, + }, + }, + returnType: { + type: 'TSTypeAnnotation', + loc: { + start: { + line: 10, + column: 26, + }, + end: { + line: 10, + column: 32, + }, + }, + range: [249, 255], + typeAnnotation: { + type: 'TSVoidKeyword', + range: [251, 255], + loc: { + start: { + line: 10, + column: 28, + }, + end: { + line: 10, + column: 32, + }, + }, + }, + }, + }, + computed: false, + method: false, + shorthand: false, + kind: 'init', + range: [227, 264], + loc: { + start: { + line: 10, + column: 4, + }, + end: { + line: 10, + column: 41, + }, + }, + }, + { + type: 'Property', + key: { + type: 'Identifier', + name: 'key', + range: [270, 273], + loc: { + start: { + line: 11, + column: 4, + }, + end: { + line: 11, + column: 7, + }, + }, + }, + value: { + type: 'ArrowFunctionExpression', + generator: false, + id: null, + params: [ + { + type: 'Identifier', + name: 'arg', + range: [278, 284], + loc: { + start: { + line: 11, + column: 12, + }, + end: { + line: 11, + column: 18, + }, + }, + typeAnnotation: { + type: 'TSTypeAnnotation', + loc: { + start: { + line: 11, + column: 15, + }, + end: { + line: 11, + column: 18, + }, + }, + range: [281, 284], + typeAnnotation: { + type: 'TSTypeReference', + typeName: { + type: 'Identifier', + name: 't', + range: [283, 284], + loc: { + start: { + line: 11, + column: 17, + }, + end: { + line: 11, + column: 18, + }, + }, + }, + range: [283, 284], + loc: { + start: { + line: 11, + column: 17, + }, + end: { + line: 11, + column: 18, + }, + }, + }, + }, + }, + { + type: 'Identifier', + name: 'arg2', + range: [286, 293], + loc: { + start: { + line: 11, + column: 20, + }, + end: { + line: 11, + column: 27, + }, + }, + typeAnnotation: { + type: 'TSTypeAnnotation', + loc: { + start: { + line: 11, + column: 24, + }, + end: { + line: 11, + column: 27, + }, + }, + range: [290, 293], + typeAnnotation: { + type: 'TSTypeReference', + typeName: { + type: 'Identifier', + name: 't', + range: [292, 293], + loc: { + start: { + line: 11, + column: 26, + }, + end: { + line: 11, + column: 27, + }, + }, + }, + range: [292, 293], + loc: { + start: { + line: 11, + column: 26, + }, + end: { + line: 11, + column: 27, + }, + }, + }, + }, + }, + ], + body: { + type: 'BlockStatement', + body: [ + { + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'x', + range: [305, 306], + loc: { + start: { + line: 11, + column: 39, + }, + end: { + line: 11, + column: 40, + }, + }, + }, + arguments: [], + range: [305, 308], + loc: { + start: { + line: 11, + column: 39, + }, + end: { + line: 11, + column: 42, + }, + }, + }, + range: [305, 308], + loc: { + start: { + line: 11, + column: 39, + }, + end: { + line: 11, + column: 42, + }, + }, + }, + ], + range: [304, 309], + loc: { + start: { + line: 11, + column: 38, + }, + end: { + line: 11, + column: 43, + }, + }, + }, + async: false, + expression: false, + range: [277, 309], + loc: { + start: { + line: 11, + column: 11, + }, + end: { + line: 11, + column: 43, + }, + }, + returnType: { + type: 'TSTypeAnnotation', + loc: { + start: { + line: 11, + column: 28, + }, + end: { + line: 11, + column: 34, + }, + }, + range: [294, 300], + typeAnnotation: { + type: 'TSVoidKeyword', + range: [296, 300], + loc: { + start: { + line: 11, + column: 30, + }, + end: { + line: 11, + column: 34, + }, + }, + }, + }, + }, + computed: false, + method: false, + shorthand: false, + kind: 'init', + range: [270, 311], + loc: { + start: { + line: 11, + column: 4, + }, + end: { + line: 11, + column: 45, + }, + }, + }, + { + type: 'Property', + key: { + type: 'Identifier', + name: 'key', + range: [317, 320], + loc: { + start: { + line: 12, + column: 4, + }, + end: { + line: 12, + column: 7, + }, + }, + }, + value: { + type: 'ArrowFunctionExpression', + generator: false, + id: null, + params: [ + { + type: 'Identifier', + name: 'arg', + range: [325, 331], + loc: { + start: { + line: 12, + column: 12, + }, + end: { + line: 12, + column: 18, + }, + }, + typeAnnotation: { + type: 'TSTypeAnnotation', + loc: { + start: { + line: 12, + column: 15, + }, + end: { + line: 12, + column: 18, + }, + }, + range: [328, 331], + typeAnnotation: { + type: 'TSTypeReference', + typeName: { + type: 'Identifier', + name: 't', + range: [330, 331], + loc: { + start: { + line: 12, + column: 17, + }, + end: { + line: 12, + column: 18, + }, + }, + }, + range: [330, 331], + loc: { + start: { + line: 12, + column: 17, + }, + end: { + line: 12, + column: 18, + }, + }, + }, + }, + }, + { + type: 'Identifier', + name: 'arg2', + range: [333, 340], + loc: { + start: { + line: 12, + column: 20, + }, + end: { + line: 12, + column: 27, + }, + }, + typeAnnotation: { + type: 'TSTypeAnnotation', + loc: { + start: { + line: 12, + column: 24, + }, + end: { + line: 12, + column: 27, + }, + }, + range: [337, 340], + typeAnnotation: { + type: 'TSTypeReference', + typeName: { + type: 'Identifier', + name: 't', + range: [339, 340], + loc: { + start: { + line: 12, + column: 26, + }, + end: { + line: 12, + column: 27, + }, + }, + }, + range: [339, 340], + loc: { + start: { + line: 12, + column: 26, + }, + end: { + line: 12, + column: 27, + }, + }, + }, + }, + }, + ], + body: { + type: 'BlockStatement', + body: [ + { + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'x', + range: [354, 355], + loc: { + start: { + line: 12, + column: 41, + }, + end: { + line: 12, + column: 42, + }, + }, + }, + arguments: [], + range: [354, 357], + loc: { + start: { + line: 12, + column: 41, + }, + end: { + line: 12, + column: 44, + }, + }, + }, + range: [354, 357], + loc: { + start: { + line: 12, + column: 41, + }, + end: { + line: 12, + column: 44, + }, + }, + }, + ], + range: [353, 358], + loc: { + start: { + line: 12, + column: 40, + }, + end: { + line: 12, + column: 45, + }, + }, + }, + async: false, + expression: false, + range: [324, 358], + loc: { + start: { + line: 12, + column: 11, + }, + end: { + line: 12, + column: 45, + }, + }, + returnType: { + type: 'TSTypeAnnotation', + loc: { + start: { + line: 12, + column: 28, + }, + end: { + line: 12, + column: 36, + }, + }, + range: [341, 349], + typeAnnotation: { + type: 'TSParenthesizedType', + typeAnnotation: { + type: 'TSVoidKeyword', + range: [344, 348], + loc: { + start: { + line: 12, + column: 31, + }, + end: { + line: 12, + column: 35, + }, + }, + }, + range: [343, 349], + loc: { + start: { + line: 12, + column: 30, + }, + end: { + line: 12, + column: 36, + }, + }, + }, + }, + }, + computed: false, + method: false, + shorthand: false, + kind: 'init', + range: [317, 360], + loc: { + start: { + line: 12, + column: 4, + }, + end: { + line: 12, + column: 47, + }, + }, + }, + { + type: 'Property', + key: { + type: 'Identifier', + name: 'key', + range: [367, 370], + loc: { + start: { + line: 14, + column: 4, + }, + end: { + line: 14, + column: 7, + }, + }, + }, + value: { + type: 'ArrowFunctionExpression', + generator: false, + id: null, + params: [], + body: { + type: 'BlockStatement', + body: [ + { + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'x', + range: [391, 392], + loc: { + start: { + line: 14, + column: 28, + }, + end: { + line: 14, + column: 29, + }, + }, + }, + arguments: [], + range: [391, 394], + loc: { + start: { + line: 14, + column: 28, + }, + end: { + line: 14, + column: 31, + }, + }, + }, + range: [391, 394], + loc: { + start: { + line: 14, + column: 28, + }, + end: { + line: 14, + column: 31, + }, + }, + }, + ], + range: [390, 395], + loc: { + start: { + line: 14, + column: 27, + }, + end: { + line: 14, + column: 32, + }, + }, + }, + async: true, + expression: false, + range: [372, 395], + loc: { + start: { + line: 14, + column: 9, + }, + end: { + line: 14, + column: 32, + }, + }, + returnType: { + type: 'TSTypeAnnotation', + loc: { + start: { + line: 14, + column: 17, + }, + end: { + line: 14, + column: 23, + }, + }, + range: [380, 386], + typeAnnotation: { + type: 'TSVoidKeyword', + range: [382, 386], + loc: { + start: { + line: 14, + column: 19, + }, + end: { + line: 14, + column: 23, + }, + }, + }, + }, + }, + computed: false, + method: false, + shorthand: false, + kind: 'init', + range: [367, 395], + loc: { + start: { + line: 14, + column: 4, + }, + end: { + line: 14, + column: 32, + }, + }, + }, + { + type: 'Property', + key: { + type: 'Identifier', + name: 'key', + range: [401, 404], + loc: { + start: { + line: 15, + column: 4, + }, + end: { + line: 15, + column: 7, + }, + }, + }, + value: { + type: 'ArrowFunctionExpression', + generator: false, + id: null, + params: [], + body: { + type: 'BlockStatement', + body: [ + { + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'x', + range: [427, 428], + loc: { + start: { + line: 15, + column: 30, + }, + end: { + line: 15, + column: 31, + }, + }, + }, + arguments: [], + range: [427, 430], + loc: { + start: { + line: 15, + column: 30, + }, + end: { + line: 15, + column: 33, + }, + }, + }, + range: [427, 430], + loc: { + start: { + line: 15, + column: 30, + }, + end: { + line: 15, + column: 33, + }, + }, + }, + ], + range: [426, 431], + loc: { + start: { + line: 15, + column: 29, + }, + end: { + line: 15, + column: 34, + }, + }, + }, + async: true, + expression: false, + range: [408, 431], + loc: { + start: { + line: 15, + column: 11, + }, + end: { + line: 15, + column: 34, + }, + }, + returnType: { + type: 'TSTypeAnnotation', + loc: { + start: { + line: 15, + column: 19, + }, + end: { + line: 15, + column: 25, + }, + }, + range: [416, 422], + typeAnnotation: { + type: 'TSVoidKeyword', + range: [418, 422], + loc: { + start: { + line: 15, + column: 21, + }, + end: { + line: 15, + column: 25, + }, + }, + }, + }, + }, + computed: false, + method: false, + shorthand: false, + kind: 'init', + range: [401, 433], + loc: { + start: { + line: 15, + column: 4, + }, + end: { + line: 15, + column: 36, + }, + }, + }, + { + type: 'Property', + key: { + type: 'Identifier', + name: 'key', + range: [439, 442], + loc: { + start: { + line: 16, + column: 4, + }, + end: { + line: 16, + column: 7, + }, + }, + }, + value: { + type: 'ArrowFunctionExpression', + generator: false, + id: null, + params: [], + body: { + type: 'BlockStatement', + body: [ + { + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'x', + range: [467, 468], + loc: { + start: { + line: 16, + column: 32, + }, + end: { + line: 16, + column: 33, + }, + }, + }, + arguments: [], + range: [467, 470], + loc: { + start: { + line: 16, + column: 32, + }, + end: { + line: 16, + column: 35, + }, + }, + }, + range: [467, 470], + loc: { + start: { + line: 16, + column: 32, + }, + end: { + line: 16, + column: 35, + }, + }, + }, + ], + range: [466, 471], + loc: { + start: { + line: 16, + column: 31, + }, + end: { + line: 16, + column: 36, + }, + }, + }, + async: true, + expression: false, + range: [446, 471], + loc: { + start: { + line: 16, + column: 11, + }, + end: { + line: 16, + column: 36, + }, + }, + returnType: { + type: 'TSTypeAnnotation', + loc: { + start: { + line: 16, + column: 19, + }, + end: { + line: 16, + column: 27, + }, + }, + range: [454, 462], + typeAnnotation: { + type: 'TSParenthesizedType', + typeAnnotation: { + type: 'TSVoidKeyword', + range: [457, 461], + loc: { + start: { + line: 16, + column: 22, + }, + end: { + line: 16, + column: 26, + }, + }, + }, + range: [456, 462], + loc: { + start: { + line: 16, + column: 21, + }, + end: { + line: 16, + column: 27, + }, + }, + }, + }, + }, + computed: false, + method: false, + shorthand: false, + kind: 'init', + range: [439, 473], + loc: { + start: { + line: 16, + column: 4, + }, + end: { + line: 16, + column: 38, + }, + }, + }, + { + type: 'Property', + key: { + type: 'Identifier', + name: 'key', + range: [480, 483], + loc: { + start: { + line: 18, + column: 4, + }, + end: { + line: 18, + column: 7, + }, + }, + }, + value: { + type: 'ArrowFunctionExpression', + generator: false, + id: null, + params: [ + { + type: 'Identifier', + name: 'arg', + range: [492, 498], + loc: { + start: { + line: 18, + column: 16, + }, + end: { + line: 18, + column: 22, + }, + }, + typeAnnotation: { + type: 'TSTypeAnnotation', + loc: { + start: { + line: 18, + column: 19, + }, + end: { + line: 18, + column: 22, + }, + }, + range: [495, 498], + typeAnnotation: { + type: 'TSTypeReference', + typeName: { + type: 'Identifier', + name: 't', + range: [497, 498], + loc: { + start: { + line: 18, + column: 21, + }, + end: { + line: 18, + column: 22, + }, + }, + }, + range: [497, 498], + loc: { + start: { + line: 18, + column: 21, + }, + end: { + line: 18, + column: 22, + }, + }, + }, + }, + }, + ], + body: { + type: 'BlockStatement', + body: [ + { + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'x', + range: [510, 511], + loc: { + start: { + line: 18, + column: 34, + }, + end: { + line: 18, + column: 35, + }, + }, + }, + arguments: [], + range: [510, 513], + loc: { + start: { + line: 18, + column: 34, + }, + end: { + line: 18, + column: 37, + }, + }, + }, + range: [510, 513], + loc: { + start: { + line: 18, + column: 34, + }, + end: { + line: 18, + column: 37, + }, + }, + }, + ], + range: [509, 514], + loc: { + start: { + line: 18, + column: 33, + }, + end: { + line: 18, + column: 38, + }, + }, + }, + async: true, + expression: false, + range: [485, 514], + loc: { + start: { + line: 18, + column: 9, + }, + end: { + line: 18, + column: 38, + }, + }, + returnType: { + type: 'TSTypeAnnotation', + loc: { + start: { + line: 18, + column: 23, + }, + end: { + line: 18, + column: 29, + }, + }, + range: [499, 505], + typeAnnotation: { + type: 'TSVoidKeyword', + range: [501, 505], + loc: { + start: { + line: 18, + column: 25, + }, + end: { + line: 18, + column: 29, + }, + }, + }, + }, + }, + computed: false, + method: false, + shorthand: false, + kind: 'init', + range: [480, 514], + loc: { + start: { + line: 18, + column: 4, + }, + end: { + line: 18, + column: 38, + }, + }, + }, + { + type: 'Property', + key: { + type: 'Identifier', + name: 'key', + range: [520, 523], + loc: { + start: { + line: 19, + column: 4, + }, + end: { + line: 19, + column: 7, + }, + }, + }, + value: { + type: 'ArrowFunctionExpression', + generator: false, + id: null, + params: [ + { + type: 'Identifier', + name: 'arg', + range: [534, 540], + loc: { + start: { + line: 19, + column: 18, + }, + end: { + line: 19, + column: 24, + }, + }, + typeAnnotation: { + type: 'TSTypeAnnotation', + loc: { + start: { + line: 19, + column: 21, + }, + end: { + line: 19, + column: 24, + }, + }, + range: [537, 540], + typeAnnotation: { + type: 'TSTypeReference', + typeName: { + type: 'Identifier', + name: 't', + range: [539, 540], + loc: { + start: { + line: 19, + column: 23, + }, + end: { + line: 19, + column: 24, + }, + }, + }, + range: [539, 540], + loc: { + start: { + line: 19, + column: 23, + }, + end: { + line: 19, + column: 24, + }, + }, + }, + }, + }, + ], + body: { + type: 'BlockStatement', + body: [ + { + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'x', + range: [552, 553], + loc: { + start: { + line: 19, + column: 36, + }, + end: { + line: 19, + column: 37, + }, + }, + }, + arguments: [], + range: [552, 555], + loc: { + start: { + line: 19, + column: 36, + }, + end: { + line: 19, + column: 39, + }, + }, + }, + range: [552, 555], + loc: { + start: { + line: 19, + column: 36, + }, + end: { + line: 19, + column: 39, + }, + }, + }, + ], + range: [551, 556], + loc: { + start: { + line: 19, + column: 35, + }, + end: { + line: 19, + column: 40, + }, + }, + }, + async: true, + expression: false, + range: [527, 556], + loc: { + start: { + line: 19, + column: 11, + }, + end: { + line: 19, + column: 40, + }, + }, + returnType: { + type: 'TSTypeAnnotation', + loc: { + start: { + line: 19, + column: 25, + }, + end: { + line: 19, + column: 31, + }, + }, + range: [541, 547], + typeAnnotation: { + type: 'TSVoidKeyword', + range: [543, 547], + loc: { + start: { + line: 19, + column: 27, + }, + end: { + line: 19, + column: 31, + }, + }, + }, + }, + }, + computed: false, + method: false, + shorthand: false, + kind: 'init', + range: [520, 558], + loc: { + start: { + line: 19, + column: 4, + }, + end: { + line: 19, + column: 42, + }, + }, + }, + { + type: 'Property', + key: { + type: 'Identifier', + name: 'key', + range: [564, 567], + loc: { + start: { + line: 20, + column: 4, + }, + end: { + line: 20, + column: 7, + }, + }, + }, + value: { + type: 'ArrowFunctionExpression', + generator: false, + id: null, + params: [ + { + type: 'Identifier', + name: 'arg', + range: [578, 584], + loc: { + start: { + line: 20, + column: 18, + }, + end: { + line: 20, + column: 24, + }, + }, + typeAnnotation: { + type: 'TSTypeAnnotation', + loc: { + start: { + line: 20, + column: 21, + }, + end: { + line: 20, + column: 24, + }, + }, + range: [581, 584], + typeAnnotation: { + type: 'TSTypeReference', + typeName: { + type: 'Identifier', + name: 't', + range: [583, 584], + loc: { + start: { + line: 20, + column: 23, + }, + end: { + line: 20, + column: 24, + }, + }, + }, + range: [583, 584], + loc: { + start: { + line: 20, + column: 23, + }, + end: { + line: 20, + column: 24, + }, + }, + }, + }, + }, + ], + body: { + type: 'BlockStatement', + body: [ + { + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'x', + range: [598, 599], + loc: { + start: { + line: 20, + column: 38, + }, + end: { + line: 20, + column: 39, + }, + }, + }, + arguments: [], + range: [598, 601], + loc: { + start: { + line: 20, + column: 38, + }, + end: { + line: 20, + column: 41, + }, + }, + }, + range: [598, 601], + loc: { + start: { + line: 20, + column: 38, + }, + end: { + line: 20, + column: 41, + }, + }, + }, + ], + range: [597, 602], + loc: { + start: { + line: 20, + column: 37, + }, + end: { + line: 20, + column: 42, + }, + }, + }, + async: true, + expression: false, + range: [571, 602], + loc: { + start: { + line: 20, + column: 11, + }, + end: { + line: 20, + column: 42, + }, + }, + returnType: { + type: 'TSTypeAnnotation', + loc: { + start: { + line: 20, + column: 25, + }, + end: { + line: 20, + column: 33, + }, + }, + range: [585, 593], + typeAnnotation: { + type: 'TSParenthesizedType', + typeAnnotation: { + type: 'TSVoidKeyword', + range: [588, 592], + loc: { + start: { + line: 20, + column: 28, + }, + end: { + line: 20, + column: 32, + }, + }, + }, + range: [587, 593], + loc: { + start: { + line: 20, + column: 27, + }, + end: { + line: 20, + column: 33, + }, + }, + }, + }, + }, + computed: false, + method: false, + shorthand: false, + kind: 'init', + range: [564, 604], + loc: { + start: { + line: 20, + column: 4, + }, + end: { + line: 20, + column: 44, + }, + }, + }, + { + type: 'Property', + key: { + type: 'Identifier', + name: 'key', + range: [611, 614], + loc: { + start: { + line: 22, + column: 4, + }, + end: { + line: 22, + column: 7, + }, + }, + }, + value: { + type: 'ArrowFunctionExpression', + generator: false, + id: null, + params: [ + { + type: 'Identifier', + name: 'arg', + range: [623, 629], + loc: { + start: { + line: 22, + column: 16, + }, + end: { + line: 22, + column: 22, + }, + }, + typeAnnotation: { + type: 'TSTypeAnnotation', + loc: { + start: { + line: 22, + column: 19, + }, + end: { + line: 22, + column: 22, + }, + }, + range: [626, 629], + typeAnnotation: { + type: 'TSTypeReference', + typeName: { + type: 'Identifier', + name: 't', + range: [628, 629], + loc: { + start: { + line: 22, + column: 21, + }, + end: { + line: 22, + column: 22, + }, + }, + }, + range: [628, 629], + loc: { + start: { + line: 22, + column: 21, + }, + end: { + line: 22, + column: 22, + }, + }, + }, + }, + }, + { + type: 'Identifier', + name: 'arg2', + range: [631, 638], + loc: { + start: { + line: 22, + column: 24, + }, + end: { + line: 22, + column: 31, + }, + }, + typeAnnotation: { + type: 'TSTypeAnnotation', + loc: { + start: { + line: 22, + column: 28, + }, + end: { + line: 22, + column: 31, + }, + }, + range: [635, 638], + typeAnnotation: { + type: 'TSTypeReference', + typeName: { + type: 'Identifier', + name: 't', + range: [637, 638], + loc: { + start: { + line: 22, + column: 30, + }, + end: { + line: 22, + column: 31, + }, + }, + }, + range: [637, 638], + loc: { + start: { + line: 22, + column: 30, + }, + end: { + line: 22, + column: 31, + }, + }, + }, + }, + }, + ], + body: { + type: 'BlockStatement', + body: [ + { + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'x', + range: [650, 651], + loc: { + start: { + line: 22, + column: 43, + }, + end: { + line: 22, + column: 44, + }, + }, + }, + arguments: [], + range: [650, 653], + loc: { + start: { + line: 22, + column: 43, + }, + end: { + line: 22, + column: 46, + }, + }, + }, + range: [650, 653], + loc: { + start: { + line: 22, + column: 43, + }, + end: { + line: 22, + column: 46, + }, + }, + }, + ], + range: [649, 654], + loc: { + start: { + line: 22, + column: 42, + }, + end: { + line: 22, + column: 47, + }, + }, + }, + async: true, + expression: false, + range: [616, 654], + loc: { + start: { + line: 22, + column: 9, + }, + end: { + line: 22, + column: 47, + }, + }, + returnType: { + type: 'TSTypeAnnotation', + loc: { + start: { + line: 22, + column: 32, + }, + end: { + line: 22, + column: 38, + }, + }, + range: [639, 645], + typeAnnotation: { + type: 'TSVoidKeyword', + range: [641, 645], + loc: { + start: { + line: 22, + column: 34, + }, + end: { + line: 22, + column: 38, + }, + }, + }, + }, + }, + computed: false, + method: false, + shorthand: false, + kind: 'init', + range: [611, 654], + loc: { + start: { + line: 22, + column: 4, + }, + end: { + line: 22, + column: 47, + }, + }, + }, + { + type: 'Property', + key: { + type: 'Identifier', + name: 'key', + range: [660, 663], + loc: { + start: { + line: 23, + column: 4, + }, + end: { + line: 23, + column: 7, + }, + }, + }, + value: { + type: 'ArrowFunctionExpression', + generator: false, + id: null, + params: [ + { + type: 'Identifier', + name: 'arg', + range: [674, 680], + loc: { + start: { + line: 23, + column: 18, + }, + end: { + line: 23, + column: 24, + }, + }, + typeAnnotation: { + type: 'TSTypeAnnotation', + loc: { + start: { + line: 23, + column: 21, + }, + end: { + line: 23, + column: 24, + }, + }, + range: [677, 680], + typeAnnotation: { + type: 'TSTypeReference', + typeName: { + type: 'Identifier', + name: 't', + range: [679, 680], + loc: { + start: { + line: 23, + column: 23, + }, + end: { + line: 23, + column: 24, + }, + }, + }, + range: [679, 680], + loc: { + start: { + line: 23, + column: 23, + }, + end: { + line: 23, + column: 24, + }, + }, + }, + }, + }, + { + type: 'Identifier', + name: 'arg2', + range: [682, 689], + loc: { + start: { + line: 23, + column: 26, + }, + end: { + line: 23, + column: 33, + }, + }, + typeAnnotation: { + type: 'TSTypeAnnotation', + loc: { + start: { + line: 23, + column: 30, + }, + end: { + line: 23, + column: 33, + }, + }, + range: [686, 689], + typeAnnotation: { + type: 'TSTypeReference', + typeName: { + type: 'Identifier', + name: 't', + range: [688, 689], + loc: { + start: { + line: 23, + column: 32, + }, + end: { + line: 23, + column: 33, + }, + }, + }, + range: [688, 689], + loc: { + start: { + line: 23, + column: 32, + }, + end: { + line: 23, + column: 33, + }, + }, + }, + }, + }, + ], + body: { + type: 'BlockStatement', + body: [ + { + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'x', + range: [701, 702], + loc: { + start: { + line: 23, + column: 45, + }, + end: { + line: 23, + column: 46, + }, + }, + }, + arguments: [], + range: [701, 704], + loc: { + start: { + line: 23, + column: 45, + }, + end: { + line: 23, + column: 48, + }, + }, + }, + range: [701, 704], + loc: { + start: { + line: 23, + column: 45, + }, + end: { + line: 23, + column: 48, + }, + }, + }, + ], + range: [700, 705], + loc: { + start: { + line: 23, + column: 44, + }, + end: { + line: 23, + column: 49, + }, + }, + }, + async: true, + expression: false, + range: [667, 705], + loc: { + start: { + line: 23, + column: 11, + }, + end: { + line: 23, + column: 49, + }, + }, + returnType: { + type: 'TSTypeAnnotation', + loc: { + start: { + line: 23, + column: 34, + }, + end: { + line: 23, + column: 40, + }, + }, + range: [690, 696], + typeAnnotation: { + type: 'TSVoidKeyword', + range: [692, 696], + loc: { + start: { + line: 23, + column: 36, + }, + end: { + line: 23, + column: 40, + }, + }, + }, + }, + }, + computed: false, + method: false, + shorthand: false, + kind: 'init', + range: [660, 707], + loc: { + start: { + line: 23, + column: 4, + }, + end: { + line: 23, + column: 51, + }, + }, + }, + { + type: 'Property', + key: { + type: 'Identifier', + name: 'key', + range: [713, 716], + loc: { + start: { + line: 24, + column: 4, + }, + end: { + line: 24, + column: 7, + }, + }, + }, + value: { + type: 'ArrowFunctionExpression', + generator: false, + id: null, + params: [ + { + type: 'Identifier', + name: 'arg', + range: [727, 733], + loc: { + start: { + line: 24, + column: 18, + }, + end: { + line: 24, + column: 24, + }, + }, + typeAnnotation: { + type: 'TSTypeAnnotation', + loc: { + start: { + line: 24, + column: 21, + }, + end: { + line: 24, + column: 24, + }, + }, + range: [730, 733], + typeAnnotation: { + type: 'TSTypeReference', + typeName: { + type: 'Identifier', + name: 't', + range: [732, 733], + loc: { + start: { + line: 24, + column: 23, + }, + end: { + line: 24, + column: 24, + }, + }, + }, + range: [732, 733], + loc: { + start: { + line: 24, + column: 23, + }, + end: { + line: 24, + column: 24, + }, + }, + }, + }, + }, + { + type: 'Identifier', + name: 'arg2', + range: [735, 742], + loc: { + start: { + line: 24, + column: 26, + }, + end: { + line: 24, + column: 33, + }, + }, + typeAnnotation: { + type: 'TSTypeAnnotation', + loc: { + start: { + line: 24, + column: 30, + }, + end: { + line: 24, + column: 33, + }, + }, + range: [739, 742], + typeAnnotation: { + type: 'TSTypeReference', + typeName: { + type: 'Identifier', + name: 't', + range: [741, 742], + loc: { + start: { + line: 24, + column: 32, + }, + end: { + line: 24, + column: 33, + }, + }, + }, + range: [741, 742], + loc: { + start: { + line: 24, + column: 32, + }, + end: { + line: 24, + column: 33, + }, + }, + }, + }, + }, + ], + body: { + type: 'BlockStatement', + body: [ + { + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'x', + range: [756, 757], + loc: { + start: { + line: 24, + column: 47, + }, + end: { + line: 24, + column: 48, + }, + }, + }, + arguments: [], + range: [756, 759], + loc: { + start: { + line: 24, + column: 47, + }, + end: { + line: 24, + column: 50, + }, + }, + }, + range: [756, 759], + loc: { + start: { + line: 24, + column: 47, + }, + end: { + line: 24, + column: 50, + }, + }, + }, + ], + range: [755, 760], + loc: { + start: { + line: 24, + column: 46, + }, + end: { + line: 24, + column: 51, + }, + }, + }, + async: true, + expression: false, + range: [720, 760], + loc: { + start: { + line: 24, + column: 11, + }, + end: { + line: 24, + column: 51, + }, + }, + returnType: { + type: 'TSTypeAnnotation', + loc: { + start: { + line: 24, + column: 34, + }, + end: { + line: 24, + column: 42, + }, + }, + range: [743, 751], + typeAnnotation: { + type: 'TSParenthesizedType', + typeAnnotation: { + type: 'TSVoidKeyword', + range: [746, 750], + loc: { + start: { + line: 24, + column: 37, + }, + end: { + line: 24, + column: 41, + }, + }, + }, + range: [745, 751], + loc: { + start: { + line: 24, + column: 36, + }, + end: { + line: 24, + column: 42, + }, + }, + }, + }, + }, + computed: false, + method: false, + shorthand: false, + kind: 'init', + range: [713, 762], + loc: { + start: { + line: 24, + column: 4, + }, + end: { + line: 24, + column: 53, + }, + }, + }, + ], + range: [13, 765], + loc: { + start: { + line: 1, + column: 13, + }, + end: { + line: 25, + column: 1, + }, + }, + }, + range: [6, 765], + loc: { + start: { + line: 1, + column: 6, + }, + end: { + line: 25, + column: 1, + }, + }, + }, + ], + kind: 'const', + range: [0, 765], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 25, + column: 1, + }, + }, + }, + ], + sourceType: 'module', + range: [0, 765], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 25, + column: 1, + }, + }, + tokens: [ + { + type: 'Keyword', + value: 'const', + range: [0, 5], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 5, + }, + }, + }, + { + type: 'Identifier', + value: 'test', + range: [6, 10], + loc: { + start: { + line: 1, + column: 6, + }, + end: { + line: 1, + column: 10, + }, + }, + }, + { + type: 'Punctuator', + value: '=', + range: [11, 12], + loc: { + start: { + line: 1, + column: 11, + }, + end: { + line: 1, + column: 12, + }, + }, + }, + { + type: 'Punctuator', + value: '{', + range: [13, 14], + loc: { + start: { + line: 1, + column: 13, + }, + end: { + line: 1, + column: 14, + }, + }, + }, + { + type: 'Identifier', + value: 'key', + range: [19, 22], + loc: { + start: { + line: 2, + column: 4, + }, + end: { + line: 2, + column: 7, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [22, 23], + loc: { + start: { + line: 2, + column: 7, + }, + end: { + line: 2, + column: 8, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [24, 25], + loc: { + start: { + line: 2, + column: 9, + }, + end: { + line: 2, + column: 10, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [25, 26], + loc: { + start: { + line: 2, + column: 10, + }, + end: { + line: 2, + column: 11, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [26, 27], + loc: { + start: { + line: 2, + column: 11, + }, + end: { + line: 2, + column: 12, + }, + }, + }, + { + type: 'Keyword', + value: 'void', + range: [28, 32], + loc: { + start: { + line: 2, + column: 13, + }, + end: { + line: 2, + column: 17, + }, + }, + }, + { + type: 'Punctuator', + value: '=>', + range: [33, 35], + loc: { + start: { + line: 2, + column: 18, + }, + end: { + line: 2, + column: 20, + }, + }, + }, + { + type: 'Punctuator', + value: '{', + range: [36, 37], + loc: { + start: { + line: 2, + column: 21, + }, + end: { + line: 2, + column: 22, + }, + }, + }, + { + type: 'Identifier', + value: 'x', + range: [37, 38], + loc: { + start: { + line: 2, + column: 22, + }, + end: { + line: 2, + column: 23, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [38, 39], + loc: { + start: { + line: 2, + column: 23, + }, + end: { + line: 2, + column: 24, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [39, 40], + loc: { + start: { + line: 2, + column: 24, + }, + end: { + line: 2, + column: 25, + }, + }, + }, + { + type: 'Punctuator', + value: '}', + range: [40, 41], + loc: { + start: { + line: 2, + column: 25, + }, + end: { + line: 2, + column: 26, + }, + }, + }, + { + type: 'Punctuator', + value: ',', + range: [41, 42], + loc: { + start: { + line: 2, + column: 26, + }, + end: { + line: 2, + column: 27, + }, + }, + }, + { + type: 'Identifier', + value: 'key', + range: [47, 50], + loc: { + start: { + line: 3, + column: 4, + }, + end: { + line: 3, + column: 7, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [50, 51], + loc: { + start: { + line: 3, + column: 7, + }, + end: { + line: 3, + column: 8, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [52, 53], + loc: { + start: { + line: 3, + column: 9, + }, + end: { + line: 3, + column: 10, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [54, 55], + loc: { + start: { + line: 3, + column: 11, + }, + end: { + line: 3, + column: 12, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [55, 56], + loc: { + start: { + line: 3, + column: 12, + }, + end: { + line: 3, + column: 13, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [56, 57], + loc: { + start: { + line: 3, + column: 13, + }, + end: { + line: 3, + column: 14, + }, + }, + }, + { + type: 'Keyword', + value: 'void', + range: [58, 62], + loc: { + start: { + line: 3, + column: 15, + }, + end: { + line: 3, + column: 19, + }, + }, + }, + { + type: 'Punctuator', + value: '=>', + range: [63, 65], + loc: { + start: { + line: 3, + column: 20, + }, + end: { + line: 3, + column: 22, + }, + }, + }, + { + type: 'Punctuator', + value: '{', + range: [66, 67], + loc: { + start: { + line: 3, + column: 23, + }, + end: { + line: 3, + column: 24, + }, + }, + }, + { + type: 'Identifier', + value: 'x', + range: [67, 68], + loc: { + start: { + line: 3, + column: 24, + }, + end: { + line: 3, + column: 25, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [68, 69], + loc: { + start: { + line: 3, + column: 25, + }, + end: { + line: 3, + column: 26, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [69, 70], + loc: { + start: { + line: 3, + column: 26, + }, + end: { + line: 3, + column: 27, + }, + }, + }, + { + type: 'Punctuator', + value: '}', + range: [70, 71], + loc: { + start: { + line: 3, + column: 27, + }, + end: { + line: 3, + column: 28, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [72, 73], + loc: { + start: { + line: 3, + column: 29, + }, + end: { + line: 3, + column: 30, + }, + }, + }, + { + type: 'Punctuator', + value: ',', + range: [73, 74], + loc: { + start: { + line: 3, + column: 30, + }, + end: { + line: 3, + column: 31, + }, + }, + }, + { + type: 'Identifier', + value: 'key', + range: [79, 82], + loc: { + start: { + line: 4, + column: 4, + }, + end: { + line: 4, + column: 7, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [82, 83], + loc: { + start: { + line: 4, + column: 7, + }, + end: { + line: 4, + column: 8, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [84, 85], + loc: { + start: { + line: 4, + column: 9, + }, + end: { + line: 4, + column: 10, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [86, 87], + loc: { + start: { + line: 4, + column: 11, + }, + end: { + line: 4, + column: 12, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [87, 88], + loc: { + start: { + line: 4, + column: 12, + }, + end: { + line: 4, + column: 13, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [88, 89], + loc: { + start: { + line: 4, + column: 13, + }, + end: { + line: 4, + column: 14, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [90, 91], + loc: { + start: { + line: 4, + column: 15, + }, + end: { + line: 4, + column: 16, + }, + }, + }, + { + type: 'Keyword', + value: 'void', + range: [91, 95], + loc: { + start: { + line: 4, + column: 16, + }, + end: { + line: 4, + column: 20, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [95, 96], + loc: { + start: { + line: 4, + column: 20, + }, + end: { + line: 4, + column: 21, + }, + }, + }, + { + type: 'Punctuator', + value: '=>', + range: [97, 99], + loc: { + start: { + line: 4, + column: 22, + }, + end: { + line: 4, + column: 24, + }, + }, + }, + { + type: 'Punctuator', + value: '{', + range: [100, 101], + loc: { + start: { + line: 4, + column: 25, + }, + end: { + line: 4, + column: 26, + }, + }, + }, + { + type: 'Identifier', + value: 'x', + range: [101, 102], + loc: { + start: { + line: 4, + column: 26, + }, + end: { + line: 4, + column: 27, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [102, 103], + loc: { + start: { + line: 4, + column: 27, + }, + end: { + line: 4, + column: 28, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [103, 104], + loc: { + start: { + line: 4, + column: 28, + }, + end: { + line: 4, + column: 29, + }, + }, + }, + { + type: 'Punctuator', + value: '}', + range: [104, 105], + loc: { + start: { + line: 4, + column: 29, + }, + end: { + line: 4, + column: 30, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [106, 107], + loc: { + start: { + line: 4, + column: 31, + }, + end: { + line: 4, + column: 32, + }, + }, + }, + { + type: 'Punctuator', + value: ',', + range: [107, 108], + loc: { + start: { + line: 4, + column: 32, + }, + end: { + line: 4, + column: 33, + }, + }, + }, + { + type: 'Identifier', + value: 'key', + range: [114, 117], + loc: { + start: { + line: 6, + column: 4, + }, + end: { + line: 6, + column: 7, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [117, 118], + loc: { + start: { + line: 6, + column: 7, + }, + end: { + line: 6, + column: 8, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [119, 120], + loc: { + start: { + line: 6, + column: 9, + }, + end: { + line: 6, + column: 10, + }, + }, + }, + { + type: 'Identifier', + value: 'arg', + range: [120, 123], + loc: { + start: { + line: 6, + column: 10, + }, + end: { + line: 6, + column: 13, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [123, 124], + loc: { + start: { + line: 6, + column: 13, + }, + end: { + line: 6, + column: 14, + }, + }, + }, + { + type: 'Identifier', + value: 't', + range: [125, 126], + loc: { + start: { + line: 6, + column: 15, + }, + end: { + line: 6, + column: 16, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [126, 127], + loc: { + start: { + line: 6, + column: 16, + }, + end: { + line: 6, + column: 17, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [127, 128], + loc: { + start: { + line: 6, + column: 17, + }, + end: { + line: 6, + column: 18, + }, + }, + }, + { + type: 'Keyword', + value: 'void', + range: [129, 133], + loc: { + start: { + line: 6, + column: 19, + }, + end: { + line: 6, + column: 23, + }, + }, + }, + { + type: 'Punctuator', + value: '=>', + range: [134, 136], + loc: { + start: { + line: 6, + column: 24, + }, + end: { + line: 6, + column: 26, + }, + }, + }, + { + type: 'Punctuator', + value: '{', + range: [137, 138], + loc: { + start: { + line: 6, + column: 27, + }, + end: { + line: 6, + column: 28, + }, + }, + }, + { + type: 'Identifier', + value: 'x', + range: [138, 139], + loc: { + start: { + line: 6, + column: 28, + }, + end: { + line: 6, + column: 29, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [139, 140], + loc: { + start: { + line: 6, + column: 29, + }, + end: { + line: 6, + column: 30, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [140, 141], + loc: { + start: { + line: 6, + column: 30, + }, + end: { + line: 6, + column: 31, + }, + }, + }, + { + type: 'Punctuator', + value: '}', + range: [141, 142], + loc: { + start: { + line: 6, + column: 31, + }, + end: { + line: 6, + column: 32, + }, + }, + }, + { + type: 'Punctuator', + value: ',', + range: [142, 143], + loc: { + start: { + line: 6, + column: 32, + }, + end: { + line: 6, + column: 33, + }, + }, + }, + { + type: 'Identifier', + value: 'key', + range: [148, 151], + loc: { + start: { + line: 7, + column: 4, + }, + end: { + line: 7, + column: 7, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [151, 152], + loc: { + start: { + line: 7, + column: 7, + }, + end: { + line: 7, + column: 8, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [153, 154], + loc: { + start: { + line: 7, + column: 9, + }, + end: { + line: 7, + column: 10, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [155, 156], + loc: { + start: { + line: 7, + column: 11, + }, + end: { + line: 7, + column: 12, + }, + }, + }, + { + type: 'Identifier', + value: 'arg', + range: [156, 159], + loc: { + start: { + line: 7, + column: 12, + }, + end: { + line: 7, + column: 15, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [159, 160], + loc: { + start: { + line: 7, + column: 15, + }, + end: { + line: 7, + column: 16, + }, + }, + }, + { + type: 'Identifier', + value: 't', + range: [161, 162], + loc: { + start: { + line: 7, + column: 17, + }, + end: { + line: 7, + column: 18, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [162, 163], + loc: { + start: { + line: 7, + column: 18, + }, + end: { + line: 7, + column: 19, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [163, 164], + loc: { + start: { + line: 7, + column: 19, + }, + end: { + line: 7, + column: 20, + }, + }, + }, + { + type: 'Keyword', + value: 'void', + range: [165, 169], + loc: { + start: { + line: 7, + column: 21, + }, + end: { + line: 7, + column: 25, + }, + }, + }, + { + type: 'Punctuator', + value: '=>', + range: [170, 172], + loc: { + start: { + line: 7, + column: 26, + }, + end: { + line: 7, + column: 28, + }, + }, + }, + { + type: 'Punctuator', + value: '{', + range: [173, 174], + loc: { + start: { + line: 7, + column: 29, + }, + end: { + line: 7, + column: 30, + }, + }, + }, + { + type: 'Identifier', + value: 'x', + range: [174, 175], + loc: { + start: { + line: 7, + column: 30, + }, + end: { + line: 7, + column: 31, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [175, 176], + loc: { + start: { + line: 7, + column: 31, + }, + end: { + line: 7, + column: 32, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [176, 177], + loc: { + start: { + line: 7, + column: 32, + }, + end: { + line: 7, + column: 33, + }, + }, + }, + { + type: 'Punctuator', + value: '}', + range: [177, 178], + loc: { + start: { + line: 7, + column: 33, + }, + end: { + line: 7, + column: 34, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [179, 180], + loc: { + start: { + line: 7, + column: 35, + }, + end: { + line: 7, + column: 36, + }, + }, + }, + { + type: 'Punctuator', + value: ',', + range: [180, 181], + loc: { + start: { + line: 7, + column: 36, + }, + end: { + line: 7, + column: 37, + }, + }, + }, + { + type: 'Identifier', + value: 'key', + range: [186, 189], + loc: { + start: { + line: 8, + column: 4, + }, + end: { + line: 8, + column: 7, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [189, 190], + loc: { + start: { + line: 8, + column: 7, + }, + end: { + line: 8, + column: 8, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [191, 192], + loc: { + start: { + line: 8, + column: 9, + }, + end: { + line: 8, + column: 10, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [193, 194], + loc: { + start: { + line: 8, + column: 11, + }, + end: { + line: 8, + column: 12, + }, + }, + }, + { + type: 'Identifier', + value: 'arg', + range: [194, 197], + loc: { + start: { + line: 8, + column: 12, + }, + end: { + line: 8, + column: 15, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [197, 198], + loc: { + start: { + line: 8, + column: 15, + }, + end: { + line: 8, + column: 16, + }, + }, + }, + { + type: 'Identifier', + value: 't', + range: [199, 200], + loc: { + start: { + line: 8, + column: 17, + }, + end: { + line: 8, + column: 18, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [200, 201], + loc: { + start: { + line: 8, + column: 18, + }, + end: { + line: 8, + column: 19, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [201, 202], + loc: { + start: { + line: 8, + column: 19, + }, + end: { + line: 8, + column: 20, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [203, 204], + loc: { + start: { + line: 8, + column: 21, + }, + end: { + line: 8, + column: 22, + }, + }, + }, + { + type: 'Keyword', + value: 'void', + range: [204, 208], + loc: { + start: { + line: 8, + column: 22, + }, + end: { + line: 8, + column: 26, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [208, 209], + loc: { + start: { + line: 8, + column: 26, + }, + end: { + line: 8, + column: 27, + }, + }, + }, + { + type: 'Punctuator', + value: '=>', + range: [210, 212], + loc: { + start: { + line: 8, + column: 28, + }, + end: { + line: 8, + column: 30, + }, + }, + }, + { + type: 'Punctuator', + value: '{', + range: [213, 214], + loc: { + start: { + line: 8, + column: 31, + }, + end: { + line: 8, + column: 32, + }, + }, + }, + { + type: 'Identifier', + value: 'x', + range: [214, 215], + loc: { + start: { + line: 8, + column: 32, + }, + end: { + line: 8, + column: 33, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [215, 216], + loc: { + start: { + line: 8, + column: 33, + }, + end: { + line: 8, + column: 34, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [216, 217], + loc: { + start: { + line: 8, + column: 34, + }, + end: { + line: 8, + column: 35, + }, + }, + }, + { + type: 'Punctuator', + value: '}', + range: [217, 218], + loc: { + start: { + line: 8, + column: 35, + }, + end: { + line: 8, + column: 36, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [219, 220], + loc: { + start: { + line: 8, + column: 37, + }, + end: { + line: 8, + column: 38, + }, + }, + }, + { + type: 'Punctuator', + value: ',', + range: [220, 221], + loc: { + start: { + line: 8, + column: 38, + }, + end: { + line: 8, + column: 39, + }, + }, + }, + { + type: 'Identifier', + value: 'key', + range: [227, 230], + loc: { + start: { + line: 10, + column: 4, + }, + end: { + line: 10, + column: 7, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [230, 231], + loc: { + start: { + line: 10, + column: 7, + }, + end: { + line: 10, + column: 8, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [232, 233], + loc: { + start: { + line: 10, + column: 9, + }, + end: { + line: 10, + column: 10, + }, + }, + }, + { + type: 'Identifier', + value: 'arg', + range: [233, 236], + loc: { + start: { + line: 10, + column: 10, + }, + end: { + line: 10, + column: 13, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [236, 237], + loc: { + start: { + line: 10, + column: 13, + }, + end: { + line: 10, + column: 14, + }, + }, + }, + { + type: 'Identifier', + value: 't', + range: [238, 239], + loc: { + start: { + line: 10, + column: 15, + }, + end: { + line: 10, + column: 16, + }, + }, + }, + { + type: 'Punctuator', + value: ',', + range: [239, 240], + loc: { + start: { + line: 10, + column: 16, + }, + end: { + line: 10, + column: 17, + }, + }, + }, + { + type: 'Identifier', + value: 'arg2', + range: [241, 245], + loc: { + start: { + line: 10, + column: 18, + }, + end: { + line: 10, + column: 22, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [245, 246], + loc: { + start: { + line: 10, + column: 22, + }, + end: { + line: 10, + column: 23, + }, + }, + }, + { + type: 'Identifier', + value: 't', + range: [247, 248], + loc: { + start: { + line: 10, + column: 24, + }, + end: { + line: 10, + column: 25, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [248, 249], + loc: { + start: { + line: 10, + column: 25, + }, + end: { + line: 10, + column: 26, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [249, 250], + loc: { + start: { + line: 10, + column: 26, + }, + end: { + line: 10, + column: 27, + }, + }, + }, + { + type: 'Keyword', + value: 'void', + range: [251, 255], + loc: { + start: { + line: 10, + column: 28, + }, + end: { + line: 10, + column: 32, + }, + }, + }, + { + type: 'Punctuator', + value: '=>', + range: [256, 258], + loc: { + start: { + line: 10, + column: 33, + }, + end: { + line: 10, + column: 35, + }, + }, + }, + { + type: 'Punctuator', + value: '{', + range: [259, 260], + loc: { + start: { + line: 10, + column: 36, + }, + end: { + line: 10, + column: 37, + }, + }, + }, + { + type: 'Identifier', + value: 'x', + range: [260, 261], + loc: { + start: { + line: 10, + column: 37, + }, + end: { + line: 10, + column: 38, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [261, 262], + loc: { + start: { + line: 10, + column: 38, + }, + end: { + line: 10, + column: 39, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [262, 263], + loc: { + start: { + line: 10, + column: 39, + }, + end: { + line: 10, + column: 40, + }, + }, + }, + { + type: 'Punctuator', + value: '}', + range: [263, 264], + loc: { + start: { + line: 10, + column: 40, + }, + end: { + line: 10, + column: 41, + }, + }, + }, + { + type: 'Punctuator', + value: ',', + range: [264, 265], + loc: { + start: { + line: 10, + column: 41, + }, + end: { + line: 10, + column: 42, + }, + }, + }, + { + type: 'Identifier', + value: 'key', + range: [270, 273], + loc: { + start: { + line: 11, + column: 4, + }, + end: { + line: 11, + column: 7, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [273, 274], + loc: { + start: { + line: 11, + column: 7, + }, + end: { + line: 11, + column: 8, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [275, 276], + loc: { + start: { + line: 11, + column: 9, + }, + end: { + line: 11, + column: 10, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [277, 278], + loc: { + start: { + line: 11, + column: 11, + }, + end: { + line: 11, + column: 12, + }, + }, + }, + { + type: 'Identifier', + value: 'arg', + range: [278, 281], + loc: { + start: { + line: 11, + column: 12, + }, + end: { + line: 11, + column: 15, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [281, 282], + loc: { + start: { + line: 11, + column: 15, + }, + end: { + line: 11, + column: 16, + }, + }, + }, + { + type: 'Identifier', + value: 't', + range: [283, 284], + loc: { + start: { + line: 11, + column: 17, + }, + end: { + line: 11, + column: 18, + }, + }, + }, + { + type: 'Punctuator', + value: ',', + range: [284, 285], + loc: { + start: { + line: 11, + column: 18, + }, + end: { + line: 11, + column: 19, + }, + }, + }, + { + type: 'Identifier', + value: 'arg2', + range: [286, 290], + loc: { + start: { + line: 11, + column: 20, + }, + end: { + line: 11, + column: 24, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [290, 291], + loc: { + start: { + line: 11, + column: 24, + }, + end: { + line: 11, + column: 25, + }, + }, + }, + { + type: 'Identifier', + value: 't', + range: [292, 293], + loc: { + start: { + line: 11, + column: 26, + }, + end: { + line: 11, + column: 27, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [293, 294], + loc: { + start: { + line: 11, + column: 27, + }, + end: { + line: 11, + column: 28, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [294, 295], + loc: { + start: { + line: 11, + column: 28, + }, + end: { + line: 11, + column: 29, + }, + }, + }, + { + type: 'Keyword', + value: 'void', + range: [296, 300], + loc: { + start: { + line: 11, + column: 30, + }, + end: { + line: 11, + column: 34, + }, + }, + }, + { + type: 'Punctuator', + value: '=>', + range: [301, 303], + loc: { + start: { + line: 11, + column: 35, + }, + end: { + line: 11, + column: 37, + }, + }, + }, + { + type: 'Punctuator', + value: '{', + range: [304, 305], + loc: { + start: { + line: 11, + column: 38, + }, + end: { + line: 11, + column: 39, + }, + }, + }, + { + type: 'Identifier', + value: 'x', + range: [305, 306], + loc: { + start: { + line: 11, + column: 39, + }, + end: { + line: 11, + column: 40, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [306, 307], + loc: { + start: { + line: 11, + column: 40, + }, + end: { + line: 11, + column: 41, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [307, 308], + loc: { + start: { + line: 11, + column: 41, + }, + end: { + line: 11, + column: 42, + }, + }, + }, + { + type: 'Punctuator', + value: '}', + range: [308, 309], + loc: { + start: { + line: 11, + column: 42, + }, + end: { + line: 11, + column: 43, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [310, 311], + loc: { + start: { + line: 11, + column: 44, + }, + end: { + line: 11, + column: 45, + }, + }, + }, + { + type: 'Punctuator', + value: ',', + range: [311, 312], + loc: { + start: { + line: 11, + column: 45, + }, + end: { + line: 11, + column: 46, + }, + }, + }, + { + type: 'Identifier', + value: 'key', + range: [317, 320], + loc: { + start: { + line: 12, + column: 4, + }, + end: { + line: 12, + column: 7, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [320, 321], + loc: { + start: { + line: 12, + column: 7, + }, + end: { + line: 12, + column: 8, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [322, 323], + loc: { + start: { + line: 12, + column: 9, + }, + end: { + line: 12, + column: 10, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [324, 325], + loc: { + start: { + line: 12, + column: 11, + }, + end: { + line: 12, + column: 12, + }, + }, + }, + { + type: 'Identifier', + value: 'arg', + range: [325, 328], + loc: { + start: { + line: 12, + column: 12, + }, + end: { + line: 12, + column: 15, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [328, 329], + loc: { + start: { + line: 12, + column: 15, + }, + end: { + line: 12, + column: 16, + }, + }, + }, + { + type: 'Identifier', + value: 't', + range: [330, 331], + loc: { + start: { + line: 12, + column: 17, + }, + end: { + line: 12, + column: 18, + }, + }, + }, + { + type: 'Punctuator', + value: ',', + range: [331, 332], + loc: { + start: { + line: 12, + column: 18, + }, + end: { + line: 12, + column: 19, + }, + }, + }, + { + type: 'Identifier', + value: 'arg2', + range: [333, 337], + loc: { + start: { + line: 12, + column: 20, + }, + end: { + line: 12, + column: 24, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [337, 338], + loc: { + start: { + line: 12, + column: 24, + }, + end: { + line: 12, + column: 25, + }, + }, + }, + { + type: 'Identifier', + value: 't', + range: [339, 340], + loc: { + start: { + line: 12, + column: 26, + }, + end: { + line: 12, + column: 27, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [340, 341], + loc: { + start: { + line: 12, + column: 27, + }, + end: { + line: 12, + column: 28, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [341, 342], + loc: { + start: { + line: 12, + column: 28, + }, + end: { + line: 12, + column: 29, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [343, 344], + loc: { + start: { + line: 12, + column: 30, + }, + end: { + line: 12, + column: 31, + }, + }, + }, + { + type: 'Keyword', + value: 'void', + range: [344, 348], + loc: { + start: { + line: 12, + column: 31, + }, + end: { + line: 12, + column: 35, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [348, 349], + loc: { + start: { + line: 12, + column: 35, + }, + end: { + line: 12, + column: 36, + }, + }, + }, + { + type: 'Punctuator', + value: '=>', + range: [350, 352], + loc: { + start: { + line: 12, + column: 37, + }, + end: { + line: 12, + column: 39, + }, + }, + }, + { + type: 'Punctuator', + value: '{', + range: [353, 354], + loc: { + start: { + line: 12, + column: 40, + }, + end: { + line: 12, + column: 41, + }, + }, + }, + { + type: 'Identifier', + value: 'x', + range: [354, 355], + loc: { + start: { + line: 12, + column: 41, + }, + end: { + line: 12, + column: 42, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [355, 356], + loc: { + start: { + line: 12, + column: 42, + }, + end: { + line: 12, + column: 43, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [356, 357], + loc: { + start: { + line: 12, + column: 43, + }, + end: { + line: 12, + column: 44, + }, + }, + }, + { + type: 'Punctuator', + value: '}', + range: [357, 358], + loc: { + start: { + line: 12, + column: 44, + }, + end: { + line: 12, + column: 45, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [359, 360], + loc: { + start: { + line: 12, + column: 46, + }, + end: { + line: 12, + column: 47, + }, + }, + }, + { + type: 'Punctuator', + value: ',', + range: [360, 361], + loc: { + start: { + line: 12, + column: 47, + }, + end: { + line: 12, + column: 48, + }, + }, + }, + { + type: 'Identifier', + value: 'key', + range: [367, 370], + loc: { + start: { + line: 14, + column: 4, + }, + end: { + line: 14, + column: 7, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [370, 371], + loc: { + start: { + line: 14, + column: 7, + }, + end: { + line: 14, + column: 8, + }, + }, + }, + { + type: 'Identifier', + value: 'async', + range: [372, 377], + loc: { + start: { + line: 14, + column: 9, + }, + end: { + line: 14, + column: 14, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [378, 379], + loc: { + start: { + line: 14, + column: 15, + }, + end: { + line: 14, + column: 16, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [379, 380], + loc: { + start: { + line: 14, + column: 16, + }, + end: { + line: 14, + column: 17, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [380, 381], + loc: { + start: { + line: 14, + column: 17, + }, + end: { + line: 14, + column: 18, + }, + }, + }, + { + type: 'Keyword', + value: 'void', + range: [382, 386], + loc: { + start: { + line: 14, + column: 19, + }, + end: { + line: 14, + column: 23, + }, + }, + }, + { + type: 'Punctuator', + value: '=>', + range: [387, 389], + loc: { + start: { + line: 14, + column: 24, + }, + end: { + line: 14, + column: 26, + }, + }, + }, + { + type: 'Punctuator', + value: '{', + range: [390, 391], + loc: { + start: { + line: 14, + column: 27, + }, + end: { + line: 14, + column: 28, + }, + }, + }, + { + type: 'Identifier', + value: 'x', + range: [391, 392], + loc: { + start: { + line: 14, + column: 28, + }, + end: { + line: 14, + column: 29, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [392, 393], + loc: { + start: { + line: 14, + column: 29, + }, + end: { + line: 14, + column: 30, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [393, 394], + loc: { + start: { + line: 14, + column: 30, + }, + end: { + line: 14, + column: 31, + }, + }, + }, + { + type: 'Punctuator', + value: '}', + range: [394, 395], + loc: { + start: { + line: 14, + column: 31, + }, + end: { + line: 14, + column: 32, + }, + }, + }, + { + type: 'Punctuator', + value: ',', + range: [395, 396], + loc: { + start: { + line: 14, + column: 32, + }, + end: { + line: 14, + column: 33, + }, + }, + }, + { + type: 'Identifier', + value: 'key', + range: [401, 404], + loc: { + start: { + line: 15, + column: 4, + }, + end: { + line: 15, + column: 7, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [404, 405], + loc: { + start: { + line: 15, + column: 7, + }, + end: { + line: 15, + column: 8, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [406, 407], + loc: { + start: { + line: 15, + column: 9, + }, + end: { + line: 15, + column: 10, + }, + }, + }, + { + type: 'Identifier', + value: 'async', + range: [408, 413], + loc: { + start: { + line: 15, + column: 11, + }, + end: { + line: 15, + column: 16, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [414, 415], + loc: { + start: { + line: 15, + column: 17, + }, + end: { + line: 15, + column: 18, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [415, 416], + loc: { + start: { + line: 15, + column: 18, + }, + end: { + line: 15, + column: 19, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [416, 417], + loc: { + start: { + line: 15, + column: 19, + }, + end: { + line: 15, + column: 20, + }, + }, + }, + { + type: 'Keyword', + value: 'void', + range: [418, 422], + loc: { + start: { + line: 15, + column: 21, + }, + end: { + line: 15, + column: 25, + }, + }, + }, + { + type: 'Punctuator', + value: '=>', + range: [423, 425], + loc: { + start: { + line: 15, + column: 26, + }, + end: { + line: 15, + column: 28, + }, + }, + }, + { + type: 'Punctuator', + value: '{', + range: [426, 427], + loc: { + start: { + line: 15, + column: 29, + }, + end: { + line: 15, + column: 30, + }, + }, + }, + { + type: 'Identifier', + value: 'x', + range: [427, 428], + loc: { + start: { + line: 15, + column: 30, + }, + end: { + line: 15, + column: 31, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [428, 429], + loc: { + start: { + line: 15, + column: 31, + }, + end: { + line: 15, + column: 32, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [429, 430], + loc: { + start: { + line: 15, + column: 32, + }, + end: { + line: 15, + column: 33, + }, + }, + }, + { + type: 'Punctuator', + value: '}', + range: [430, 431], + loc: { + start: { + line: 15, + column: 33, + }, + end: { + line: 15, + column: 34, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [432, 433], + loc: { + start: { + line: 15, + column: 35, + }, + end: { + line: 15, + column: 36, + }, + }, + }, + { + type: 'Punctuator', + value: ',', + range: [433, 434], + loc: { + start: { + line: 15, + column: 36, + }, + end: { + line: 15, + column: 37, + }, + }, + }, + { + type: 'Identifier', + value: 'key', + range: [439, 442], + loc: { + start: { + line: 16, + column: 4, + }, + end: { + line: 16, + column: 7, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [442, 443], + loc: { + start: { + line: 16, + column: 7, + }, + end: { + line: 16, + column: 8, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [444, 445], + loc: { + start: { + line: 16, + column: 9, + }, + end: { + line: 16, + column: 10, + }, + }, + }, + { + type: 'Identifier', + value: 'async', + range: [446, 451], + loc: { + start: { + line: 16, + column: 11, + }, + end: { + line: 16, + column: 16, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [452, 453], + loc: { + start: { + line: 16, + column: 17, + }, + end: { + line: 16, + column: 18, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [453, 454], + loc: { + start: { + line: 16, + column: 18, + }, + end: { + line: 16, + column: 19, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [454, 455], + loc: { + start: { + line: 16, + column: 19, + }, + end: { + line: 16, + column: 20, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [456, 457], + loc: { + start: { + line: 16, + column: 21, + }, + end: { + line: 16, + column: 22, + }, + }, + }, + { + type: 'Keyword', + value: 'void', + range: [457, 461], + loc: { + start: { + line: 16, + column: 22, + }, + end: { + line: 16, + column: 26, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [461, 462], + loc: { + start: { + line: 16, + column: 26, + }, + end: { + line: 16, + column: 27, + }, + }, + }, + { + type: 'Punctuator', + value: '=>', + range: [463, 465], + loc: { + start: { + line: 16, + column: 28, + }, + end: { + line: 16, + column: 30, + }, + }, + }, + { + type: 'Punctuator', + value: '{', + range: [466, 467], + loc: { + start: { + line: 16, + column: 31, + }, + end: { + line: 16, + column: 32, + }, + }, + }, + { + type: 'Identifier', + value: 'x', + range: [467, 468], + loc: { + start: { + line: 16, + column: 32, + }, + end: { + line: 16, + column: 33, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [468, 469], + loc: { + start: { + line: 16, + column: 33, + }, + end: { + line: 16, + column: 34, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [469, 470], + loc: { + start: { + line: 16, + column: 34, + }, + end: { + line: 16, + column: 35, + }, + }, + }, + { + type: 'Punctuator', + value: '}', + range: [470, 471], + loc: { + start: { + line: 16, + column: 35, + }, + end: { + line: 16, + column: 36, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [472, 473], + loc: { + start: { + line: 16, + column: 37, + }, + end: { + line: 16, + column: 38, + }, + }, + }, + { + type: 'Punctuator', + value: ',', + range: [473, 474], + loc: { + start: { + line: 16, + column: 38, + }, + end: { + line: 16, + column: 39, + }, + }, + }, + { + type: 'Identifier', + value: 'key', + range: [480, 483], + loc: { + start: { + line: 18, + column: 4, + }, + end: { + line: 18, + column: 7, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [483, 484], + loc: { + start: { + line: 18, + column: 7, + }, + end: { + line: 18, + column: 8, + }, + }, + }, + { + type: 'Identifier', + value: 'async', + range: [485, 490], + loc: { + start: { + line: 18, + column: 9, + }, + end: { + line: 18, + column: 14, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [491, 492], + loc: { + start: { + line: 18, + column: 15, + }, + end: { + line: 18, + column: 16, + }, + }, + }, + { + type: 'Identifier', + value: 'arg', + range: [492, 495], + loc: { + start: { + line: 18, + column: 16, + }, + end: { + line: 18, + column: 19, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [495, 496], + loc: { + start: { + line: 18, + column: 19, + }, + end: { + line: 18, + column: 20, + }, + }, + }, + { + type: 'Identifier', + value: 't', + range: [497, 498], + loc: { + start: { + line: 18, + column: 21, + }, + end: { + line: 18, + column: 22, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [498, 499], + loc: { + start: { + line: 18, + column: 22, + }, + end: { + line: 18, + column: 23, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [499, 500], + loc: { + start: { + line: 18, + column: 23, + }, + end: { + line: 18, + column: 24, + }, + }, + }, + { + type: 'Keyword', + value: 'void', + range: [501, 505], + loc: { + start: { + line: 18, + column: 25, + }, + end: { + line: 18, + column: 29, + }, + }, + }, + { + type: 'Punctuator', + value: '=>', + range: [506, 508], + loc: { + start: { + line: 18, + column: 30, + }, + end: { + line: 18, + column: 32, + }, + }, + }, + { + type: 'Punctuator', + value: '{', + range: [509, 510], + loc: { + start: { + line: 18, + column: 33, + }, + end: { + line: 18, + column: 34, + }, + }, + }, + { + type: 'Identifier', + value: 'x', + range: [510, 511], + loc: { + start: { + line: 18, + column: 34, + }, + end: { + line: 18, + column: 35, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [511, 512], + loc: { + start: { + line: 18, + column: 35, + }, + end: { + line: 18, + column: 36, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [512, 513], + loc: { + start: { + line: 18, + column: 36, + }, + end: { + line: 18, + column: 37, + }, + }, + }, + { + type: 'Punctuator', + value: '}', + range: [513, 514], + loc: { + start: { + line: 18, + column: 37, + }, + end: { + line: 18, + column: 38, + }, + }, + }, + { + type: 'Punctuator', + value: ',', + range: [514, 515], + loc: { + start: { + line: 18, + column: 38, + }, + end: { + line: 18, + column: 39, + }, + }, + }, + { + type: 'Identifier', + value: 'key', + range: [520, 523], + loc: { + start: { + line: 19, + column: 4, + }, + end: { + line: 19, + column: 7, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [523, 524], + loc: { + start: { + line: 19, + column: 7, + }, + end: { + line: 19, + column: 8, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [525, 526], + loc: { + start: { + line: 19, + column: 9, + }, + end: { + line: 19, + column: 10, + }, + }, + }, + { + type: 'Identifier', + value: 'async', + range: [527, 532], + loc: { + start: { + line: 19, + column: 11, + }, + end: { + line: 19, + column: 16, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [533, 534], + loc: { + start: { + line: 19, + column: 17, + }, + end: { + line: 19, + column: 18, + }, + }, + }, + { + type: 'Identifier', + value: 'arg', + range: [534, 537], + loc: { + start: { + line: 19, + column: 18, + }, + end: { + line: 19, + column: 21, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [537, 538], + loc: { + start: { + line: 19, + column: 21, + }, + end: { + line: 19, + column: 22, + }, + }, + }, + { + type: 'Identifier', + value: 't', + range: [539, 540], + loc: { + start: { + line: 19, + column: 23, + }, + end: { + line: 19, + column: 24, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [540, 541], + loc: { + start: { + line: 19, + column: 24, + }, + end: { + line: 19, + column: 25, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [541, 542], + loc: { + start: { + line: 19, + column: 25, + }, + end: { + line: 19, + column: 26, + }, + }, + }, + { + type: 'Keyword', + value: 'void', + range: [543, 547], + loc: { + start: { + line: 19, + column: 27, + }, + end: { + line: 19, + column: 31, + }, + }, + }, + { + type: 'Punctuator', + value: '=>', + range: [548, 550], + loc: { + start: { + line: 19, + column: 32, + }, + end: { + line: 19, + column: 34, + }, + }, + }, + { + type: 'Punctuator', + value: '{', + range: [551, 552], + loc: { + start: { + line: 19, + column: 35, + }, + end: { + line: 19, + column: 36, + }, + }, + }, + { + type: 'Identifier', + value: 'x', + range: [552, 553], + loc: { + start: { + line: 19, + column: 36, + }, + end: { + line: 19, + column: 37, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [553, 554], + loc: { + start: { + line: 19, + column: 37, + }, + end: { + line: 19, + column: 38, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [554, 555], + loc: { + start: { + line: 19, + column: 38, + }, + end: { + line: 19, + column: 39, + }, + }, + }, + { + type: 'Punctuator', + value: '}', + range: [555, 556], + loc: { + start: { + line: 19, + column: 39, + }, + end: { + line: 19, + column: 40, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [557, 558], + loc: { + start: { + line: 19, + column: 41, + }, + end: { + line: 19, + column: 42, + }, + }, + }, + { + type: 'Punctuator', + value: ',', + range: [558, 559], + loc: { + start: { + line: 19, + column: 42, + }, + end: { + line: 19, + column: 43, + }, + }, + }, + { + type: 'Identifier', + value: 'key', + range: [564, 567], + loc: { + start: { + line: 20, + column: 4, + }, + end: { + line: 20, + column: 7, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [567, 568], + loc: { + start: { + line: 20, + column: 7, + }, + end: { + line: 20, + column: 8, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [569, 570], + loc: { + start: { + line: 20, + column: 9, + }, + end: { + line: 20, + column: 10, + }, + }, + }, + { + type: 'Identifier', + value: 'async', + range: [571, 576], + loc: { + start: { + line: 20, + column: 11, + }, + end: { + line: 20, + column: 16, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [577, 578], + loc: { + start: { + line: 20, + column: 17, + }, + end: { + line: 20, + column: 18, + }, + }, + }, + { + type: 'Identifier', + value: 'arg', + range: [578, 581], + loc: { + start: { + line: 20, + column: 18, + }, + end: { + line: 20, + column: 21, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [581, 582], + loc: { + start: { + line: 20, + column: 21, + }, + end: { + line: 20, + column: 22, + }, + }, + }, + { + type: 'Identifier', + value: 't', + range: [583, 584], + loc: { + start: { + line: 20, + column: 23, + }, + end: { + line: 20, + column: 24, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [584, 585], + loc: { + start: { + line: 20, + column: 24, + }, + end: { + line: 20, + column: 25, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [585, 586], + loc: { + start: { + line: 20, + column: 25, + }, + end: { + line: 20, + column: 26, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [587, 588], + loc: { + start: { + line: 20, + column: 27, + }, + end: { + line: 20, + column: 28, + }, + }, + }, + { + type: 'Keyword', + value: 'void', + range: [588, 592], + loc: { + start: { + line: 20, + column: 28, + }, + end: { + line: 20, + column: 32, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [592, 593], + loc: { + start: { + line: 20, + column: 32, + }, + end: { + line: 20, + column: 33, + }, + }, + }, + { + type: 'Punctuator', + value: '=>', + range: [594, 596], + loc: { + start: { + line: 20, + column: 34, + }, + end: { + line: 20, + column: 36, + }, + }, + }, + { + type: 'Punctuator', + value: '{', + range: [597, 598], + loc: { + start: { + line: 20, + column: 37, + }, + end: { + line: 20, + column: 38, + }, + }, + }, + { + type: 'Identifier', + value: 'x', + range: [598, 599], + loc: { + start: { + line: 20, + column: 38, + }, + end: { + line: 20, + column: 39, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [599, 600], + loc: { + start: { + line: 20, + column: 39, + }, + end: { + line: 20, + column: 40, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [600, 601], + loc: { + start: { + line: 20, + column: 40, + }, + end: { + line: 20, + column: 41, + }, + }, + }, + { + type: 'Punctuator', + value: '}', + range: [601, 602], + loc: { + start: { + line: 20, + column: 41, + }, + end: { + line: 20, + column: 42, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [603, 604], + loc: { + start: { + line: 20, + column: 43, + }, + end: { + line: 20, + column: 44, + }, + }, + }, + { + type: 'Punctuator', + value: ',', + range: [604, 605], + loc: { + start: { + line: 20, + column: 44, + }, + end: { + line: 20, + column: 45, + }, + }, + }, + { + type: 'Identifier', + value: 'key', + range: [611, 614], + loc: { + start: { + line: 22, + column: 4, + }, + end: { + line: 22, + column: 7, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [614, 615], + loc: { + start: { + line: 22, + column: 7, + }, + end: { + line: 22, + column: 8, + }, + }, + }, + { + type: 'Identifier', + value: 'async', + range: [616, 621], + loc: { + start: { + line: 22, + column: 9, + }, + end: { + line: 22, + column: 14, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [622, 623], + loc: { + start: { + line: 22, + column: 15, + }, + end: { + line: 22, + column: 16, + }, + }, + }, + { + type: 'Identifier', + value: 'arg', + range: [623, 626], + loc: { + start: { + line: 22, + column: 16, + }, + end: { + line: 22, + column: 19, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [626, 627], + loc: { + start: { + line: 22, + column: 19, + }, + end: { + line: 22, + column: 20, + }, + }, + }, + { + type: 'Identifier', + value: 't', + range: [628, 629], + loc: { + start: { + line: 22, + column: 21, + }, + end: { + line: 22, + column: 22, + }, + }, + }, + { + type: 'Punctuator', + value: ',', + range: [629, 630], + loc: { + start: { + line: 22, + column: 22, + }, + end: { + line: 22, + column: 23, + }, + }, + }, + { + type: 'Identifier', + value: 'arg2', + range: [631, 635], + loc: { + start: { + line: 22, + column: 24, + }, + end: { + line: 22, + column: 28, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [635, 636], + loc: { + start: { + line: 22, + column: 28, + }, + end: { + line: 22, + column: 29, + }, + }, + }, + { + type: 'Identifier', + value: 't', + range: [637, 638], + loc: { + start: { + line: 22, + column: 30, + }, + end: { + line: 22, + column: 31, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [638, 639], + loc: { + start: { + line: 22, + column: 31, + }, + end: { + line: 22, + column: 32, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [639, 640], + loc: { + start: { + line: 22, + column: 32, + }, + end: { + line: 22, + column: 33, + }, + }, + }, + { + type: 'Keyword', + value: 'void', + range: [641, 645], + loc: { + start: { + line: 22, + column: 34, + }, + end: { + line: 22, + column: 38, + }, + }, + }, + { + type: 'Punctuator', + value: '=>', + range: [646, 648], + loc: { + start: { + line: 22, + column: 39, + }, + end: { + line: 22, + column: 41, + }, + }, + }, + { + type: 'Punctuator', + value: '{', + range: [649, 650], + loc: { + start: { + line: 22, + column: 42, + }, + end: { + line: 22, + column: 43, + }, + }, + }, + { + type: 'Identifier', + value: 'x', + range: [650, 651], + loc: { + start: { + line: 22, + column: 43, + }, + end: { + line: 22, + column: 44, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [651, 652], + loc: { + start: { + line: 22, + column: 44, + }, + end: { + line: 22, + column: 45, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [652, 653], + loc: { + start: { + line: 22, + column: 45, + }, + end: { + line: 22, + column: 46, + }, + }, + }, + { + type: 'Punctuator', + value: '}', + range: [653, 654], + loc: { + start: { + line: 22, + column: 46, + }, + end: { + line: 22, + column: 47, + }, + }, + }, + { + type: 'Punctuator', + value: ',', + range: [654, 655], + loc: { + start: { + line: 22, + column: 47, + }, + end: { + line: 22, + column: 48, + }, + }, + }, + { + type: 'Identifier', + value: 'key', + range: [660, 663], + loc: { + start: { + line: 23, + column: 4, + }, + end: { + line: 23, + column: 7, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [663, 664], + loc: { + start: { + line: 23, + column: 7, + }, + end: { + line: 23, + column: 8, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [665, 666], + loc: { + start: { + line: 23, + column: 9, + }, + end: { + line: 23, + column: 10, + }, + }, + }, + { + type: 'Identifier', + value: 'async', + range: [667, 672], + loc: { + start: { + line: 23, + column: 11, + }, + end: { + line: 23, + column: 16, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [673, 674], + loc: { + start: { + line: 23, + column: 17, + }, + end: { + line: 23, + column: 18, + }, + }, + }, + { + type: 'Identifier', + value: 'arg', + range: [674, 677], + loc: { + start: { + line: 23, + column: 18, + }, + end: { + line: 23, + column: 21, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [677, 678], + loc: { + start: { + line: 23, + column: 21, + }, + end: { + line: 23, + column: 22, + }, + }, + }, + { + type: 'Identifier', + value: 't', + range: [679, 680], + loc: { + start: { + line: 23, + column: 23, + }, + end: { + line: 23, + column: 24, + }, + }, + }, + { + type: 'Punctuator', + value: ',', + range: [680, 681], + loc: { + start: { + line: 23, + column: 24, + }, + end: { + line: 23, + column: 25, + }, + }, + }, + { + type: 'Identifier', + value: 'arg2', + range: [682, 686], + loc: { + start: { + line: 23, + column: 26, + }, + end: { + line: 23, + column: 30, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [686, 687], + loc: { + start: { + line: 23, + column: 30, + }, + end: { + line: 23, + column: 31, + }, + }, + }, + { + type: 'Identifier', + value: 't', + range: [688, 689], + loc: { + start: { + line: 23, + column: 32, + }, + end: { + line: 23, + column: 33, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [689, 690], + loc: { + start: { + line: 23, + column: 33, + }, + end: { + line: 23, + column: 34, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [690, 691], + loc: { + start: { + line: 23, + column: 34, + }, + end: { + line: 23, + column: 35, + }, + }, + }, + { + type: 'Keyword', + value: 'void', + range: [692, 696], + loc: { + start: { + line: 23, + column: 36, + }, + end: { + line: 23, + column: 40, + }, + }, + }, + { + type: 'Punctuator', + value: '=>', + range: [697, 699], + loc: { + start: { + line: 23, + column: 41, + }, + end: { + line: 23, + column: 43, + }, + }, + }, + { + type: 'Punctuator', + value: '{', + range: [700, 701], + loc: { + start: { + line: 23, + column: 44, + }, + end: { + line: 23, + column: 45, + }, + }, + }, + { + type: 'Identifier', + value: 'x', + range: [701, 702], + loc: { + start: { + line: 23, + column: 45, + }, + end: { + line: 23, + column: 46, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [702, 703], + loc: { + start: { + line: 23, + column: 46, + }, + end: { + line: 23, + column: 47, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [703, 704], + loc: { + start: { + line: 23, + column: 47, + }, + end: { + line: 23, + column: 48, + }, + }, + }, + { + type: 'Punctuator', + value: '}', + range: [704, 705], + loc: { + start: { + line: 23, + column: 48, + }, + end: { + line: 23, + column: 49, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [706, 707], + loc: { + start: { + line: 23, + column: 50, + }, + end: { + line: 23, + column: 51, + }, + }, + }, + { + type: 'Punctuator', + value: ',', + range: [707, 708], + loc: { + start: { + line: 23, + column: 51, + }, + end: { + line: 23, + column: 52, + }, + }, + }, + { + type: 'Identifier', + value: 'key', + range: [713, 716], + loc: { + start: { + line: 24, + column: 4, + }, + end: { + line: 24, + column: 7, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [716, 717], + loc: { + start: { + line: 24, + column: 7, + }, + end: { + line: 24, + column: 8, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [718, 719], + loc: { + start: { + line: 24, + column: 9, + }, + end: { + line: 24, + column: 10, + }, + }, + }, + { + type: 'Identifier', + value: 'async', + range: [720, 725], + loc: { + start: { + line: 24, + column: 11, + }, + end: { + line: 24, + column: 16, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [726, 727], + loc: { + start: { + line: 24, + column: 17, + }, + end: { + line: 24, + column: 18, + }, + }, + }, + { + type: 'Identifier', + value: 'arg', + range: [727, 730], + loc: { + start: { + line: 24, + column: 18, + }, + end: { + line: 24, + column: 21, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [730, 731], + loc: { + start: { + line: 24, + column: 21, + }, + end: { + line: 24, + column: 22, + }, + }, + }, + { + type: 'Identifier', + value: 't', + range: [732, 733], + loc: { + start: { + line: 24, + column: 23, + }, + end: { + line: 24, + column: 24, + }, + }, + }, + { + type: 'Punctuator', + value: ',', + range: [733, 734], + loc: { + start: { + line: 24, + column: 24, + }, + end: { + line: 24, + column: 25, + }, + }, + }, + { + type: 'Identifier', + value: 'arg2', + range: [735, 739], + loc: { + start: { + line: 24, + column: 26, + }, + end: { + line: 24, + column: 30, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [739, 740], + loc: { + start: { + line: 24, + column: 30, + }, + end: { + line: 24, + column: 31, + }, + }, + }, + { + type: 'Identifier', + value: 't', + range: [741, 742], + loc: { + start: { + line: 24, + column: 32, + }, + end: { + line: 24, + column: 33, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [742, 743], + loc: { + start: { + line: 24, + column: 33, + }, + end: { + line: 24, + column: 34, + }, + }, + }, + { + type: 'Punctuator', + value: ':', + range: [743, 744], + loc: { + start: { + line: 24, + column: 34, + }, + end: { + line: 24, + column: 35, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [745, 746], + loc: { + start: { + line: 24, + column: 36, + }, + end: { + line: 24, + column: 37, + }, + }, + }, + { + type: 'Keyword', + value: 'void', + range: [746, 750], + loc: { + start: { + line: 24, + column: 37, + }, + end: { + line: 24, + column: 41, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [750, 751], + loc: { + start: { + line: 24, + column: 41, + }, + end: { + line: 24, + column: 42, + }, + }, + }, + { + type: 'Punctuator', + value: '=>', + range: [752, 754], + loc: { + start: { + line: 24, + column: 43, + }, + end: { + line: 24, + column: 45, + }, + }, + }, + { + type: 'Punctuator', + value: '{', + range: [755, 756], + loc: { + start: { + line: 24, + column: 46, + }, + end: { + line: 24, + column: 47, + }, + }, + }, + { + type: 'Identifier', + value: 'x', + range: [756, 757], + loc: { + start: { + line: 24, + column: 47, + }, + end: { + line: 24, + column: 48, + }, + }, + }, + { + type: 'Punctuator', + value: '(', + range: [757, 758], + loc: { + start: { + line: 24, + column: 48, + }, + end: { + line: 24, + column: 49, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [758, 759], + loc: { + start: { + line: 24, + column: 49, + }, + end: { + line: 24, + column: 50, + }, + }, + }, + { + type: 'Punctuator', + value: '}', + range: [759, 760], + loc: { + start: { + line: 24, + column: 50, + }, + end: { + line: 24, + column: 51, + }, + }, + }, + { + type: 'Punctuator', + value: ')', + range: [761, 762], + loc: { + start: { + line: 24, + column: 52, + }, + end: { + line: 24, + column: 53, + }, + }, + }, + { + type: 'Punctuator', + value: ',', + range: [762, 763], + loc: { + start: { + line: 24, + column: 53, + }, + end: { + line: 24, + column: 54, + }, + }, + }, + { + type: 'Punctuator', + value: '}', + range: [764, 765], + loc: { + start: { + line: 25, + column: 0, + }, + end: { + line: 25, + column: 1, + }, + }, + }, + ], + comments: [], +}); diff --git a/tests/lib/cli-engine/cli-engine.js b/tests/lib/cli-engine/cli-engine.js index 75f8a8fdba5..b06a5be3190 100644 --- a/tests/lib/cli-engine/cli-engine.js +++ b/tests/lib/cli-engine/cli-engine.js @@ -1641,6 +1641,8 @@ describe("CLIEngine", () => { { column: 9, line: 2, + endColumn: 11, + endLine: 2, message: "Expected '===' and instead saw '=='.", messageId: "unexpected", nodeType: "BinaryExpression", diff --git a/tests/lib/rules/accessor-pairs.js b/tests/lib/rules/accessor-pairs.js index 4f55cd10eb7..c647a37f3a0 100644 --- a/tests/lib/rules/accessor-pairs.js +++ b/tests/lib/rules/accessor-pairs.js @@ -43,6 +43,10 @@ ruleTester.run("accessor-pairs", rule, { // Test default settings, this would be an error if `getWithoutSet` was set to `true` "var o = { get a() {} }", + { + code: "var o = { get a() {} }", + options: [{}] + }, // No accessors { @@ -319,7 +323,315 @@ ruleTester.run("accessor-pairs", rule, { "Object.create(null, {set: {value: function() {}}});", { code: "var o = {get: function() {}}", options: [{ getWithoutSet: true }] }, { code: "var o = {[set]: function() {}}", parserOptions: { ecmaVersion: 6 } }, - { code: "var set = 'value'; Object.defineProperty(obj, 'foo', {[set]: function(value) {}});", parserOptions: { ecmaVersion: 6 } } + { code: "var set = 'value'; Object.defineProperty(obj, 'foo', {[set]: function(value) {}});", parserOptions: { ecmaVersion: 6 } }, + + //------------------------------------------------------------------------------ + // Classes + //------------------------------------------------------------------------------ + + // Test default settings + { + code: "class A { set a(foo) {} }", + parserOptions: { ecmaVersion: 6 } + }, + { + code: "class A { get a() {} set b(foo) {} }", + options: [{}], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "class A { get a() {} }", + options: [{ enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "class A { get a() {} }", + options: [{ setWithoutGet: true, getWithoutSet: true }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "class A { set a(foo) {} }", + options: [{ setWithoutGet: true, getWithoutSet: true }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "class A { static get a() {} }", + options: [{ setWithoutGet: true, getWithoutSet: true }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "class A { static set a(foo) {} }", + options: [{ setWithoutGet: true, getWithoutSet: true }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "A = class { get a() {} };", + options: [{ setWithoutGet: true, getWithoutSet: true }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "A = class { get a() {} set b(foo) {} };", + options: [{ setWithoutGet: true, getWithoutSet: true }], + parserOptions: { ecmaVersion: 6 } + }, + + // Explicitly disabled option + { + code: "class A { set a(foo) {} }", + options: [{ enforceForClassMembers: false }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "class A { get a() {} set b(foo) {} static get c() {} static set d(bar) {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: false }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "(class A { get a() {} set b(foo) {} static get c() {} static set d(bar) {} });", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: false }], + parserOptions: { ecmaVersion: 6 } + }, + + // Disabled accessor kind options + { + code: "class A { get a() {} }", + options: [{ setWithoutGet: true, getWithoutSet: false, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "class A { set a(foo) {} }", + options: [{ setWithoutGet: false, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "class A { static get a() {} }", + options: [{ setWithoutGet: true, getWithoutSet: false, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "class A { static set a(foo) {} }", + options: [{ setWithoutGet: false, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "A = class { set a(foo) {} };", + options: [{ setWithoutGet: false, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "class A { get a() {} set b(foo) {} static get c() {} static set d(bar) {} }", + options: [{ setWithoutGet: false, getWithoutSet: false, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + }, + + // No accessors + { + code: "class A {}", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "(class {})", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "class A { constructor () {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "class A { a() {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "class A { static a() {} 'b'() {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "class A { [a]() {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "A = class { a() {} static a() {} b() {} static c() {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + }, + + // Valid pairs with identifiers + { + code: "class A { get a() {} set a(foo) {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "class A { set a(foo) {} get a() {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "class A { static get a() {} static set a(foo) {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "class A { static set a(foo) {} static get a() {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "(class { set a(foo) {} get a() {} });", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + }, + + // Valid pairs with statically computed names + { + code: "class A { get 'a'() {} set ['a'](foo) {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "class A { set [`a`](foo) {} get a() {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "class A { get 'a'() {} set a(foo) {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "A = class { static get 1e2() {} static set [100](foo) {} };", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + }, + + // Valid pairs with expressions + { + code: "class A { get [a]() {} set [a](foo) {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "A = class { set [(f())](foo) {} get [(f())]() {} };", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "class A { static set [f(a)](foo) {} static get [f(a)]() {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + }, + + // Multiple valid pairs in the same class + { + code: "class A { get a() {} set b(foo) {} set a(bar) {} get b() {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "class A { get a() {} set a(bar) {} b() {} set c(foo) {} get c() {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "(class { get a() {} static set a(foo) {} set a(bar) {} static get a() {} });", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + }, + + // Valid pairs with other elements + { + code: "class A { get a() {} b() {} set a(foo) {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "class A { set a(foo) {} get a() {} b() {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "class A { a() {} get b() {} c() {} set b(foo) {} d() {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "class A { get a() {} set a(foo) {} static a() {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "A = class { static get a() {} static b() {} static set a(foo) {} };", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "A = class { static set a(foo) {} static get a() {} a() {} };", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + }, + + // Duplicate keys. This is the responsibility of no-dupe-class-members, but this rule still checks if there is the other accessor kind. + { + code: "class A { get a() {} get a() {} set a(foo) {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "class A { get [a]() {} set [a](foo) {} set [a](foo) {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "class A { get a() {} set 'a'(foo) {} get [`a`]() {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "A = class { get a() {} set a(foo) {} a() {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "A = class { a() {} get a() {} set a(foo) {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "class A { static set a(foo) {} static set a(foo) {} static get a() {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "class A { static get a() {} static set a(foo) {} static get a() {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "class A { static set a(foo) {} static get a() {} static a() {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + }, + + /* + * This code should be invalid by this rule because it creates a class with the setter only, while the getter is ignored. + * However, this edge case is not covered, it should be reported by no-dupe-class-members anyway. + */ + { + code: "class A { get a() {} a() {} set a(foo) {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "class A { static set a(foo) {} static a() {} static get a() {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + } ], invalid: [ @@ -333,6 +645,11 @@ ruleTester.run("accessor-pairs", rule, { code: "var o = { set a(value) {} };", errors: [{ message: "Getter is not present for setter 'a'.", type: "Property" }] }, + { + code: "var o = { set a(value) {} };", + options: [{}], + errors: [{ message: "Getter is not present for setter 'a'.", type: "Property" }] + }, // Test that the options do not affect each other { @@ -530,7 +847,7 @@ ruleTester.run("accessor-pairs", rule, { code: "var o = { get ''() {}, set ' '(foo) {} };", options: [{ setWithoutGet: true, getWithoutSet: true }], errors: [ - { messageId: "missingSetterInObjectLiteral", type: "Property", column: 11 }, // TODO: Change to message when getFunctionNameWithKind gets fixed + { message: "Setter is not present for getter ''.", type: "Property", column: 11 }, { message: "Getter is not present for setter ' '.", type: "Property", column: 24 } ] }, @@ -538,7 +855,7 @@ ruleTester.run("accessor-pairs", rule, { code: "var o = { get ''() {}, set null(foo) {} };", options: [{ setWithoutGet: true, getWithoutSet: true }], errors: [ - { messageId: "missingSetterInObjectLiteral", type: "Property", column: 11 }, // TODO: Change to message when getFunctionNameWithKind gets fixed + { message: "Setter is not present for getter ''.", type: "Property", column: 11 }, { message: "Getter is not present for setter 'null'.", type: "Property", column: 24 } ] }, @@ -766,7 +1083,6 @@ ruleTester.run("accessor-pairs", rule, { { code: "var o = { get a() {} };", options: [{ setWithoutGet: true, getWithoutSet: true }], - parserOptions: { ecmaVersion: 2018 }, errors: [{ message: "Setter is not present for getter 'a'.", type: "Property", @@ -779,7 +1095,7 @@ ruleTester.run("accessor-pairs", rule, { { code: "var o = {\n set [\n a](foo) {} };", options: [{ setWithoutGet: true, getWithoutSet: true }], - parserOptions: { ecmaVersion: 2018 }, + parserOptions: { ecmaVersion: 2015 }, errors: [{ message: "Getter is not present for setter.", type: "Property", @@ -809,6 +1125,605 @@ ruleTester.run("accessor-pairs", rule, { { code: "Object.create(null, {foo: {set: function(value) {}}});", errors: [{ message: "Getter is not present in property descriptor.", type: "ObjectExpression" }] + }, + + //------------------------------------------------------------------------------ + // Classes + //------------------------------------------------------------------------------ + + // Test default settings + { + code: "class A { set a(value) {} }", + options: [{ enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [{ message: "Getter is not present for class setter 'a'.", type: "MethodDefinition" }] + }, + { + code: "class A { static set a(value) {} }", + options: [{ enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [{ message: "Getter is not present for class static setter 'a'.", type: "MethodDefinition" }] + }, + { + code: "A = class { set a(value) {} };", + options: [{ enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [{ message: "Getter is not present for class setter 'a'.", type: "MethodDefinition" }] + }, + { + code: "(class A { static set a(value) {} });", + options: [{ enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [{ message: "Getter is not present for class static setter 'a'.", type: "MethodDefinition" }] + }, + + // Test that the accessor kind options do not affect each other + { + code: "class A { set a(value) {} }", + options: [{ setWithoutGet: true, getWithoutSet: false, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [{ message: "Getter is not present for class setter 'a'.", type: "MethodDefinition" }] + }, + { + code: "A = class { static set a(value) {} };", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [{ message: "Getter is not present for class static setter 'a'.", type: "MethodDefinition" }] + }, + { + code: "let foo = class A { get a() {} };", + options: [{ setWithoutGet: false, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [{ message: "Setter is not present for class getter 'a'.", type: "MethodDefinition" }] + }, + { + code: "class A { static get a() {} };", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [{ message: "Setter is not present for class static getter 'a'.", type: "MethodDefinition" }] + }, + { + code: "(class { get a() {} });", + options: [{ getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [{ message: "Setter is not present for class getter 'a'.", type: "MethodDefinition" }] + }, + + // Various kinds of keys + { + code: "class A { get abc() {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [{ message: "Setter is not present for class getter 'abc'.", type: "MethodDefinition" }] + }, + { + code: "A = class { static set 'abc'(foo) {} };", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [{ message: "Getter is not present for class static setter 'abc'.", type: "MethodDefinition" }] + }, + { + code: "(class { get 123() {} });", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [{ message: "Setter is not present for class getter '123'.", type: "MethodDefinition" }] + }, + { + code: "class A { static get 1e2() {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [{ message: "Setter is not present for class static getter '100'.", type: "MethodDefinition" }] + }, + { + code: "A = class { get ['abc']() {} };", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [{ message: "Setter is not present for class getter 'abc'.", type: "MethodDefinition" }] + }, + { + code: "class A { set [`abc`](foo) {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [{ message: "Getter is not present for class setter 'abc'.", type: "MethodDefinition" }] + }, + { + code: "class A { static get [123]() {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [{ message: "Setter is not present for class static getter '123'.", type: "MethodDefinition" }] + }, + { + code: "class A { get [abc]() {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [{ message: "Setter is not present for class getter.", type: "MethodDefinition" }] + }, + { + code: "class A { static get [f(abc)]() {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [{ message: "Setter is not present for class static getter.", type: "MethodDefinition" }] + }, + { + code: "A = class { set [a + b](foo) {} };", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [{ message: "Getter is not present for class setter.", type: "MethodDefinition" }] + }, + { + code: "class A { get ['constructor']() {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [{ message: "Setter is not present for class getter 'constructor'.", type: "MethodDefinition" }] + }, + + // Different keys + { + code: "class A { get a() {} set b(foo) {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { message: "Setter is not present for class getter 'a'.", type: "MethodDefinition", column: 11 }, + { message: "Getter is not present for class setter 'b'.", type: "MethodDefinition", column: 22 } + ] + }, + { + code: "A = class { set a(foo) {} get b() {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { message: "Getter is not present for class setter 'a'.", type: "MethodDefinition", column: 13 }, + { message: "Setter is not present for class getter 'b'.", type: "MethodDefinition", column: 27 } + ] + }, + { + code: "A = class { static get a() {} static set b(foo) {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { message: "Setter is not present for class static getter 'a'.", type: "MethodDefinition", column: 13 }, + { message: "Getter is not present for class static setter 'b'.", type: "MethodDefinition", column: 31 } + ] + }, + { + code: "class A { get a() {} set b(foo) {} }", + options: [{ setWithoutGet: false, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { message: "Setter is not present for class getter 'a'.", type: "MethodDefinition", column: 11 } + ] + }, + { + code: "class A { get a() {} set b(foo) {} }", + options: [{ setWithoutGet: true, getWithoutSet: false, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { message: "Getter is not present for class setter 'b'.", type: "MethodDefinition", column: 22 } + ] + }, + { + code: "class A { get 'a '() {} set 'a'(foo) {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { message: "Setter is not present for class getter 'a '.", type: "MethodDefinition", column: 11 }, + { message: "Getter is not present for class setter 'a'.", type: "MethodDefinition", column: 25 } + ] + }, + { + code: "class A { get 'a'() {} set 1(foo) {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { message: "Setter is not present for class getter 'a'.", type: "MethodDefinition", column: 11 }, + { message: "Getter is not present for class setter '1'.", type: "MethodDefinition", column: 24 } + ] + }, + { + code: "class A { get 1() {} set 2(foo) {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { message: "Setter is not present for class getter '1'.", type: "MethodDefinition", column: 11 }, + { message: "Getter is not present for class setter '2'.", type: "MethodDefinition", column: 22 } + ] + }, + { + code: "class A { get ''() {} set null(foo) {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { message: "Setter is not present for class getter ''.", type: "MethodDefinition", column: 11 }, + { message: "Getter is not present for class setter 'null'.", type: "MethodDefinition", column: 23 } + ] + }, + { + code: "class A { get a() {} set [a](foo) {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { message: "Setter is not present for class getter 'a'.", type: "MethodDefinition", column: 11 }, + { message: "Getter is not present for class setter.", type: "MethodDefinition", column: 22 } + ] + }, + { + code: "class A { get [a]() {} set [b](foo) {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { message: "Setter is not present for class getter.", type: "MethodDefinition", column: 11 }, + { message: "Getter is not present for class setter.", type: "MethodDefinition", column: 24 } + ] + }, + { + code: "class A { get [a]() {} set [a++](foo) {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { message: "Setter is not present for class getter.", type: "MethodDefinition", column: 11 }, + { message: "Getter is not present for class setter.", type: "MethodDefinition", column: 24 } + ] + }, + { + code: "class A { get [a + b]() {} set [a - b](foo) {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { message: "Setter is not present for class getter.", type: "MethodDefinition", column: 11 }, + { message: "Getter is not present for class setter.", type: "MethodDefinition", column: 28 } + ] + }, + + // Prototype and static accessors with same keys + { + code: "class A { get a() {} static set a(foo) {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { message: "Setter is not present for class getter 'a'.", type: "MethodDefinition", column: 11 }, + { message: "Getter is not present for class static setter 'a'.", type: "MethodDefinition", column: 22 } + ] + }, + { + code: "A = class { static get a() {} set a(foo) {} };", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { message: "Setter is not present for class static getter 'a'.", type: "MethodDefinition", column: 13 }, + { message: "Getter is not present for class setter 'a'.", type: "MethodDefinition", column: 31 } + ] + }, + { + code: "class A { set [a](foo) {} static get [a]() {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { message: "Getter is not present for class setter.", type: "MethodDefinition", column: 11 }, + { message: "Setter is not present for class static getter.", type: "MethodDefinition", column: 27 } + ] + }, + { + code: "class A { static set [a](foo) {} get [a]() {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { message: "Getter is not present for class static setter.", type: "MethodDefinition", column: 11 }, + { message: "Setter is not present for class getter.", type: "MethodDefinition", column: 34 } + ] + }, + + // Multiple invalid of same and different kinds + { + code: "class A { get a() {} get b() {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { message: "Setter is not present for class getter 'a'.", type: "MethodDefinition", column: 11 }, + { message: "Setter is not present for class getter 'b'.", type: "MethodDefinition", column: 22 } + ] + }, + { + code: "A = class { get a() {} get [b]() {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { message: "Setter is not present for class getter 'a'.", type: "MethodDefinition", column: 13 }, + { message: "Setter is not present for class getter.", type: "MethodDefinition", column: 24 } + ] + }, + { + code: "class A { get [a]() {} get [b]() {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { message: "Setter is not present for class getter.", type: "MethodDefinition", column: 11 }, + { message: "Setter is not present for class getter.", type: "MethodDefinition", column: 24 } + ] + }, + { + code: "A = class { set a(foo) {} set b(bar) {} };", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { message: "Getter is not present for class setter 'a'.", type: "MethodDefinition", column: 13 }, + { message: "Getter is not present for class setter 'b'.", type: "MethodDefinition", column: 27 } + ] + }, + { + code: "class A { static get a() {} static get b() {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { message: "Setter is not present for class static getter 'a'.", type: "MethodDefinition", column: 11 }, + { message: "Setter is not present for class static getter 'b'.", type: "MethodDefinition", column: 29 } + ] + }, + { + code: "A = class { static set a(foo) {} static set b(bar) {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { message: "Getter is not present for class static setter 'a'.", type: "MethodDefinition", column: 13 }, + { message: "Getter is not present for class static setter 'b'.", type: "MethodDefinition", column: 34 } + ] + }, + { + code: "class A { static get a() {} set b(foo) {} static set c(bar) {} get d() {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { message: "Setter is not present for class static getter 'a'.", type: "MethodDefinition", column: 11 }, + { message: "Getter is not present for class setter 'b'.", type: "MethodDefinition", column: 29 }, + { message: "Getter is not present for class static setter 'c'.", type: "MethodDefinition", column: 43 }, + { message: "Setter is not present for class getter 'd'.", type: "MethodDefinition", column: 64 } + ] + }, + + // Checks per class + { + code: "class A { get a() {} } class B { set a(foo) {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { message: "Setter is not present for class getter 'a'.", type: "MethodDefinition", column: 11 }, + { message: "Getter is not present for class setter 'a'.", type: "MethodDefinition", column: 34 } + ] + }, + { + code: "A = class { set a(foo) {} }, class { get a() {} };", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { message: "Getter is not present for class setter 'a'.", type: "MethodDefinition", column: 13 }, + { message: "Setter is not present for class getter 'a'.", type: "MethodDefinition", column: 38 } + ] + }, + { + code: "A = class { get a() {} }, { set a(foo) {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { message: "Setter is not present for class getter 'a'.", type: "MethodDefinition", column: 13 }, + { message: "Getter is not present for setter 'a'.", type: "Property", column: 29 } + ] + }, + { + code: "A = { get a() {} }, class { set a(foo) {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { message: "Setter is not present for getter 'a'.", type: "Property", column: 7 }, + { message: "Getter is not present for class setter 'a'.", type: "MethodDefinition", column: 29 } + ] + }, + + // Combinations or valid and invalid + { + code: "class A { get a() {} get b() {} set b(foo) {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [{ message: "Setter is not present for class getter 'a'.", type: "MethodDefinition", column: 11 }] + }, + { + code: "A = class { get b() {} get a() {} set b(foo) {} };", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [{ message: "Setter is not present for class getter 'a'.", type: "MethodDefinition", column: 24 }] + }, + { + code: "class A { set b(foo) {} get b() {} set a(bar) {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [{ message: "Getter is not present for class setter 'a'.", type: "MethodDefinition", column: 36 }] + }, + { + code: "A = class { static get b() {} set a(foo) {} static set b(bar) {} };", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [{ message: "Getter is not present for class setter 'a'.", type: "MethodDefinition", column: 31 }] + }, + { + code: "class A { static set a(foo) {} get b() {} set b(bar) {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [{ message: "Getter is not present for class static setter 'a'.", type: "MethodDefinition", column: 11 }] + }, + { + code: "class A { get b() {} static get a() {} set b(bar) {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [{ message: "Setter is not present for class static getter 'a'.", type: "MethodDefinition", column: 22 }] + }, + { + code: "class A { static set b(foo) {} static get a() {} static get b() {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [{ message: "Setter is not present for class static getter 'a'.", type: "MethodDefinition", column: 32 }] + }, + { + code: "class A { get [v1](){} static set i1(foo){} static set v2(bar){} get [i2](){} static get i3(){} set [v1](baz){} static get v2(){} set i4(quux){} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { message: "Getter is not present for class static setter 'i1'.", type: "MethodDefinition", column: 24 }, + { message: "Setter is not present for class getter.", type: "MethodDefinition", column: 66 }, + { message: "Setter is not present for class static getter 'i3'.", type: "MethodDefinition", column: 79 }, + { message: "Getter is not present for class setter 'i4'.", type: "MethodDefinition", column: 131 } + ] + }, + + // In the case of duplicates which don't have the other kind, all nodes are reported + { + code: "class A { get a() {} get a() {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { message: "Setter is not present for class getter 'a'.", type: "MethodDefinition", column: 11 }, + { message: "Setter is not present for class getter 'a'.", type: "MethodDefinition", column: 22 } + ] + }, + { + code: "A = class { set a(foo) {} set a(foo) {} };", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { message: "Getter is not present for class setter 'a'.", type: "MethodDefinition", column: 13 }, + { message: "Getter is not present for class setter 'a'.", type: "MethodDefinition", column: 27 } + ] + }, + { + code: "A = class { static get a() {} static get a() {} };", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { message: "Setter is not present for class static getter 'a'.", type: "MethodDefinition", column: 13 }, + { message: "Setter is not present for class static getter 'a'.", type: "MethodDefinition", column: 31 } + ] + }, + { + code: "class A { set a(foo) {} set a(foo) {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { message: "Getter is not present for class setter 'a'.", type: "MethodDefinition", column: 11 }, + { message: "Getter is not present for class setter 'a'.", type: "MethodDefinition", column: 25 } + ] + }, + + // Other elements or even method duplicates in the same class do not affect this rule + { + code: "class A { a() {} get b() {} c() {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { message: "Setter is not present for class getter 'b'.", type: "MethodDefinition", column: 18 } + ] + }, + { + code: "A = class { a() {} get b() {} c() {} set d(foo) {} };", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { message: "Setter is not present for class getter 'b'.", type: "MethodDefinition", column: 20 }, + { message: "Getter is not present for class setter 'd'.", type: "MethodDefinition", column: 38 } + ] + }, + { + code: "class A { static a() {} get b() {} static c() {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { message: "Setter is not present for class getter 'b'.", type: "MethodDefinition", column: 25 } + ] + }, + { + code: "class A { a() {} get a() {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { message: "Setter is not present for class getter 'a'.", type: "MethodDefinition", column: 18 } + ] + }, + { + code: "A = class { static a() {} set a(foo) {} };", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { message: "Getter is not present for class setter 'a'.", type: "MethodDefinition", column: 27 } + ] + }, + { + code: "class A { a() {} static get b() {} c() {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { message: "Setter is not present for class static getter 'b'.", type: "MethodDefinition", column: 18 } + ] + }, + { + code: "A = class { static a() {} static set b(foo) {} static c() {} d() {} };", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { message: "Getter is not present for class static setter 'b'.", type: "MethodDefinition", column: 27 } + ] + }, + { + code: "class A { a() {} static get a() {} a() {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { message: "Setter is not present for class static getter 'a'.", type: "MethodDefinition", column: 18 } + ] + }, + { + code: "class A { static set a(foo) {} static a() {} }", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { message: "Getter is not present for class static setter 'a'.", type: "MethodDefinition", column: 11 } + ] + }, + + // Full location tests + { + code: "class A { get a() {} };", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [{ + message: "Setter is not present for class getter 'a'.", + type: "MethodDefinition", + line: 1, + column: 11, + endLine: 1, + endColumn: 16 + }] + }, + { + code: "A = class {\n set [\n a](foo) {} };", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [{ + message: "Getter is not present for class setter.", + type: "MethodDefinition", + line: 2, + column: 3, + endLine: 3, + endColumn: 4 + }] + }, + { + code: "class A { static get a() {} };", + options: [{ setWithoutGet: true, getWithoutSet: true, enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [{ + message: "Setter is not present for class static getter 'a'.", + type: "MethodDefinition", + line: 1, + column: 11, + endLine: 1, + endColumn: 23 + }] } ] }); diff --git a/tests/lib/rules/computed-property-spacing.js b/tests/lib/rules/computed-property-spacing.js index fa1ca38f48a..3901d8c3fb3 100644 --- a/tests/lib/rules/computed-property-spacing.js +++ b/tests/lib/rules/computed-property-spacing.js @@ -72,7 +72,118 @@ ruleTester.run("computed-property-spacing", rule, { // never - unrelated cases { code: "var foo = {};", options: ["never"] }, - { code: "var foo = [];", options: ["never"] } + { code: "var foo = [];", options: ["never"] }, + + //------------------------------------------------------------------------------ + // Classes + //------------------------------------------------------------------------------ + + // test default settings + { + code: "class A { [ a ](){} }", + parserOptions: { ecmaVersion: 6 } + }, + { + code: "class A { [ a ](){} get [ b ](){} set [ c ](foo){} static [ d ](){} static get [ e ](){} static set [ f ](bar){} }", + options: ["never"], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "A = class { [ a ](){} get [ b ](){} set [ c ](foo){} static [ d ](){} static get [ e ](){} static set [ f ](bar){} }", + options: ["never", {}], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "A = class { [a](){} }", + options: ["always"], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "A = class { [a](){} get [b](){} set [c](foo){} static [d](){} static get [e](){} static set [f](bar){} }", + options: ["always"], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "class A { [a](){} get [b](){} set [c](foo){} static [d](){} static get [e](){} static set [f](bar){} }", + options: ["always", {}], + parserOptions: { ecmaVersion: 6 } + }, + + // explicitly disabled option + { + code: "class A { [ a ](){} }", + options: ["never", { enforceForClassMembers: false }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "A = class { [ a ](){} get [ b ](){} set [ c ](foo){} static [ d ](){} static get [ e ](){} static set [ f ](bar){} }", + options: ["never", { enforceForClassMembers: false }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "A = class { [a](){} }", + options: ["always", { enforceForClassMembers: false }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "class A { [a](){} get [b](){} set [b](foo){} static [c](){} static get [d](){} static set [d](bar){} }", + options: ["always", { enforceForClassMembers: false }], + parserOptions: { ecmaVersion: 6 } + }, + + // valid spacing + { + code: "A = class { [a](){} }", + options: ["never", { enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "class A { [a] ( ) { } }", + options: ["never", { enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "A = class { [ \n a \n ](){} }", + options: ["never", { enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "class A { [a](){} get [b](){} set [b](foo){} static [c](){} static get [d](){} static set [d](bar){} }", + options: ["never", { enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "class A { [ a ](){} }", + options: ["always", { enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "class A { [ a ](){}[ b ](){} }", + options: ["always", { enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "A = class { [\na\n](){} }", + options: ["always", { enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "A = class { [ a ](){} get [ b ](){} set [ c ](foo){} static [ d ](){} static get [ e ](){} static set [ f ](bar){} }", + options: ["always", { enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + }, + + // non-computed + { + code: "class A { a ( ) { } get b(){} set b ( foo ){} static c (){} static get d() {} static set d( bar ) {} }", + options: ["never", { enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "A = class {a(){}get b(){}set b(foo){}static c(){}static get d(){}static set d(bar){}}", + options: ["always", { enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 } + } ], invalid: [ @@ -322,7 +433,330 @@ ruleTester.run("computed-property-spacing", rule, { line: 1 } ] - } + }, + + //------------------------------------------------------------------------------ + // Classes + //------------------------------------------------------------------------------ + + // never + { + code: "class A { [ a](){} }", + output: "class A { [a](){} }", + options: ["never", { enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "unexpectedSpaceAfter", + data: { tokenValue: "[" }, + type: "MethodDefinition", + column: 11, + line: 1 + } + ] + }, + { + code: "A = class { [a](){} b(){} static [c ](){} static [d](){}}", + output: "A = class { [a](){} b(){} static [c](){} static [d](){}}", + options: ["never", { enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "unexpectedSpaceBefore", + data: { tokenValue: "]" }, + type: "MethodDefinition", + column: 37, + line: 1 + } + ] + }, + { + code: "class A { get [a ](){} set [ a](foo){} get b(){} static set b(bar){} static get [ a](){} static set [a ](baz){} }", + output: "class A { get [a](){} set [a](foo){} get b(){} static set b(bar){} static get [a](){} static set [a](baz){} }", + options: ["never", { enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "unexpectedSpaceBefore", + data: { tokenValue: "]" }, + type: "MethodDefinition", + column: 18, + line: 1 + }, + { + messageId: "unexpectedSpaceAfter", + data: { tokenValue: "[" }, + type: "MethodDefinition", + column: 28, + line: 1 + }, + { + messageId: "unexpectedSpaceAfter", + data: { tokenValue: "[" }, + type: "MethodDefinition", + column: 81, + line: 1 + }, + { + messageId: "unexpectedSpaceBefore", + data: { tokenValue: "]" }, + type: "MethodDefinition", + column: 104, + line: 1 + } + ] + }, + { + code: "A = class { [ a ](){} get [ b ](){} set [ c ](foo){} static [ d ](){} static get [ e ](){} static set [ f ](bar){} }", + output: "A = class { [a](){} get [b](){} set [c](foo){} static [d](){} static get [e](){} static set [f](bar){} }", + options: ["never", { enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "unexpectedSpaceAfter", + data: { tokenValue: "[" }, + type: "MethodDefinition", + column: 13, + line: 1 + }, + { + messageId: "unexpectedSpaceBefore", + data: { tokenValue: "]" }, + type: "MethodDefinition", + column: 17, + line: 1 + }, + { + messageId: "unexpectedSpaceAfter", + data: { tokenValue: "[" }, + type: "MethodDefinition", + column: 27, + line: 1 + }, + { + messageId: "unexpectedSpaceBefore", + data: { tokenValue: "]" }, + type: "MethodDefinition", + column: 31, + line: 1 + }, + { + messageId: "unexpectedSpaceAfter", + data: { tokenValue: "[" }, + type: "MethodDefinition", + column: 41, + line: 1 + }, + { + messageId: "unexpectedSpaceBefore", + data: { tokenValue: "]" }, + type: "MethodDefinition", + column: 45, + line: 1 + }, + { + messageId: "unexpectedSpaceAfter", + data: { tokenValue: "[" }, + type: "MethodDefinition", + column: 61, + line: 1 + }, + { + messageId: "unexpectedSpaceBefore", + data: { tokenValue: "]" }, + type: "MethodDefinition", + column: 65, + line: 1 + }, + { + messageId: "unexpectedSpaceAfter", + data: { tokenValue: "[" }, + type: "MethodDefinition", + column: 82, + line: 1 + }, + { + messageId: "unexpectedSpaceBefore", + data: { tokenValue: "]" }, + type: "MethodDefinition", + column: 86, + line: 1 + }, + { + messageId: "unexpectedSpaceAfter", + data: { tokenValue: "[" }, + type: "MethodDefinition", + column: 103, + line: 1 + }, + { + messageId: "unexpectedSpaceBefore", + data: { tokenValue: "]" }, + type: "MethodDefinition", + column: 107, + line: 1 + } + ] + }, + // always + { + code: "class A { [ a](){} }", + output: "class A { [ a ](){} }", + options: ["always", { enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "missingSpaceBefore", + data: { tokenValue: "]" }, + type: "MethodDefinition", + column: 14, + line: 1 + } + ] + }, + { + code: "A = class { [ a ](){} b(){} static [c ](){} static [ d ](){}}", + output: "A = class { [ a ](){} b(){} static [ c ](){} static [ d ](){}}", + options: ["always", { enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "missingSpaceAfter", + data: { tokenValue: "[" }, + type: "MethodDefinition", + column: 36, + line: 1 + } + ] + }, + { + code: "class A { get [a ](){} set [ a](foo){} get b(){} static set b(bar){} static get [ a](){} static set [a ](baz){} }", + output: "class A { get [ a ](){} set [ a ](foo){} get b(){} static set b(bar){} static get [ a ](){} static set [ a ](baz){} }", + options: ["always", { enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "missingSpaceAfter", + data: { tokenValue: "[" }, + type: "MethodDefinition", + column: 15, + line: 1 + }, + { + messageId: "missingSpaceBefore", + data: { tokenValue: "]" }, + type: "MethodDefinition", + column: 31, + line: 1 + }, + { + messageId: "missingSpaceBefore", + data: { tokenValue: "]" }, + type: "MethodDefinition", + column: 84, + line: 1 + }, + { + messageId: "missingSpaceAfter", + data: { tokenValue: "[" }, + type: "MethodDefinition", + column: 101, + line: 1 + } + ] + }, + { + code: "A = class { [a](){} get [b](){} set [c](foo){} static [d](){} static get [e](){} static set [f](bar){} }", + output: "A = class { [ a ](){} get [ b ](){} set [ c ](foo){} static [ d ](){} static get [ e ](){} static set [ f ](bar){} }", + options: ["always", { enforceForClassMembers: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "missingSpaceAfter", + data: { tokenValue: "[" }, + type: "MethodDefinition", + column: 13, + line: 1 + }, + { + messageId: "missingSpaceBefore", + data: { tokenValue: "]" }, + type: "MethodDefinition", + column: 15, + line: 1 + }, + { + messageId: "missingSpaceAfter", + data: { tokenValue: "[" }, + type: "MethodDefinition", + column: 25, + line: 1 + }, + { + messageId: "missingSpaceBefore", + data: { tokenValue: "]" }, + type: "MethodDefinition", + column: 27, + line: 1 + }, + { + messageId: "missingSpaceAfter", + data: { tokenValue: "[" }, + type: "MethodDefinition", + column: 37, + line: 1 + }, + { + messageId: "missingSpaceBefore", + data: { tokenValue: "]" }, + type: "MethodDefinition", + column: 39, + line: 1 + }, + { + messageId: "missingSpaceAfter", + data: { tokenValue: "[" }, + type: "MethodDefinition", + column: 55, + line: 1 + }, + { + messageId: "missingSpaceBefore", + data: { tokenValue: "]" }, + type: "MethodDefinition", + column: 57, + line: 1 + }, + { + messageId: "missingSpaceAfter", + data: { tokenValue: "[" }, + type: "MethodDefinition", + column: 74, + line: 1 + }, + { + messageId: "missingSpaceBefore", + data: { tokenValue: "]" }, + type: "MethodDefinition", + column: 76, + line: 1 + }, + { + messageId: "missingSpaceAfter", + data: { tokenValue: "[" }, + type: "MethodDefinition", + column: 93, + line: 1 + }, + { + messageId: "missingSpaceBefore", + data: { tokenValue: "]" }, + type: "MethodDefinition", + column: 95, + line: 1 + } + ] + } ] }); diff --git a/tests/lib/rules/eqeqeq.js b/tests/lib/rules/eqeqeq.js index b74e9bc2ca5..05e33bbcfa9 100644 --- a/tests/lib/rules/eqeqeq.js +++ b/tests/lib/rules/eqeqeq.js @@ -105,6 +105,69 @@ ruleTester.run("eqeqeq", rule, { { messageId: "unexpected", data: wantedNotEqEq, type: "BinaryExpression", line: 1 }, { messageId: "unexpected", data: wantedNotEqEq, type: "BinaryExpression", line: 1 } ] + }, + + // location tests + { + code: "a == b;", + errors: [ + { + messageId: "unexpected", + data: wantedEqEqEq, + type: "BinaryExpression", + column: 3, + endColumn: 5 + } + ] + }, + { + code: "a!=b;", + errors: [ + { + messageId: "unexpected", + data: wantedNotEqEq, + type: "BinaryExpression", + column: 2, + endColumn: 4 + } + ] + }, + { + code: "(a + b) == c;", + errors: [ + { + messageId: "unexpected", + data: wantedEqEqEq, + type: "BinaryExpression", + column: 9, + endColumn: 11 + } + ] + }, + { + code: "(a + b) != c;", + errors: [ + { + messageId: "unexpected", + data: wantedNotEqEq, + type: "BinaryExpression", + column: 10, + endColumn: 12 + } + ] + }, + { + code: "((1) ) == (2);", + output: "((1) ) === (2);", + errors: [ + { + messageId: "unexpected", + data: wantedEqEqEq, + type: "BinaryExpression", + column: 9, + endColumn: 11 + } + ] } // If no output is provided, assert that no output is produced. diff --git a/tests/lib/rules/indent.js b/tests/lib/rules/indent.js index b38c97e960b..e2d6202a998 100644 --- a/tests/lib/rules/indent.js +++ b/tests/lib/rules/indent.js @@ -4950,6 +4950,212 @@ ruleTester.run("indent", rule, { bar }]; `, + unIndent` + let foo + + // comment + + ;(async () => {})() + `, + unIndent` + let foo + // comment + + ;(async () => {})() + `, + unIndent` + let foo + + // comment + ;(async () => {})() + `, + unIndent` + let foo + // comment + ;(async () => {})() + `, + unIndent` + let foo + + /* comment */; + + (async () => {})() + `, + unIndent` + let foo + /* comment */; + + (async () => {})() + `, + unIndent` + let foo + + /* comment */; + (async () => {})() + `, + unIndent` + let foo + /* comment */; + (async () => {})() + `, + unIndent` + let foo + /* comment */; + + (async () => {})() + `, + unIndent` + let foo + /* comment */; + (async () => {})() + `, + unIndent` + // comment + + ;(async () => {})() + `, + unIndent` + // comment + ;(async () => {})() + `, + unIndent` + { + let foo + + // comment + + ;(async () => {})() + } + `, + unIndent` + { + let foo + // comment + ;(async () => {})() + } + `, + unIndent` + { + // comment + + ;(async () => {})() + } + `, + unIndent` + { + // comment + ;(async () => {})() + } + `, + unIndent` + const foo = 1 + const bar = foo + + /* comment */ + + ;[1, 2, 3].forEach(() => {}) + `, + unIndent` + const foo = 1 + const bar = foo + /* comment */ + + ;[1, 2, 3].forEach(() => {}) + `, + unIndent` + const foo = 1 + const bar = foo + + /* comment */ + ;[1, 2, 3].forEach(() => {}) + `, + unIndent` + const foo = 1 + const bar = foo + /* comment */ + ;[1, 2, 3].forEach(() => {}) + `, + unIndent` + const foo = 1 + const bar = foo + + /* comment */; + + [1, 2, 3].forEach(() => {}) + `, + unIndent` + const foo = 1 + const bar = foo + /* comment */; + + [1, 2, 3].forEach(() => {}) + `, + unIndent` + const foo = 1 + const bar = foo + + /* comment */; + [1, 2, 3].forEach(() => {}) + `, + unIndent` + const foo = 1 + const bar = foo + /* comment */; + [1, 2, 3].forEach(() => {}) + `, + unIndent` + const foo = 1 + const bar = foo + /* comment */; + + [1, 2, 3].forEach(() => {}) + `, + unIndent` + const foo = 1 + const bar = foo + /* comment */; + [1, 2, 3].forEach(() => {}) + `, + unIndent` + /* comment */ + + ;[1, 2, 3].forEach(() => {}) + `, + unIndent` + /* comment */ + ;[1, 2, 3].forEach(() => {}) + `, + unIndent` + { + const foo = 1 + const bar = foo + + /* comment */ + + ;[1, 2, 3].forEach(() => {}) + } + `, + unIndent` + { + const foo = 1 + const bar = foo + /* comment */ + ;[1, 2, 3].forEach(() => {}) + } + `, + unIndent` + { + /* comment */ + + ;[1, 2, 3].forEach(() => {}) + } + `, + unIndent` + { + /* comment */ + ;[1, 2, 3].forEach(() => {}) + } + `, // import expressions { @@ -9606,6 +9812,290 @@ ruleTester.run("indent", rule, { `, errors: expectedErrors([5, 0, 4, "Line"]) }, + { + code: unIndent` + let foo + + // comment + + ;(async () => {})() + `, + output: unIndent` + let foo + + // comment + + ;(async () => {})() + `, + errors: expectedErrors([3, 0, 4, "Line"]) + }, + { + code: unIndent` + let foo + // comment + ;(async () => {})() + `, + output: unIndent` + let foo + // comment + ;(async () => {})() + `, + errors: expectedErrors([2, 0, 4, "Line"]) + }, + { + code: unIndent` + let foo + + /* comment */; + + (async () => {})() + `, + output: unIndent` + let foo + + /* comment */; + + (async () => {})() + `, + errors: expectedErrors([3, 4, 0, "Block"]) + }, + { + code: unIndent` + // comment + + ;(async () => {})() + `, + output: unIndent` + // comment + + ;(async () => {})() + `, + errors: expectedErrors([1, 0, 4, "Line"]) + }, + { + code: unIndent` + // comment + ;(async () => {})() + `, + output: unIndent` + // comment + ;(async () => {})() + `, + errors: expectedErrors([1, 0, 4, "Line"]) + }, + { + code: unIndent` + { + let foo + + // comment + + ;(async () => {})() + + } + `, + output: unIndent` + { + let foo + + // comment + + ;(async () => {})() + + } + `, + errors: expectedErrors([4, 4, 8, "Line"]) + }, + { + code: unIndent` + { + let foo + // comment + ;(async () => {})() + + } + `, + output: unIndent` + { + let foo + // comment + ;(async () => {})() + + } + `, + errors: expectedErrors([3, 4, 8, "Line"]) + }, + { + code: unIndent` + { + let foo + + /* comment */; + + (async () => {})() + + } + `, + output: unIndent` + { + let foo + + /* comment */; + + (async () => {})() + + } + `, + errors: expectedErrors([4, 8, 4, "Block"]) + }, + { + code: unIndent` + const foo = 1 + const bar = foo + + /* comment */ + + ;[1, 2, 3].forEach(() => {}) + `, + output: unIndent` + const foo = 1 + const bar = foo + + /* comment */ + + ;[1, 2, 3].forEach(() => {}) + `, + errors: expectedErrors([4, 0, 4, "Block"]) + }, + { + code: unIndent` + const foo = 1 + const bar = foo + /* comment */ + ;[1, 2, 3].forEach(() => {}) + `, + output: unIndent` + const foo = 1 + const bar = foo + /* comment */ + ;[1, 2, 3].forEach(() => {}) + `, + errors: expectedErrors([3, 0, 4, "Block"]) + }, + { + code: unIndent` + const foo = 1 + const bar = foo + + /* comment */; + + [1, 2, 3].forEach(() => {}) + `, + output: unIndent` + const foo = 1 + const bar = foo + + /* comment */; + + [1, 2, 3].forEach(() => {}) + `, + errors: expectedErrors([4, 4, 0, "Block"]) + }, + { + code: unIndent` + /* comment */ + + ;[1, 2, 3].forEach(() => {}) + `, + output: unIndent` + /* comment */ + + ;[1, 2, 3].forEach(() => {}) + `, + errors: expectedErrors([1, 0, 4, "Block"]) + }, + { + code: unIndent` + /* comment */ + ;[1, 2, 3].forEach(() => {}) + `, + output: unIndent` + /* comment */ + ;[1, 2, 3].forEach(() => {}) + `, + errors: expectedErrors([1, 0, 4, "Block"]) + }, + { + code: unIndent` + { + const foo = 1 + const bar = foo + + /* comment */ + + ;[1, 2, 3].forEach(() => {}) + + } + `, + output: unIndent` + { + const foo = 1 + const bar = foo + + /* comment */ + + ;[1, 2, 3].forEach(() => {}) + + } + `, + errors: expectedErrors([5, 4, 8, "Block"]) + }, + { + code: unIndent` + { + const foo = 1 + const bar = foo + /* comment */ + ;[1, 2, 3].forEach(() => {}) + + } + `, + output: unIndent` + { + const foo = 1 + const bar = foo + /* comment */ + ;[1, 2, 3].forEach(() => {}) + + } + `, + errors: expectedErrors([4, 4, 8, "Block"]) + }, + { + code: unIndent` + { + const foo = 1 + const bar = foo + + /* comment */; + + [1, 2, 3].forEach(() => {}) + + } + `, + output: unIndent` + { + const foo = 1 + const bar = foo + + /* comment */; + + [1, 2, 3].forEach(() => {}) + + } + `, + errors: expectedErrors([5, 8, 4, "Block"]) + }, // import expressions { diff --git a/tests/lib/rules/no-import-assign.js b/tests/lib/rules/no-import-assign.js new file mode 100644 index 00000000000..ab65451e33a --- /dev/null +++ b/tests/lib/rules/no-import-assign.js @@ -0,0 +1,315 @@ +/** + * @fileoverview Tests for no-import-assign rule. + * @author Toru Nagashima + */ + +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const rule = require("../../../lib/rules/no-import-assign"), + { RuleTester } = require("../../../lib/rule-tester"); + +//------------------------------------------------------------------------------ +// Tests +//------------------------------------------------------------------------------ + +const ruleTester = new RuleTester({ + parserOptions: { + ecmaVersion: 2018, + sourceType: "module" + }, + globals: { + Reflect: "readonly" + } +}); + +ruleTester.run("no-import-assign", rule, { + valid: [ + "import mod from 'mod'; mod.prop = 0", + "import mod from 'mod'; mod.prop += 0", + "import mod from 'mod'; mod.prop++", + "import mod from 'mod'; delete mod.prop", + "import mod from 'mod'; for (mod.prop in foo);", + "import mod from 'mod'; for (mod.prop of foo);", + "import mod from 'mod'; [mod.prop] = foo;", + "import mod from 'mod'; [...mod.prop] = foo;", + "import mod from 'mod'; ({ bar: mod.prop } = foo);", + "import mod from 'mod'; ({ ...mod.prop } = foo);", + "import {named} from 'mod'; named.prop = 0", + "import {named} from 'mod'; named.prop += 0", + "import {named} from 'mod'; named.prop++", + "import {named} from 'mod'; delete named.prop", + "import {named} from 'mod'; for (named.prop in foo);", + "import {named} from 'mod'; for (named.prop of foo);", + "import {named} from 'mod'; [named.prop] = foo;", + "import {named} from 'mod'; [...named.prop] = foo;", + "import {named} from 'mod'; ({ bar: named.prop } = foo);", + "import {named} from 'mod'; ({ ...named.prop } = foo);", + "import * as mod from 'mod'; mod.named.prop = 0", + "import * as mod from 'mod'; mod.named.prop += 0", + "import * as mod from 'mod'; mod.named.prop++", + "import * as mod from 'mod'; delete mod.named.prop", + "import * as mod from 'mod'; for (mod.named.prop in foo);", + "import * as mod from 'mod'; for (mod.named.prop of foo);", + "import * as mod from 'mod'; [mod.named.prop] = foo;", + "import * as mod from 'mod'; [...mod.named.prop] = foo;", + "import * as mod from 'mod'; ({ bar: mod.named.prop } = foo);", + "import * as mod from 'mod'; ({ ...mod.named.prop } = foo);", + "import * as mod from 'mod'; obj[mod] = 0", + "import * as mod from 'mod'; obj[mod.named] = 0", + "import * as mod from 'mod'; for (var foo in mod.named);", + "import * as mod from 'mod'; for (var foo of mod.named);", + "import * as mod from 'mod'; [bar = mod.named] = foo;", + "import * as mod from 'mod'; ({ bar = mod.named } = foo);", + "import * as mod from 'mod'; ({ bar: baz = mod.named } = foo);", + "import * as mod from 'mod'; ({ [mod.named]: bar } = foo);", + "import * as mod from 'mod'; var obj = { ...mod.named };", + "import * as mod from 'mod'; var obj = { foo: mod.named };", + "import mod from 'mod'; { let mod = 0; mod = 1 }", + "import * as mod from 'mod'; { let mod = 0; mod = 1 }", + "import * as mod from 'mod'; { let mod = 0; mod.named = 1 }", + "import {} from 'mod'", + "import 'mod'", + "import mod from 'mod'; Object.assign(mod, obj);", + "import {named} from 'mod'; Object.assign(named, obj);", + "import * as mod from 'mod'; Object.assign(mod.prop, obj);", + "import * as mod from 'mod'; Object.assign(obj, mod, other);", + "import * as mod from 'mod'; Object[assign](mod, obj);", + "import * as mod from 'mod'; Object.getPrototypeOf(mod);", + "import * as mod from 'mod'; Reflect.set(obj, key, mod);", + "import * as mod from 'mod'; { var Object; Object.assign(mod, obj); }", + "import * as mod from 'mod'; var Object; Object.assign(mod, obj);", + "import * as mod from 'mod'; Object.seal(mod, obj)", + "import * as mod from 'mod'; Object.preventExtensions(mod)", + "import * as mod from 'mod'; Reflect.preventExtensions(mod)" + ], + invalid: [ + { + code: "import mod1 from 'mod'; mod1 = 0", + errors: [{ messageId: "readonly", data: { name: "mod1" }, column: 25 }] + }, + { + code: "import mod2 from 'mod'; mod2 += 0", + errors: [{ messageId: "readonly", data: { name: "mod2" }, column: 25 }] + }, + { + code: "import mod3 from 'mod'; mod3++", + errors: [{ messageId: "readonly", data: { name: "mod3" }, column: 25 }] + }, + { + code: "import mod4 from 'mod'; for (mod4 in foo);", + errors: [{ messageId: "readonly", data: { name: "mod4" }, column: 25 }] + }, + { + code: "import mod5 from 'mod'; for (mod5 of foo);", + errors: [{ messageId: "readonly", data: { name: "mod5" }, column: 25 }] + }, + { + code: "import mod6 from 'mod'; [mod6] = foo", + errors: [{ messageId: "readonly", data: { name: "mod6" }, column: 25 }] + }, + { + code: "import mod7 from 'mod'; [mod7 = 0] = foo", + errors: [{ messageId: "readonly", data: { name: "mod7" }, column: 25 }] + }, + { + code: "import mod8 from 'mod'; [...mod8] = foo", + errors: [{ messageId: "readonly", data: { name: "mod8" }, column: 25 }] + }, + { + code: "import mod9 from 'mod'; ({ bar: mod9 } = foo)", + errors: [{ messageId: "readonly", data: { name: "mod9" }, column: 26 }] + }, + { + code: "import mod10 from 'mod'; ({ bar: mod10 = 0 } = foo)", + errors: [{ messageId: "readonly", data: { name: "mod10" }, column: 27 }] + }, + { + code: "import mod11 from 'mod'; ({ ...mod11 } = foo)", + errors: [{ messageId: "readonly", data: { name: "mod11" }, column: 27 }] + }, + { + code: "import {named1} from 'mod'; named1 = 0", + errors: [{ messageId: "readonly", data: { name: "named1" }, column: 29 }] + }, + { + code: "import {named2} from 'mod'; named2 += 0", + errors: [{ messageId: "readonly", data: { name: "named2" }, column: 29 }] + }, + { + code: "import {named3} from 'mod'; named3++", + errors: [{ messageId: "readonly", data: { name: "named3" }, column: 29 }] + }, + { + code: "import {named4} from 'mod'; for (named4 in foo);", + errors: [{ messageId: "readonly", data: { name: "named4" }, column: 29 }] + }, + { + code: "import {named5} from 'mod'; for (named5 of foo);", + errors: [{ messageId: "readonly", data: { name: "named5" }, column: 29 }] + }, + { + code: "import {named6} from 'mod'; [named6] = foo", + errors: [{ messageId: "readonly", data: { name: "named6" }, column: 29 }] + }, + { + code: "import {named7} from 'mod'; [named7 = 0] = foo", + errors: [{ messageId: "readonly", data: { name: "named7" }, column: 29 }] + }, + { + code: "import {named8} from 'mod'; [...named8] = foo", + errors: [{ messageId: "readonly", data: { name: "named8" }, column: 29 }] + }, + { + code: "import {named9} from 'mod'; ({ bar: named9 } = foo)", + errors: [{ messageId: "readonly", data: { name: "named9" }, column: 30 }] + }, + { + code: "import {named10} from 'mod'; ({ bar: named10 = 0 } = foo)", + errors: [{ messageId: "readonly", data: { name: "named10" }, column: 31 }] + }, + { + code: "import {named11} from 'mod'; ({ ...named11 } = foo)", + errors: [{ messageId: "readonly", data: { name: "named11" }, column: 31 }] + }, + { + code: "import {named12 as foo} from 'mod'; foo = 0; named12 = 0", + errors: [{ messageId: "readonly", data: { name: "foo" }, column: 37 }] + }, + { + code: "import * as mod1 from 'mod'; mod1 = 0", + errors: [{ messageId: "readonly", data: { name: "mod1" }, column: 30 }] + }, + { + code: "import * as mod2 from 'mod'; mod2 += 0", + errors: [{ messageId: "readonly", data: { name: "mod2" }, column: 30 }] + }, + { + code: "import * as mod3 from 'mod'; mod3++", + errors: [{ messageId: "readonly", data: { name: "mod3" }, column: 30 }] + }, + { + code: "import * as mod4 from 'mod'; for (mod4 in foo);", + errors: [{ messageId: "readonly", data: { name: "mod4" }, column: 30 }] + }, + { + code: "import * as mod5 from 'mod'; for (mod5 of foo);", + errors: [{ messageId: "readonly", data: { name: "mod5" }, column: 30 }] + }, + { + code: "import * as mod6 from 'mod'; [mod6] = foo", + errors: [{ messageId: "readonly", data: { name: "mod6" }, column: 30 }] + }, + { + code: "import * as mod7 from 'mod'; [mod7 = 0] = foo", + errors: [{ messageId: "readonly", data: { name: "mod7" }, column: 30 }] + }, + { + code: "import * as mod8 from 'mod'; [...mod8] = foo", + errors: [{ messageId: "readonly", data: { name: "mod8" }, column: 30 }] + }, + { + code: "import * as mod9 from 'mod'; ({ bar: mod9 } = foo)", + errors: [{ messageId: "readonly", data: { name: "mod9" }, column: 31 }] + }, + { + code: "import * as mod10 from 'mod'; ({ bar: mod10 = 0 } = foo)", + errors: [{ messageId: "readonly", data: { name: "mod10" }, column: 32 }] + }, + { + code: "import * as mod11 from 'mod'; ({ ...mod11 } = foo)", + errors: [{ messageId: "readonly", data: { name: "mod11" }, column: 32 }] + }, + { + code: "import * as mod1 from 'mod'; mod1.named = 0", + errors: [{ messageId: "readonlyMember", data: { name: "mod1" }, column: 30 }] + }, + { + code: "import * as mod2 from 'mod'; mod2.named += 0", + errors: [{ messageId: "readonlyMember", data: { name: "mod2" }, column: 30 }] + }, + { + code: "import * as mod3 from 'mod'; mod3.named++", + errors: [{ messageId: "readonlyMember", data: { name: "mod3" }, column: 30 }] + }, + { + code: "import * as mod4 from 'mod'; for (mod4.named in foo);", + errors: [{ messageId: "readonlyMember", data: { name: "mod4" }, column: 30 }] + }, + { + code: "import * as mod5 from 'mod'; for (mod5.named of foo);", + errors: [{ messageId: "readonlyMember", data: { name: "mod5" }, column: 30 }] + }, + { + code: "import * as mod6 from 'mod'; [mod6.named] = foo", + errors: [{ messageId: "readonlyMember", data: { name: "mod6" }, column: 30 }] + }, + { + code: "import * as mod7 from 'mod'; [mod7.named = 0] = foo", + errors: [{ messageId: "readonlyMember", data: { name: "mod7" }, column: 30 }] + }, + { + code: "import * as mod8 from 'mod'; [...mod8.named] = foo", + errors: [{ messageId: "readonlyMember", data: { name: "mod8" }, column: 30 }] + }, + { + code: "import * as mod9 from 'mod'; ({ bar: mod9.named } = foo)", + errors: [{ messageId: "readonlyMember", data: { name: "mod9" }, column: 31 }] + }, + { + code: "import * as mod10 from 'mod'; ({ bar: mod10.named = 0 } = foo)", + errors: [{ messageId: "readonlyMember", data: { name: "mod10" }, column: 32 }] + }, + { + code: "import * as mod11 from 'mod'; ({ ...mod11.named } = foo)", + errors: [{ messageId: "readonlyMember", data: { name: "mod11" }, column: 32 }] + }, + { + code: "import * as mod12 from 'mod'; delete mod12.named", + errors: [{ messageId: "readonlyMember", data: { name: "mod12" }, column: 31 }] + }, + { + code: "import * as mod from 'mod'; Object.assign(mod, obj)", + errors: [{ messageId: "readonlyMember", data: { name: "mod" }, column: 29 }] + }, + { + code: "import * as mod from 'mod'; Object.defineProperty(mod, key, d)", + errors: [{ messageId: "readonlyMember", data: { name: "mod" }, column: 29 }] + }, + { + code: "import * as mod from 'mod'; Object.defineProperties(mod, d)", + errors: [{ messageId: "readonlyMember", data: { name: "mod" }, column: 29 }] + }, + { + code: "import * as mod from 'mod'; Object.setPrototypeOf(mod, proto)", + errors: [{ messageId: "readonlyMember", data: { name: "mod" }, column: 29 }] + }, + { + code: "import * as mod from 'mod'; Object.freeze(mod)", + errors: [{ messageId: "readonlyMember", data: { name: "mod" }, column: 29 }] + }, + { + code: "import * as mod from 'mod'; Reflect.defineProperty(mod, key, d)", + errors: [{ messageId: "readonlyMember", data: { name: "mod" }, column: 29 }] + }, + { + code: "import * as mod from 'mod'; Reflect.deleteProperty(mod, key)", + errors: [{ messageId: "readonlyMember", data: { name: "mod" }, column: 29 }] + }, + { + code: "import * as mod from 'mod'; Reflect.set(mod, key, value)", + errors: [{ messageId: "readonlyMember", data: { name: "mod" }, column: 29 }] + }, + { + code: "import * as mod from 'mod'; Reflect.setPrototypeOf(mod, proto)", + errors: [{ messageId: "readonlyMember", data: { name: "mod" }, column: 29 }] + }, + { + code: "import mod, * as mod_ns from 'mod'; mod.prop = 0; mod_ns.prop = 0", + errors: [{ messageId: "readonlyMember", data: { name: "mod_ns" }, column: 51 }] + } + ] +}); diff --git a/tests/lib/rules/no-lone-blocks.js b/tests/lib/rules/no-lone-blocks.js index 3640a10127f..139e24c9d04 100644 --- a/tests/lib/rules/no-lone-blocks.js +++ b/tests/lib/rules/no-lone-blocks.js @@ -56,7 +56,8 @@ ruleTester.run("no-lone-blocks", rule, { baz; } } - ` + `, + { code: "function foo() { { const x = 4 } const x = 3 }", parserOptions: { ecmaVersion: 6 } } ], invalid: [ { code: "{}", errors: [{ message: "Block is redundant.", type: "BlockStatement" }] }, @@ -118,6 +119,39 @@ ruleTester.run("no-lone-blocks", rule, { } `, errors: [{ message: "Block is redundant.", type: "BlockStatement", line: 4 }] + }, + { + code: ` + function foo () { + { + const x = 4; + } + } + `, + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + message: "Nested block is redundant.", + type: "BlockStatement", + line: 3 + } + ] + }, + { + code: ` + function foo () { + { + var x = 4; + } + } + `, + errors: [ + { + message: "Nested block is redundant.", + type: "BlockStatement", + line: 3 + } + ] } ] }); diff --git a/tests/lib/rules/no-obj-calls.js b/tests/lib/rules/no-obj-calls.js index 6f390ab4575..d5bcf063818 100644 --- a/tests/lib/rules/no-obj-calls.js +++ b/tests/lib/rules/no-obj-calls.js @@ -20,11 +20,112 @@ const ruleTester = new RuleTester(); ruleTester.run("no-obj-calls", rule, { valid: [ - "var x = Math.random();" + "var x = Math;", + "var x = Math.random();", + "var x = Math.PI;", + "var x = foo.Math();", + "JSON.parse(foo)", + "Reflect.get(foo, 'x')", + "Atomics.load(foo, 0)", + + // non-existing variables + "/*globals Math: off*/ Math();", + { + code: "JSON();", + globals: { JSON: "off" } + }, + "Reflect();", + "Atomics();", + { + code: "Atomics();", + env: { es6: true } + }, + + // shadowed variables + "var Math; Math();", + { + code: "let JSON; JSON();", + parserOptions: { ecmaVersion: 2015 } + }, + { + code: "if (foo) { const Reflect = 1; Reflect(); }", + parserOptions: { ecmaVersion: 2015 }, + env: { es6: true } + }, + "function foo(Math) { Math(); }", + { + code: "function foo(Atomics) { Atomics(); }", + env: { es2017: true } + }, + "function foo() { var JSON; JSON(); }", + { + code: "function foo() { var Atomics = bar(); var baz = Atomics(5); }", + globals: { Atomics: false } + } ], invalid: [ - { code: "var x = Math();", errors: [{ message: "'Math' is not a function.", type: "CallExpression" }] }, - { code: "var x = JSON();", errors: [{ message: "'JSON' is not a function.", type: "CallExpression" }] }, - { code: "var x = Reflect();", errors: [{ message: "'Reflect' is not a function.", type: "CallExpression" }] } + + // test full message + { + code: "Math();", + errors: [{ message: "'Math' is not a function.", type: "CallExpression" }] + }, + + { + code: "var x = Math();", + errors: [{ messageId: "unexpectedCall", data: { name: "Math" }, type: "CallExpression" }] + }, + { + code: "f(Math());", + errors: [{ messageId: "unexpectedCall", data: { name: "Math" }, type: "CallExpression", column: 3, endColumn: 9 }] + }, + { + code: "Math().foo;", + errors: [{ messageId: "unexpectedCall", data: { name: "Math" }, type: "CallExpression", column: 1, endColumn: 7 }] + }, + { + code: "var x = JSON();", + errors: [{ messageId: "unexpectedCall", data: { name: "JSON" }, type: "CallExpression" }] + }, + { + code: "x = JSON(str);", + errors: [{ messageId: "unexpectedCall", data: { name: "JSON" }, type: "CallExpression" }] + }, + { + code: "Math( JSON() );", + errors: [ + { messageId: "unexpectedCall", data: { name: "Math" }, type: "CallExpression", column: 1, endColumn: 15 }, + { messageId: "unexpectedCall", data: { name: "JSON" }, type: "CallExpression", column: 7, endColumn: 13 } + ] + }, + { + code: "var x = Reflect();", + env: { es6: true }, + errors: [{ messageId: "unexpectedCall", data: { name: "Reflect" }, type: "CallExpression" }] + }, + { + code: "var x = Reflect();", + env: { es2017: true }, + errors: [{ messageId: "unexpectedCall", data: { name: "Reflect" }, type: "CallExpression" }] + }, + { + code: "/*globals Reflect: true*/ Reflect();", + errors: [{ messageId: "unexpectedCall", data: { name: "Reflect" }, type: "CallExpression" }] + }, + { + code: "var x = Atomics();", + env: { es2017: true }, + errors: [{ messageId: "unexpectedCall", data: { name: "Atomics" }, type: "CallExpression" }] + }, + { + code: "var x = Atomics();", + env: { es2020: true }, + errors: [{ messageId: "unexpectedCall", data: { name: "Atomics" }, type: "CallExpression" }] + }, + { + code: "var x = Atomics();", + globals: { Atomics: false }, + errors: [{ messageId: "unexpectedCall", data: { name: "Atomics" }, type: "CallExpression" }] + } ] }); diff --git a/tests/lib/rules/no-octal-escape.js b/tests/lib/rules/no-octal-escape.js index b15416ebf95..cd555ab607e 100644 --- a/tests/lib/rules/no-octal-escape.js +++ b/tests/lib/rules/no-octal-escape.js @@ -24,13 +24,34 @@ ruleTester.run("no-octal-escape", rule, { "var foo = \"\\x51\";", "var foo = \"foo \\\\251 bar\";", "var foo = /([abc]) \\1/g;", - "var foo = '\\0';" + "var foo = '\\0';", + "'\\0 '", + "'\\0a'", + "'\\\\1'", + "'\\\\01'", + "'\\08'", + "'\\09'" ], invalid: [ + + // Test full message { code: "var foo = \"foo \\01 bar\";", errors: [{ message: "Don't use octal: '\\01'. Use '\\u....' instead.", type: "Literal" }] }, - { code: "var foo = \"foo \\251 bar\";", errors: [{ message: "Don't use octal: '\\251'. Use '\\u....' instead.", type: "Literal" }] }, - { code: "var foo = \"\\751\";", errors: [{ message: "Don't use octal: '\\75'. Use '\\u....' instead.", type: "Literal" }] }, - { code: "var foo = \"\\3s51\";", errors: [{ message: "Don't use octal: '\\3'. Use '\\u....' instead.", type: "Literal" }] }, - { code: "var foo = \"\\\\\\751\";", errors: [{ message: "Don't use octal: '\\75'. Use '\\u....' instead.", type: "Literal" }] } + + { code: "var foo = \"foo \\251 bar\";", errors: [{ messageId: "octalEscapeSequence", data: { sequence: "251" }, type: "Literal" }] }, + { code: "var foo = \"\\751\";", errors: [{ messageId: "octalEscapeSequence", data: { sequence: "75" }, type: "Literal" }] }, + { code: "var foo = \"\\3s51\";", errors: [{ messageId: "octalEscapeSequence", data: { sequence: "3" }, type: "Literal" }] }, + { code: "var foo = \"\\\\\\751\";", errors: [{ messageId: "octalEscapeSequence", data: { sequence: "75" }, type: "Literal" }] }, + { code: "'\\0\\1'", errors: [{ messageId: "octalEscapeSequence", data: { sequence: "1" }, type: "Literal" }] }, + { code: "'\\0 \\1'", errors: [{ messageId: "octalEscapeSequence", data: { sequence: "1" }, type: "Literal" }] }, + { code: "'\\0\\01'", errors: [{ messageId: "octalEscapeSequence", data: { sequence: "01" }, type: "Literal" }] }, + { code: "'\\0 \\01'", errors: [{ messageId: "octalEscapeSequence", data: { sequence: "01" }, type: "Literal" }] }, + { code: "'\\08\\1'", errors: [{ messageId: "octalEscapeSequence", data: { sequence: "1" }, type: "Literal" }] }, + { code: "'\\08\\01'", errors: [{ messageId: "octalEscapeSequence", data: { sequence: "01" }, type: "Literal" }] }, + + // Only the first one is reported + { code: "'\\01\\02'", errors: [{ messageId: "octalEscapeSequence", data: { sequence: "01" }, type: "Literal" }] }, + { code: "'\\02\\01'", errors: [{ messageId: "octalEscapeSequence", data: { sequence: "02" }, type: "Literal" }] }, + { code: "'\\01\\2'", errors: [{ messageId: "octalEscapeSequence", data: { sequence: "01" }, type: "Literal" }] }, + { code: "'\\2\\01'", errors: [{ messageId: "octalEscapeSequence", data: { sequence: "2" }, type: "Literal" }] } ] }); diff --git a/tests/lib/rules/no-self-assign.js b/tests/lib/rules/no-self-assign.js index fbf52dcba0e..4e168a89789 100644 --- a/tests/lib/rules/no-self-assign.js +++ b/tests/lib/rules/no-self-assign.js @@ -41,6 +41,8 @@ ruleTester.run("no-self-assign", rule, { { code: "({a} = {a: b})", parserOptions: { ecmaVersion: 6 } }, { code: "({a} = {a() {}})", parserOptions: { ecmaVersion: 6 } }, { code: "({a} = {[a]: a})", parserOptions: { ecmaVersion: 6 } }, + { code: "({[a]: b} = {[a]: b})", parserOptions: { ecmaVersion: 6 } }, + { code: "({'foo': a, 1: a} = {'bar': a, 2: a})", parserOptions: { ecmaVersion: 6 } }, { code: "({a, ...b} = {a, ...b})", parserOptions: { ecmaVersion: 2018 } }, { code: "a.b = a.c", options: [{ props: true }] }, { code: "a.b = c.b", options: [{ props: true }] }, @@ -80,6 +82,15 @@ ruleTester.run("no-self-assign", rule, { { code: "[[a], {b}] = [[a], {b}]", parserOptions: { ecmaVersion: 6 }, errors: ["'a' is assigned to itself.", "'b' is assigned to itself."] }, { code: "({a} = {a})", parserOptions: { ecmaVersion: 6 }, errors: ["'a' is assigned to itself."] }, { code: "({a: b} = {a: b})", parserOptions: { ecmaVersion: 6 }, errors: ["'b' is assigned to itself."] }, + { code: "({'a': b} = {'a': b})", parserOptions: { ecmaVersion: 6 }, errors: ["'b' is assigned to itself."] }, + { code: "({a: b} = {'a': b})", parserOptions: { ecmaVersion: 6 }, errors: ["'b' is assigned to itself."] }, + { code: "({'a': b} = {a: b})", parserOptions: { ecmaVersion: 6 }, errors: ["'b' is assigned to itself."] }, + { code: "({1: b} = {1: b})", parserOptions: { ecmaVersion: 6 }, errors: ["'b' is assigned to itself."] }, + { code: "({1: b} = {'1': b})", parserOptions: { ecmaVersion: 6 }, errors: ["'b' is assigned to itself."] }, + { code: "({'1': b} = {1: b})", parserOptions: { ecmaVersion: 6 }, errors: ["'b' is assigned to itself."] }, + { code: "({['a']: b} = {a: b})", parserOptions: { ecmaVersion: 6 }, errors: ["'b' is assigned to itself."] }, + { code: "({'a': b} = {[`a`]: b})", parserOptions: { ecmaVersion: 6 }, errors: ["'b' is assigned to itself."] }, + { code: "({1: b} = {[1]: b})", parserOptions: { ecmaVersion: 6 }, errors: ["'b' is assigned to itself."] }, { code: "({a, b} = {a, b})", parserOptions: { ecmaVersion: 6 }, errors: ["'a' is assigned to itself.", "'b' is assigned to itself."] }, { code: "({a, b} = {b, a})", parserOptions: { ecmaVersion: 6 }, errors: ["'b' is assigned to itself.", "'a' is assigned to itself."] }, { code: "({a, b} = {c, a})", parserOptions: { ecmaVersion: 6 }, errors: ["'a' is assigned to itself."] }, diff --git a/tests/lib/rules/no-sequences.js b/tests/lib/rules/no-sequences.js index 55721de3e9d..7fcba267b7e 100644 --- a/tests/lib/rules/no-sequences.js +++ b/tests/lib/rules/no-sequences.js @@ -54,6 +54,17 @@ ruleTester.run("no-sequences", rule, { // Examples of code that should trigger the rule invalid: [ + { + code: "1, 2;", + errors: [{ + message: "Unexpected use of comma operator.", + type: "SequenceExpression", + line: 1, + column: 2, + endLine: 1, + endColumn: 3 + }] + }, { code: "a = 1, 2", errors: errors(6) }, { code: "do {} while (doSomething(), !!test);", errors: errors(27) }, { code: "for (; doSomething(), !!test; );", errors: errors(21) }, @@ -61,6 +72,9 @@ ruleTester.run("no-sequences", rule, { { code: "switch (doSomething(), val) {}", errors: errors(22) }, { code: "while (doSomething(), !!test);", errors: errors(21) }, { code: "with (doSomething(), val) {}", errors: errors(20) }, - { code: "a => (doSomething(), a)", env: { es6: true }, errors: errors(20) } + { code: "a => (doSomething(), a)", env: { es6: true }, errors: errors(20) }, + { code: "(1), 2", errors: errors(4) }, + { code: "((1)) , (2)", errors: errors(7) }, + { code: "while((1) , 2);", errors: errors(11) } ] }); diff --git a/tests/lib/rules/no-unsafe-negation.js b/tests/lib/rules/no-unsafe-negation.js index 8316aad0227..6ac24541248 100644 --- a/tests/lib/rules/no-unsafe-negation.js +++ b/tests/lib/rules/no-unsafe-negation.js @@ -34,32 +34,26 @@ ruleTester.run("no-unsafe-negation", rule, { invalid: [ { code: "!a in b", - output: "!(a in b)", errors: [unexpectedInError] }, { code: "(!a in b)", - output: "(!(a in b))", errors: [unexpectedInError] }, { code: "!(a) in b", - output: "!((a) in b)", errors: [unexpectedInError] }, { code: "!a instanceof b", - output: "!(a instanceof b)", errors: [unexpectedInstanceofError] }, { code: "(!a instanceof b)", - output: "(!(a instanceof b))", errors: [unexpectedInstanceofError] }, { code: "!(a) instanceof b", - output: "!((a) instanceof b)", errors: [unexpectedInstanceofError] } ] diff --git a/tests/lib/rules/object-curly-spacing.js b/tests/lib/rules/object-curly-spacing.js index 156bdb363b2..305ae28314e 100644 --- a/tests/lib/rules/object-curly-spacing.js +++ b/tests/lib/rules/object-curly-spacing.js @@ -26,6 +26,8 @@ ruleTester.run("object-curly-spacing", rule, { { code: "var obj = { foo: bar, baz: qux };", options: ["always"] }, { code: "var obj = { foo: { bar: quxx }, baz: qux };", options: ["always"] }, { code: "var obj = {\nfoo: bar,\nbaz: qux\n};", options: ["always"] }, + { code: "var obj = { /**/foo:bar/**/ };", options: ["always"] }, + { code: "var obj = { //\nfoo:bar };", options: ["always"] }, // always - destructuring { code: "var { x } = y", options: ["always"], parserOptions: { ecmaVersion: 6 } }, @@ -33,6 +35,8 @@ ruleTester.run("object-curly-spacing", rule, { { code: "var { x,y } = y", options: ["always"], parserOptions: { ecmaVersion: 6 } }, { code: "var {\nx,y } = y", options: ["always"], parserOptions: { ecmaVersion: 6 } }, { code: "var {\nx,y\n} = z", options: ["always"], parserOptions: { ecmaVersion: 6 } }, + { code: "var { /**/x/**/ } = y", options: ["always"], parserOptions: { ecmaVersion: 6 } }, + { code: "var { //\nx } = y", options: ["always"], parserOptions: { ecmaVersion: 6 } }, { code: "var { x = 10, y } = y", options: ["always"], parserOptions: { ecmaVersion: 6 } }, { code: "var { x: { z }, y } = y", options: ["always"], parserOptions: { ecmaVersion: 6 } }, { code: "var {\ny,\n} = x", options: ["always"], parserOptions: { ecmaVersion: 6 } }, @@ -44,6 +48,8 @@ ruleTester.run("object-curly-spacing", rule, { { code: "import * as door from 'room'", options: ["always"], parserOptions: { ecmaVersion: 6, sourceType: "module" } }, { code: "import { door } from 'room'", options: ["always"], parserOptions: { ecmaVersion: 6, sourceType: "module" } }, { code: "import {\ndoor } from 'room'", options: ["always"], parserOptions: { ecmaVersion: 6, sourceType: "module" } }, + { code: "import { /**/door/**/ } from 'room'", options: ["always"], parserOptions: { ecmaVersion: 6, sourceType: "module" } }, + { code: "import { //\ndoor } from 'room'", options: ["always"], parserOptions: { ecmaVersion: 6, sourceType: "module" } }, { code: "export { door } from 'room'", options: ["always"], parserOptions: { ecmaVersion: 6, sourceType: "module" } }, { code: "import { house, mouse } from 'caravan'", options: ["always"], parserOptions: { ecmaVersion: 6, sourceType: "module" } }, { code: "import house, { mouse } from 'caravan'", options: ["always"], parserOptions: { ecmaVersion: 6, sourceType: "module" } }, @@ -55,6 +61,10 @@ ruleTester.run("object-curly-spacing", rule, { { code: "import {\nx,\n} from 'foo';", options: ["always"], parserOptions: { ecmaVersion: 6, sourceType: "module" } }, { code: "export { x, } from 'foo';", options: ["always"], parserOptions: { ecmaVersion: 6, sourceType: "module" } }, { code: "export {\nx,\n} from 'foo';", options: ["always"], parserOptions: { ecmaVersion: 6, sourceType: "module" } }, + { code: "export { /**/x/**/ } from 'foo';", options: ["always"], parserOptions: { ecmaVersion: 6, sourceType: "module" } }, + { code: "export { //\nx } from 'foo';", options: ["always"], parserOptions: { ecmaVersion: 6, sourceType: "module" } }, + { code: "var x = 1;\nexport { /**/x/**/ };", options: ["always"], parserOptions: { ecmaVersion: 6, sourceType: "module" } }, + { code: "var x = 1;\nexport { //\nx };", options: ["always"], parserOptions: { ecmaVersion: 6, sourceType: "module" } }, // always - empty object { code: "var foo = {};", options: ["always"] }, @@ -86,6 +96,8 @@ ruleTester.run("object-curly-spacing", rule, { { code: "var obj = {\nfoo: bar,\nbaz: qux\n};", options: ["never"] }, { code: "var obj = {foo: bar, baz: qux /* */};", options: ["never"] }, { code: "var obj = {/* */ foo: bar, baz: qux};", options: ["never"] }, + { code: "var obj = {//\n foo: bar};", options: ["never"] }, + { code: "var obj = { // line comment exception\n foo: bar};", options: ["never"] }, // never - destructuring { code: "var {x} = y", options: ["never"], parserOptions: { ecmaVersion: 6 } }, @@ -101,6 +113,8 @@ ruleTester.run("object-curly-spacing", rule, { { code: "var {y:x} = x", options: ["never"], parserOptions: { ecmaVersion: 6 } }, { code: "var {/* */ y} = x", options: ["never"], parserOptions: { ecmaVersion: 6 } }, { code: "var {y /* */} = x", options: ["never"], parserOptions: { ecmaVersion: 6 } }, + { code: "var {//\n y} = x", options: ["never"], parserOptions: { ecmaVersion: 6 } }, + { code: "var { // line comment exception\n y} = x", options: ["never"], parserOptions: { ecmaVersion: 6 } }, // never - import / export { code: "import door from 'room'", options: ["never"], parserOptions: { ecmaVersion: 6, sourceType: "module" } }, @@ -111,6 +125,12 @@ ruleTester.run("object-curly-spacing", rule, { { code: "export {/* */ door} from 'room'", options: ["never"], parserOptions: { ecmaVersion: 6, sourceType: "module" } }, { code: "import {door /* */} from 'room'", options: ["never"], parserOptions: { ecmaVersion: 6, sourceType: "module" } }, { code: "export {door /* */} from 'room'", options: ["never"], parserOptions: { ecmaVersion: 6, sourceType: "module" } }, + { code: "import {//\n door} from 'room'", options: ["never"], parserOptions: { ecmaVersion: 6, sourceType: "module" } }, + { code: "export {//\n door} from 'room'", options: ["never"], parserOptions: { ecmaVersion: 6, sourceType: "module" } }, + { code: "var door = foo;\nexport {//\n door}", options: ["never"], parserOptions: { ecmaVersion: 6, sourceType: "module" } }, + { code: "import { // line comment exception\n door} from 'room'", options: ["never"], parserOptions: { ecmaVersion: 6, sourceType: "module" } }, + { code: "export { // line comment exception\n door} from 'room'", options: ["never"], parserOptions: { ecmaVersion: 6, sourceType: "module" } }, + { code: "var door = foo; export { // line comment exception\n door}", options: ["never"], parserOptions: { ecmaVersion: 6, sourceType: "module" } }, { code: "import {\ndoor} from 'room'", options: ["never"], parserOptions: { ecmaVersion: 6, sourceType: "module" } }, { code: "export {\ndoor\n} from 'room'", options: ["never"], parserOptions: { ecmaVersion: 6, sourceType: "module" } }, { code: "import {house,mouse} from 'caravan'", options: ["never"], parserOptions: { ecmaVersion: 6, sourceType: "module" } }, @@ -271,6 +291,20 @@ ruleTester.run("object-curly-spacing", rule, { } ] }, + { + code: "import x, {//\n bar } from 'foo';", + output: "import x, { //\n bar } from 'foo';", + options: ["always"], + parserOptions: { ecmaVersion: 6, sourceType: "module" }, + errors: [ + { + message: "A space is required after '{'.", + type: "ImportDeclaration", + line: 1, + column: 11 + } + ] + }, { code: "import x, { bar, baz} from 'foo';", output: "import x, { bar, baz } from 'foo';", @@ -408,6 +442,40 @@ ruleTester.run("object-curly-spacing", rule, { } ] }, + { + code: "var bar = 0;\nexport {/* */ bar /* */};", + output: "var bar = 0;\nexport { /* */ bar /* */ };", + options: ["always"], + parserOptions: { ecmaVersion: 6, sourceType: "module" }, + errors: [ + { + message: "A space is required after '{'.", + type: "ExportNamedDeclaration", + line: 2, + column: 8 + }, + { + message: "A space is required before '}'.", + type: "ExportNamedDeclaration", + line: 2, + column: 24 + } + ] + }, + { + code: "var bar = 0;\nexport {//\n bar };", + output: "var bar = 0;\nexport { //\n bar };", + options: ["always"], + parserOptions: { ecmaVersion: 6, sourceType: "module" }, + errors: [ + { + message: "A space is required after '{'.", + type: "ExportNamedDeclaration", + line: 2, + column: 8 + } + ] + }, { code: "var bar = 0;\nexport { /* */ bar /* */ };", output: "var bar = 0;\nexport {/* */ bar /* */};", @@ -619,6 +687,19 @@ ruleTester.run("object-curly-spacing", rule, { } ] }, + { + code: "var obj = {//\n foo: bar };", + output: "var obj = { //\n foo: bar };", + options: ["always"], + errors: [ + { + message: "A space is required after '{'.", + type: "ObjectExpression", + line: 1, + column: 11 + } + ] + }, { code: "var obj = { foo: bar, baz: qux};", output: "var obj = { foo: bar, baz: qux };", @@ -716,6 +797,19 @@ ruleTester.run("object-curly-spacing", rule, { } ] }, + { + code: "var obj = { // line comment exception\n foo: bar };", + output: "var obj = { // line comment exception\n foo: bar};", + options: ["never"], + errors: [ + { + message: "There should be no space before '}'.", + type: "ObjectExpression", + line: 2, + column: 11 + } + ] + }, { code: "var obj = { foo: { bar: quxx}, baz: qux};", output: "var obj = {foo: {bar: quxx}, baz: qux};", @@ -832,6 +926,20 @@ ruleTester.run("object-curly-spacing", rule, { } ] }, + { + code: "var {//\n x } = y", + output: "var { //\n x } = y", + options: ["always"], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + message: "A space is required after '{'.", + type: "ObjectPattern", + line: 1, + column: 5 + } + ] + }, { code: "var { x, y } = y", output: "var {x, y} = y", diff --git a/tests/lib/rules/object-shorthand.js b/tests/lib/rules/object-shorthand.js index 04d702535ba..911df1e3a41 100644 --- a/tests/lib/rules/object-shorthand.js +++ b/tests/lib/rules/object-shorthand.js @@ -11,6 +11,7 @@ const rule = require("../../../lib/rules/object-shorthand"), { RuleTester } = require("../../../lib/rule-tester"); +const { unIndent } = require("../_utils"); //------------------------------------------------------------------------------ // Tests @@ -1070,6 +1071,36 @@ ruleTester.run("object-shorthand", rule, { options: ["always", { avoidExplicitReturnArrows: true }], errors: [METHOD_ERROR] }, + { + code: "({ a: ((arg) => { return foo; }) })", + output: "({ a(arg) { return foo; } })", + options: ["always", { avoidExplicitReturnArrows: true }], + errors: [METHOD_ERROR] + }, + { + code: "({ a: ((arg, arg2) => { return foo; }) })", + output: "({ a(arg, arg2) { return foo; } })", + options: ["always", { avoidExplicitReturnArrows: true }], + errors: [METHOD_ERROR] + }, + { + code: "({ a: (async () => { return foo; }) })", + output: "({ async a() { return foo; } })", + options: ["always", { avoidExplicitReturnArrows: true }], + errors: [METHOD_ERROR] + }, + { + code: "({ a: (async (arg) => { return foo; }) })", + output: "({ async a(arg) { return foo; } })", + options: ["always", { avoidExplicitReturnArrows: true }], + errors: [METHOD_ERROR] + }, + { + code: "({ a: (async (arg, arg2) => { return foo; }) })", + output: "({ async a(arg, arg2) { return foo; } })", + options: ["always", { avoidExplicitReturnArrows: true }], + errors: [METHOD_ERROR] + }, // async generators { @@ -1083,6 +1114,67 @@ ruleTester.run("object-shorthand", rule, { output: "({ a: async function*() {} })", options: ["never"], errors: [LONGFORM_METHOD_ERROR] + }, + + // typescript: arrow function should preserve the return value + { + code: unIndent` + const test = { + key: (): void => {x()}, + key: ( (): void => {x()} ), + key: ( (): (void) => {x()} ), + + key: (arg: t): void => {x()}, + key: ( (arg: t): void => {x()} ), + key: ( (arg: t): (void) => {x()} ), + + key: (arg: t, arg2: t): void => {x()}, + key: ( (arg: t, arg2: t): void => {x()} ), + key: ( (arg: t, arg2: t): (void) => {x()} ), + + key: async (): void => {x()}, + key: ( async (): void => {x()} ), + key: ( async (): (void) => {x()} ), + + key: async (arg: t): void => {x()}, + key: ( async (arg: t): void => {x()} ), + key: ( async (arg: t): (void) => {x()} ), + + key: async (arg: t, arg2: t): void => {x()}, + key: ( async (arg: t, arg2: t): void => {x()} ), + key: ( async (arg: t, arg2: t): (void) => {x()} ), + } + `, + output: unIndent` + const test = { + key(): void {x()}, + key(): void {x()}, + key(): (void) {x()}, + + key(arg: t): void {x()}, + key(arg: t): void {x()}, + key(arg: t): (void) {x()}, + + key(arg: t, arg2: t): void {x()}, + key(arg: t, arg2: t): void {x()}, + key(arg: t, arg2: t): (void) {x()}, + + async key(): void {x()}, + async key(): void {x()}, + async key(): (void) {x()}, + + async key(arg: t): void {x()}, + async key(arg: t): void {x()}, + async key(arg: t): (void) {x()}, + + async key(arg: t, arg2: t): void {x()}, + async key(arg: t, arg2: t): void {x()}, + async key(arg: t, arg2: t): (void) {x()}, + } + `, + options: ["always", { avoidExplicitReturnArrows: true }], + parser: require.resolve("../../fixtures/parsers/typescript-parsers/object-with-arrow-fn-props"), + errors: Array(18).fill(METHOD_ERROR) } ] }); diff --git a/tests/lib/rules/prefer-regex-literals.js b/tests/lib/rules/prefer-regex-literals.js new file mode 100644 index 00000000000..e263ef03dc7 --- /dev/null +++ b/tests/lib/rules/prefer-regex-literals.js @@ -0,0 +1,182 @@ +/** + * @fileoverview Tests for the prefer-regex-literals rule + * @author Milos Djermanovic + */ + +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const rule = require("../../../lib/rules/prefer-regex-literals"); +const { RuleTester } = require("../../../lib/rule-tester"); + +//------------------------------------------------------------------------------ +// Tests +//------------------------------------------------------------------------------ + +const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 2015 } }); + +ruleTester.run("prefer-regex-literals", rule, { + valid: [ + "/abc/", + "/abc/g", + + // considered as dynamic + "new RegExp(pattern)", + "RegExp(pattern, 'g')", + "new RegExp(f('a'))", + "RegExp(prefix + 'a')", + "new RegExp('a' + sufix)", + "RegExp(`a` + sufix);", + "new RegExp(String.raw`a` + sufix);", + "RegExp('a', flags)", + "RegExp('a', 'g' + flags)", + "new RegExp(String.raw`a`, flags);", + "RegExp(`${prefix}abc`)", + "new RegExp(`a${b}c`);", + "new RegExp(`a${''}c`);", + "new RegExp(String.raw`a${b}c`);", + "new RegExp(String.raw`a${''}c`);", + "new RegExp('a' + 'b')", + "RegExp(1)", + + // invalid number of arguments + "new RegExp;", + "new RegExp();", + "RegExp();", + "new RegExp('a', 'g', 'b');", + "RegExp('a', 'g', 'b');", + "new RegExp(`a`, `g`, `b`);", + "RegExp(`a`, `g`, `b`);", + "new RegExp(String.raw`a`, String.raw`g`, String.raw`b`);", + "RegExp(String.raw`a`, String.raw`g`, String.raw`b`);", + + // not String.raw`` + "new RegExp(String`a`);", + "RegExp(raw`a`);", + "new RegExp(f(String.raw)`a`);", + "RegExp(string.raw`a`);", + "new RegExp(String.Raw`a`);", + "new RegExp(String[raw]`a`);", + "RegExp(String.raw.foo`a`);", + "new RegExp(String.foo.raw`a`);", + "RegExp(foo.String.raw`a`);", + "new RegExp(String.raw);", + + // not the global String in String.raw`` + "let String; new RegExp(String.raw`a`);", + "function foo() { var String; new RegExp(String.raw`a`); }", + "function foo(String) { RegExp(String.raw`a`); }", + "if (foo) { const String = bar; RegExp(String.raw`a`); }", + "/* globals String:off */ new RegExp(String.raw`a`);", + { + code: "RegExp('a', String.raw`g`);", + globals: { String: "off" } + }, + + // not RegExp + "new Regexp('abc');", + "Regexp(`a`);", + "new Regexp(String.raw`a`);", + + // not the global RegExp + "let RegExp; new RegExp('a');", + "function foo() { var RegExp; RegExp('a', 'g'); }", + "function foo(RegExp) { new RegExp(String.raw`a`); }", + "if (foo) { const RegExp = bar; RegExp('a'); }", + "/* globals RegExp:off */ new RegExp('a');", + { + code: "RegExp('a');", + globals: { RegExp: "off" } + } + ], + + invalid: [ + { + code: "new RegExp('abc');", + errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }] + }, + { + code: "RegExp('abc');", + errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }] + }, + { + code: "new RegExp('abc', 'g');", + errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }] + }, + { + code: "RegExp('abc', 'g');", + errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }] + }, + { + code: "new RegExp(`abc`);", + errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }] + }, + { + code: "RegExp(`abc`);", + errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }] + }, + { + code: "new RegExp(`abc`, `g`);", + errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }] + }, + { + code: "RegExp(`abc`, `g`);", + errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }] + }, + { + code: "new RegExp(String.raw`abc`);", + errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }] + }, + { + code: "RegExp(String.raw`abc`);", + errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }] + }, + { + code: "new RegExp(String.raw`abc`, String.raw`g`);", + errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }] + }, + { + code: "RegExp(String.raw`abc`, String.raw`g`);", + errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }] + }, + { + code: "new RegExp(String['raw']`a`);", + errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }] + }, + { + code: "new RegExp('');", + errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }] + }, + { + code: "RegExp('', '');", + errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }] + }, + { + code: "new RegExp(String.raw``);", + errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }] + }, + { + code: "new RegExp('a', `g`);", + errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }] + }, + { + code: "RegExp(`a`, 'g');", + errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }] + }, + { + code: "RegExp(String.raw`a`, 'g');", + errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }] + }, + { + code: "new RegExp(String.raw`\\d`, `g`);", + errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }] + }, + { + code: "RegExp('a', String.raw`g`);", + errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }] + } + ] +}); diff --git a/tests/lib/rules/space-before-function-paren.js b/tests/lib/rules/space-before-function-paren.js index 5bcfd7be16c..961d6895adc 100644 --- a/tests/lib/rules/space-before-function-paren.js +++ b/tests/lib/rules/space-before-function-paren.js @@ -24,6 +24,11 @@ ruleTester.run("space-before-function-paren", rule, { "function foo () {}", "var foo = function () {}", "var bar = function foo () {}", + "var bar = function foo/**/ () {}", + "var bar = function foo /**/() {}", + "var bar = function foo/**/\n() {}", + "var bar = function foo\n/**/() {}", + "var bar = function foo//\n() {}", "var obj = { get foo () {}, set foo (val) {} };", { code: "var obj = { foo () {} };", @@ -34,6 +39,9 @@ ruleTester.run("space-before-function-paren", rule, { { code: "function foo() {}", options: ["never"] }, { code: "var foo = function() {}", options: ["never"] }, + { code: "var foo = function/**/() {}", options: ["never"] }, + { code: "var foo = function/* */() {}", options: ["never"] }, + { code: "var foo = function/* *//* */() {}", options: ["never"] }, { code: "var bar = function foo() {}", options: ["never"] }, { code: "var obj = { get foo() {}, set foo(val) {} };", options: ["never"] }, { @@ -226,6 +234,84 @@ ruleTester.run("space-before-function-paren", rule, { } ] }, + { + code: "function foo /* */ () {}", + output: "function foo/* */() {}", + options: ["never"], + errors: [ + { + type: "FunctionDeclaration", + message: "Unexpected space before function parentheses.", + line: 1, + column: 13 + } + ] + }, + { + code: "function foo/* block comment */ () {}", + output: "function foo/* block comment */() {}", + options: ["never"], + errors: [ + { + type: "FunctionDeclaration", + message: "Unexpected space before function parentheses.", + line: 1, + column: 13 + } + ] + }, + { + code: "function foo/* 1 */ /* 2 */ \n /* 3 */\n/* 4 */ () {}", + output: "function foo/* 1 *//* 2 *//* 3 *//* 4 */() {}", + options: ["never"], + errors: [ + { + type: "FunctionDeclaration", + message: "Unexpected space before function parentheses.", + line: 1, + column: 13 + } + ] + }, + { + code: "function foo//\n() {}", + output: null, + options: ["never"], + errors: [ + { + type: "FunctionDeclaration", + message: "Unexpected space before function parentheses.", + line: 1, + column: 13 + } + ] + }, + { + code: "function foo // line comment \n () {}", + output: null, + options: ["never"], + errors: [ + { + type: "FunctionDeclaration", + message: "Unexpected space before function parentheses.", + line: 1, + column: 13 + } + ] + }, + { + code: "function foo\n//\n() {}", + output: null, + options: ["never"], + errors: [ + { + type: "FunctionDeclaration", + message: "Unexpected space before function parentheses.", + line: 1, + column: 13 + } + ] + }, { code: "var foo = function () {}", output: "var foo = function() {}", diff --git a/tools/rule-types.json b/tools/rule-types.json index 74cae9391cb..6c72abb6cb2 100644 --- a/tools/rule-types.json +++ b/tools/rule-types.json @@ -119,6 +119,7 @@ "no-implicit-coercion": "suggestion", "no-implicit-globals": "suggestion", "no-implied-eval": "suggestion", + "no-import-assign": "problem", "no-inline-comments": "suggestion", "no-inner-declarations": "problem", "no-invalid-regexp": "problem", @@ -229,6 +230,7 @@ "prefer-object-spread": "suggestion", "prefer-promise-reject-errors": "suggestion", "prefer-reflect": "suggestion", + "prefer-regex-literals": "suggestion", "prefer-rest-params": "suggestion", "prefer-spread": "suggestion", "prefer-template": "suggestion",