From 938f32a2c9c769f80e025b3b9eb1fc9a6177aa9a Mon Sep 17 00:00:00 2001 From: medusalix Date: Thu, 26 Mar 2020 19:14:55 +0100 Subject: [PATCH 01/13] Add `disallow-objects-as-default` rule --- docs/rules/disallow-objects-as-default.md | 29 ++++++++++ index.js | 1 + readme.md | 2 + rules/disallow-objects-as-default.js | 36 ++++++++++++ test/disallow-objects-as-default.js | 70 +++++++++++++++++++++++ 5 files changed, 138 insertions(+) create mode 100644 docs/rules/disallow-objects-as-default.md create mode 100644 rules/disallow-objects-as-default.js create mode 100644 test/disallow-objects-as-default.js diff --git a/docs/rules/disallow-objects-as-default.md b/docs/rules/disallow-objects-as-default.md new file mode 100644 index 0000000000..7c32c842bd --- /dev/null +++ b/docs/rules/disallow-objects-as-default.md @@ -0,0 +1,29 @@ +# Disallow the use of objects as default parameters + +Default parameters should not be passed to a function through an object. The `foo = {a: false}` parameter works fine if only used with one option. As soon as additional options are added, you risk replacing the whole `foo = {a: false, b: true}` object when passing only one option: `{a: true}`. For this reason, object destructuring should be used instead. + + +## Fail + +```js +const abc = (foo = {a: false}) => {}; +``` + +```js +const abc = (foo = {a: false, b: 123}) => {}; +``` + + +## Pass + +```js +const abc = (foo = {}) => {}; +``` + +```js +const abc = (foo = false) => {}; +``` + +```js +const foo = ({a = false, b = 123}) => {}; +``` diff --git a/index.js b/index.js index 21ef42c3f6..431e85a677 100644 --- a/index.js +++ b/index.js @@ -21,6 +21,7 @@ module.exports = { 'unicorn/catch-error-name': 'error', 'unicorn/consistent-function-scoping': 'error', 'unicorn/custom-error-definition': 'off', + 'unicorn/disallow-objects-as-default': 'error', 'unicorn/error-message': 'error', 'unicorn/escape-case': 'error', 'unicorn/expiring-todo-comments': 'error', diff --git a/readme.md b/readme.md index 2a0503dd0d..212e42a7a0 100644 --- a/readme.md +++ b/readme.md @@ -37,6 +37,7 @@ Configure it in `package.json`. "unicorn/catch-error-name": "error", "unicorn/consistent-function-scoping": "error", "unicorn/custom-error-definition": "off", + "unicorn/disallow-objects-as-default": "error", "unicorn/error-message": "error", "unicorn/escape-case": "error", "unicorn/expiring-todo-comments": "error", @@ -99,6 +100,7 @@ Configure it in `package.json`. - [catch-error-name](docs/rules/catch-error-name.md) - Enforce a specific parameter name in catch clauses. *(fixable)* - [consistent-function-scoping](docs/rules/consistent-function-scoping.md) - Move function definitions to the highest possible scope. - [custom-error-definition](docs/rules/custom-error-definition.md) - Enforce correct `Error` subclassing. *(fixable)* +- [disallow-objects-as-default](docs/rules/disallow-objects-as-default.md) - Disallow the use of objects as default parameters. - [error-message](docs/rules/error-message.md) - Enforce passing a `message` value when throwing a built-in error. - [escape-case](docs/rules/escape-case.md) - Require escape sequences to use uppercase values. *(fixable)* - [expiring-todo-comments](docs/rules/expiring-todo-comments.md) - Add expiration conditions to TODO comments. diff --git a/rules/disallow-objects-as-default.js b/rules/disallow-objects-as-default.js new file mode 100644 index 0000000000..a2d3c80cc2 --- /dev/null +++ b/rules/disallow-objects-as-default.js @@ -0,0 +1,36 @@ +'use strict'; +const getDocumentationUrl = require('./utils/get-documentation-url'); + +const MESSAGE_ID = 'disallowObjectsAsDefault'; + +const objectParameterSelector = [ + 'AssignmentPattern', + '[left.type="Identifier"]', + '[right.type="ObjectExpression"]', + '[right.properties.length>0]' +].join(''); + +const create = context => { + return { + [objectParameterSelector]: node => { + context.report({ + node, + messageId: MESSAGE_ID, + data: {parameter: node.left.name} + }); + } + }; +}; + +module.exports = { + create, + meta: { + type: 'problem', + docs: { + url: getDocumentationUrl(__filename) + }, + messages: { + [MESSAGE_ID]: 'Do not assign default object to parameter `{{parameter}}`.' + } + } +}; diff --git a/test/disallow-objects-as-default.js b/test/disallow-objects-as-default.js new file mode 100644 index 0000000000..7e3f6d53a4 --- /dev/null +++ b/test/disallow-objects-as-default.js @@ -0,0 +1,70 @@ +import test from 'ava'; +import avaRuleTester from 'eslint-ava-rule-tester'; +import rule from '../rules/disallow-objects-as-default'; + +const ruleTester = avaRuleTester(test, { + env: { + es6: true + } +}); + +const error = { + ruleId: 'disallow-objects-as-default', + messageId: 'disallowObjectsAsDefault', + data: {parameter: 'foo'} +}; + +ruleTester.run('disallow-objects-as-default', rule, { + valid: [ + 'const abc = {};', + 'const abc = {foo: 123};', + 'function abc(foo) {}', + 'function abc(foo = null) {}', + 'function abc(foo = undefined) {}', + 'function abc(foo = 123) {}', + 'function abc(foo = true) {}', + 'function abc(foo = \'bar\') {}', + 'function abc(foo = 123, bar = \'foo\') {}', + 'function abc(foo = {}) {}', + 'function abc({foo = 123} = {}) {}', + 'const abc = foo => {};', + 'const abc = (foo = null) => {};', + 'const abc = (foo = undefined) => {};', + 'const abc = (foo = 123) => {};', + 'const abc = (foo = true) => {};', + 'const abc = (foo = \'bar\') => {};', + 'const abc = (foo = 123, bar = \'foo\') => {};', + 'const abc = (foo = {}) => {};', + 'const abc = ({a = true, b = \'foo\'}) => {};' + ], + invalid: [ + { + code: 'function abc(foo = {a: 123}) {}', + errors: [error] + }, + { + code: 'function abc(foo = {a: false}) {}', + errors: [error] + }, + { + code: 'function abc(foo = {a: \'bar\'}) {}', + errors: [error] + }, + { + code: 'function abc(foo = {a: \'bar\', b: {c: true}}) {}', + errors: [error] + }, + { + code: 'const abc = (foo = {a: false}) => {};', + errors: [error] + }, + { + code: 'const abc = (foo = {a: 123, b: false}) => {};', + errors: [error] + }, + { + code: 'const abc = (foo = {a: false, b: 1, c: "test", d: null}) => {};', + errors: [error] + } + ] +}); From 6a89a88e52722b2eb1b42acb2b6e895967b23e34 Mon Sep 17 00:00:00 2001 From: medusalix Date: Fri, 27 Mar 2020 17:08:48 +0100 Subject: [PATCH 02/13] Rename to `no-object-as-default` --- ...llow-objects-as-default.md => no-object-as-default.md} | 0 index.js | 2 +- readme.md | 4 ++-- ...llow-objects-as-default.js => no-object-as-default.js} | 2 +- ...llow-objects-as-default.js => no-object-as-default.js} | 8 ++++---- 5 files changed, 8 insertions(+), 8 deletions(-) rename docs/rules/{disallow-objects-as-default.md => no-object-as-default.md} (100%) rename rules/{disallow-objects-as-default.js => no-object-as-default.js} (93%) rename test/{disallow-objects-as-default.js => no-object-as-default.js} (88%) diff --git a/docs/rules/disallow-objects-as-default.md b/docs/rules/no-object-as-default.md similarity index 100% rename from docs/rules/disallow-objects-as-default.md rename to docs/rules/no-object-as-default.md diff --git a/index.js b/index.js index 431e85a677..58611f2a78 100644 --- a/index.js +++ b/index.js @@ -21,7 +21,6 @@ module.exports = { 'unicorn/catch-error-name': 'error', 'unicorn/consistent-function-scoping': 'error', 'unicorn/custom-error-definition': 'off', - 'unicorn/disallow-objects-as-default': 'error', 'unicorn/error-message': 'error', 'unicorn/escape-case': 'error', 'unicorn/expiring-todo-comments': 'error', @@ -40,6 +39,7 @@ module.exports = { 'unicorn/no-nested-ternary': 'error', 'unicorn/no-new-buffer': 'error', 'unicorn/no-null': 'error', + 'unicorn/no-object-as-default': 'error', 'unicorn/no-process-exit': 'error', 'unicorn/no-reduce': 'error', 'unicorn/no-unreadable-array-destructuring': 'error', diff --git a/readme.md b/readme.md index 212e42a7a0..5cfd26fed0 100644 --- a/readme.md +++ b/readme.md @@ -37,7 +37,6 @@ Configure it in `package.json`. "unicorn/catch-error-name": "error", "unicorn/consistent-function-scoping": "error", "unicorn/custom-error-definition": "off", - "unicorn/disallow-objects-as-default": "error", "unicorn/error-message": "error", "unicorn/escape-case": "error", "unicorn/expiring-todo-comments": "error", @@ -56,6 +55,7 @@ Configure it in `package.json`. "unicorn/no-nested-ternary": "error", "unicorn/no-new-buffer": "error", "unicorn/no-null": "error", + "unicorn/no-object-as-default": "error", "unicorn/no-process-exit": "error", "unicorn/no-reduce": "error", "unicorn/no-unreadable-array-destructuring": "error", @@ -100,7 +100,6 @@ Configure it in `package.json`. - [catch-error-name](docs/rules/catch-error-name.md) - Enforce a specific parameter name in catch clauses. *(fixable)* - [consistent-function-scoping](docs/rules/consistent-function-scoping.md) - Move function definitions to the highest possible scope. - [custom-error-definition](docs/rules/custom-error-definition.md) - Enforce correct `Error` subclassing. *(fixable)* -- [disallow-objects-as-default](docs/rules/disallow-objects-as-default.md) - Disallow the use of objects as default parameters. - [error-message](docs/rules/error-message.md) - Enforce passing a `message` value when throwing a built-in error. - [escape-case](docs/rules/escape-case.md) - Require escape sequences to use uppercase values. *(fixable)* - [expiring-todo-comments](docs/rules/expiring-todo-comments.md) - Add expiration conditions to TODO comments. @@ -118,6 +117,7 @@ Configure it in `package.json`. - [no-nested-ternary](docs/rules/no-nested-ternary.md) - Disallow nested ternary expressions. *(partly fixable)* - [no-new-buffer](docs/rules/no-new-buffer.md) - Enforce the use of `Buffer.from()` and `Buffer.alloc()` instead of the deprecated `new Buffer()`. *(fixable)* - [no-null](docs/rules/no-null.md) - Disallow the use of the `null` literal. +- [no-object-as-default](docs/rules/no-object-as-default.md) - Disallow the use of objects as default parameters. - [no-process-exit](docs/rules/no-process-exit.md) - Disallow `process.exit()`. - [no-reduce](docs/rules/no-reduce.md) - Disallow `Array#reduce()` and `Array#reduceRight()`. - [no-unreadable-array-destructuring](docs/rules/no-unreadable-array-destructuring.md) - Disallow unreadable array destructuring. diff --git a/rules/disallow-objects-as-default.js b/rules/no-object-as-default.js similarity index 93% rename from rules/disallow-objects-as-default.js rename to rules/no-object-as-default.js index a2d3c80cc2..b3812fbf57 100644 --- a/rules/disallow-objects-as-default.js +++ b/rules/no-object-as-default.js @@ -1,7 +1,7 @@ 'use strict'; const getDocumentationUrl = require('./utils/get-documentation-url'); -const MESSAGE_ID = 'disallowObjectsAsDefault'; +const MESSAGE_ID = 'noObjectAsDefault'; const objectParameterSelector = [ 'AssignmentPattern', diff --git a/test/disallow-objects-as-default.js b/test/no-object-as-default.js similarity index 88% rename from test/disallow-objects-as-default.js rename to test/no-object-as-default.js index 7e3f6d53a4..e68d1bf5a0 100644 --- a/test/disallow-objects-as-default.js +++ b/test/no-object-as-default.js @@ -1,6 +1,6 @@ import test from 'ava'; import avaRuleTester from 'eslint-ava-rule-tester'; -import rule from '../rules/disallow-objects-as-default'; +import rule from '../rules/no-object-as-default'; const ruleTester = avaRuleTester(test, { env: { @@ -9,12 +9,12 @@ const ruleTester = avaRuleTester(test, { }); const error = { - ruleId: 'disallow-objects-as-default', - messageId: 'disallowObjectsAsDefault', + ruleId: 'no-object-as-default', + messageId: 'noObjectAsDefault', data: {parameter: 'foo'} }; -ruleTester.run('disallow-objects-as-default', rule, { +ruleTester.run('no-object-as-default', rule, { valid: [ 'const abc = {};', 'const abc = {foo: 123};', From 261becc57c2d6b678454b7c3d8c05e0fee040b9a Mon Sep 17 00:00:00 2001 From: medusalix Date: Sat, 6 Jun 2020 19:10:39 +0200 Subject: [PATCH 03/13] Remove `ruleId` from tests --- test/no-object-as-default.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/no-object-as-default.js b/test/no-object-as-default.js index e68d1bf5a0..995a4aaff6 100644 --- a/test/no-object-as-default.js +++ b/test/no-object-as-default.js @@ -9,7 +9,6 @@ const ruleTester = avaRuleTester(test, { }); const error = { - ruleId: 'no-object-as-default', messageId: 'noObjectAsDefault', data: {parameter: 'foo'} }; From d7d1cb28e2b4e54cd601948f02f3679c1c08de52 Mon Sep 17 00:00:00 2001 From: Severin Date: Sun, 28 Jun 2020 13:39:12 +0200 Subject: [PATCH 04/13] Update docs Co-authored-by: Sindre Sorhus --- docs/rules/no-object-as-default.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/rules/no-object-as-default.md b/docs/rules/no-object-as-default.md index 7c32c842bd..d1c66b2a03 100644 --- a/docs/rules/no-object-as-default.md +++ b/docs/rules/no-object-as-default.md @@ -1,6 +1,6 @@ # Disallow the use of objects as default parameters -Default parameters should not be passed to a function through an object. The `foo = {a: false}` parameter works fine if only used with one option. As soon as additional options are added, you risk replacing the whole `foo = {a: false, b: true}` object when passing only one option: `{a: true}`. For this reason, object destructuring should be used instead. +Default parameters should not be passed to a function through an object literal. The `foo = {a: false}` parameter works fine if only used with one option. As soon as additional options are added, you risk replacing the whole `foo = {a: false, b: true}` object when passing only one option: `{a: true}`. For this reason, object destructuring should be used instead. ## Fail From a476d857d6fa5948453e8fa81afd04901f72e397 Mon Sep 17 00:00:00 2001 From: Severin Date: Sun, 28 Jun 2020 13:39:26 +0200 Subject: [PATCH 05/13] Update message Co-authored-by: Sindre Sorhus --- rules/no-object-as-default.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/no-object-as-default.js b/rules/no-object-as-default.js index b3812fbf57..cbba381f32 100644 --- a/rules/no-object-as-default.js +++ b/rules/no-object-as-default.js @@ -30,7 +30,7 @@ module.exports = { url: getDocumentationUrl(__filename) }, messages: { - [MESSAGE_ID]: 'Do not assign default object to parameter `{{parameter}}`.' + [MESSAGE_ID]: 'Do not use an object literal as default for parameter `{{parameter}}`.' } } }; From f3f4b6a8d06ee17010f6d11bda3c1add2c3892e0 Mon Sep 17 00:00:00 2001 From: medusalix Date: Sun, 28 Jun 2020 14:38:46 +0200 Subject: [PATCH 06/13] Rename to `no-object-as-default-parameter` --- ...ject-as-default.md => no-object-as-default-parameter.md} | 0 index.js | 2 +- readme.md | 4 ++-- ...ject-as-default.js => no-object-as-default-parameter.js} | 2 +- ...ject-as-default.js => no-object-as-default-parameter.js} | 6 +++--- 5 files changed, 7 insertions(+), 7 deletions(-) rename docs/rules/{no-object-as-default.md => no-object-as-default-parameter.md} (100%) rename rules/{no-object-as-default.js => no-object-as-default-parameter.js} (93%) rename test/{no-object-as-default.js => no-object-as-default-parameter.js} (90%) diff --git a/docs/rules/no-object-as-default.md b/docs/rules/no-object-as-default-parameter.md similarity index 100% rename from docs/rules/no-object-as-default.md rename to docs/rules/no-object-as-default-parameter.md diff --git a/index.js b/index.js index 58611f2a78..1c0b88e4b1 100644 --- a/index.js +++ b/index.js @@ -39,7 +39,7 @@ module.exports = { 'unicorn/no-nested-ternary': 'error', 'unicorn/no-new-buffer': 'error', 'unicorn/no-null': 'error', - 'unicorn/no-object-as-default': 'error', + 'unicorn/no-object-as-default-parameter': 'error', 'unicorn/no-process-exit': 'error', 'unicorn/no-reduce': 'error', 'unicorn/no-unreadable-array-destructuring': 'error', diff --git a/readme.md b/readme.md index 5cfd26fed0..37d1a14fb1 100644 --- a/readme.md +++ b/readme.md @@ -55,7 +55,7 @@ Configure it in `package.json`. "unicorn/no-nested-ternary": "error", "unicorn/no-new-buffer": "error", "unicorn/no-null": "error", - "unicorn/no-object-as-default": "error", + "unicorn/no-object-as-default-parameter": "error", "unicorn/no-process-exit": "error", "unicorn/no-reduce": "error", "unicorn/no-unreadable-array-destructuring": "error", @@ -117,7 +117,7 @@ Configure it in `package.json`. - [no-nested-ternary](docs/rules/no-nested-ternary.md) - Disallow nested ternary expressions. *(partly fixable)* - [no-new-buffer](docs/rules/no-new-buffer.md) - Enforce the use of `Buffer.from()` and `Buffer.alloc()` instead of the deprecated `new Buffer()`. *(fixable)* - [no-null](docs/rules/no-null.md) - Disallow the use of the `null` literal. -- [no-object-as-default](docs/rules/no-object-as-default.md) - Disallow the use of objects as default parameters. +- [no-object-as-default-parameter](docs/rules/no-object-as-default-parameter.md) - Disallow the use of objects as default parameters. - [no-process-exit](docs/rules/no-process-exit.md) - Disallow `process.exit()`. - [no-reduce](docs/rules/no-reduce.md) - Disallow `Array#reduce()` and `Array#reduceRight()`. - [no-unreadable-array-destructuring](docs/rules/no-unreadable-array-destructuring.md) - Disallow unreadable array destructuring. diff --git a/rules/no-object-as-default.js b/rules/no-object-as-default-parameter.js similarity index 93% rename from rules/no-object-as-default.js rename to rules/no-object-as-default-parameter.js index cbba381f32..602fe63874 100644 --- a/rules/no-object-as-default.js +++ b/rules/no-object-as-default-parameter.js @@ -1,7 +1,7 @@ 'use strict'; const getDocumentationUrl = require('./utils/get-documentation-url'); -const MESSAGE_ID = 'noObjectAsDefault'; +const MESSAGE_ID = 'noObjectAsDefaultParameter'; const objectParameterSelector = [ 'AssignmentPattern', diff --git a/test/no-object-as-default.js b/test/no-object-as-default-parameter.js similarity index 90% rename from test/no-object-as-default.js rename to test/no-object-as-default-parameter.js index 995a4aaff6..564de27640 100644 --- a/test/no-object-as-default.js +++ b/test/no-object-as-default-parameter.js @@ -1,6 +1,6 @@ import test from 'ava'; import avaRuleTester from 'eslint-ava-rule-tester'; -import rule from '../rules/no-object-as-default'; +import rule from '../rules/no-object-as-default-parameter'; const ruleTester = avaRuleTester(test, { env: { @@ -9,11 +9,11 @@ const ruleTester = avaRuleTester(test, { }); const error = { - messageId: 'noObjectAsDefault', + messageId: 'noObjectAsDefaultParameter', data: {parameter: 'foo'} }; -ruleTester.run('no-object-as-default', rule, { +ruleTester.run('no-object-as-default-parameter', rule, { valid: [ 'const abc = {};', 'const abc = {foo: 123};', From b2488cda3e04ed252c0b10da2ebfc517f90f393a Mon Sep 17 00:00:00 2001 From: medusalix Date: Sun, 28 Jun 2020 16:30:35 +0200 Subject: [PATCH 07/13] Fix default value assignment --- rules/no-object-as-default-parameter.js | 2 ++ test/no-object-as-default-parameter.js | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/rules/no-object-as-default-parameter.js b/rules/no-object-as-default-parameter.js index 602fe63874..22653efd14 100644 --- a/rules/no-object-as-default-parameter.js +++ b/rules/no-object-as-default-parameter.js @@ -4,6 +4,8 @@ const getDocumentationUrl = require('./utils/get-documentation-url'); const MESSAGE_ID = 'noObjectAsDefaultParameter'; const objectParameterSelector = [ + ':matches(FunctionDeclaration, ArrowFunctionExpression)', + '>', 'AssignmentPattern', '[left.type="Identifier"]', '[right.type="ObjectExpression"]', diff --git a/test/no-object-as-default-parameter.js b/test/no-object-as-default-parameter.js index 564de27640..bb8451006f 100644 --- a/test/no-object-as-default-parameter.js +++ b/test/no-object-as-default-parameter.js @@ -34,7 +34,10 @@ ruleTester.run('no-object-as-default-parameter', rule, { 'const abc = (foo = \'bar\') => {};', 'const abc = (foo = 123, bar = \'foo\') => {};', 'const abc = (foo = {}) => {};', - 'const abc = ({a = true, b = \'foo\'}) => {};' + 'const abc = ({a = true, b = \'foo\'}) => {};', + 'const {abc = {foo: 1}} = bar;', + 'const {abc = {null: \'baz\'}} = bar;', + 'const {abc = {foo: undefined}} = undefined;' ], invalid: [ { From f23d3cdba236a77d1e7073e1932e10375426f5f8 Mon Sep 17 00:00:00 2001 From: medusalix Date: Sun, 28 Jun 2020 16:44:19 +0200 Subject: [PATCH 08/13] Simplify selector --- rules/no-object-as-default-parameter.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/rules/no-object-as-default-parameter.js b/rules/no-object-as-default-parameter.js index 22653efd14..5173034962 100644 --- a/rules/no-object-as-default-parameter.js +++ b/rules/no-object-as-default-parameter.js @@ -4,9 +4,7 @@ const getDocumentationUrl = require('./utils/get-documentation-url'); const MESSAGE_ID = 'noObjectAsDefaultParameter'; const objectParameterSelector = [ - ':matches(FunctionDeclaration, ArrowFunctionExpression)', - '>', - 'AssignmentPattern', + ':function > AssignmentPattern.params', '[left.type="Identifier"]', '[right.type="ObjectExpression"]', '[right.properties.length>0]' From 64624e7654538618979f6630ecbaa312ee81af68 Mon Sep 17 00:00:00 2001 From: medusalix Date: Sun, 28 Jun 2020 17:04:04 +0200 Subject: [PATCH 09/13] Add additional tests --- test/no-object-as-default-parameter.js | 51 +++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/test/no-object-as-default-parameter.js b/test/no-object-as-default-parameter.js index bb8451006f..8e1060e1a3 100644 --- a/test/no-object-as-default-parameter.js +++ b/test/no-object-as-default-parameter.js @@ -1,5 +1,6 @@ import test from 'ava'; import avaRuleTester from 'eslint-ava-rule-tester'; +import {outdent} from 'outdent'; import rule from '../rules/no-object-as-default-parameter'; const ruleTester = avaRuleTester(test, { @@ -35,9 +36,11 @@ ruleTester.run('no-object-as-default-parameter', rule, { 'const abc = (foo = 123, bar = \'foo\') => {};', 'const abc = (foo = {}) => {};', 'const abc = ({a = true, b = \'foo\'}) => {};', - 'const {abc = {foo: 1}} = bar;', + 'const abc = function(foo = 123) {}', + 'const {abc = {foo: 123}} = bar;', 'const {abc = {null: \'baz\'}} = bar;', - 'const {abc = {foo: undefined}} = undefined;' + 'const {abc = {foo: undefined}} = undefined;', + 'const abc = ([{foo = false, bar = 123}]) => {};' ], invalid: [ { @@ -67,6 +70,50 @@ ruleTester.run('no-object-as-default-parameter', rule, { { code: 'const abc = (foo = {a: false, b: 1, c: "test", d: null}) => {};', errors: [error] + }, + { + code: 'const abc = function(foo = {a: 123}) {}', + errors: [error] + }, + { + code: outdent` + class A { + abc(foo = {a: 123}) {} + } + `, + errors: [error] + }, + { + code: outdent` + class A { + constructor(foo = {a: 123}) {} + } + `, + errors: [error] + }, + { + code: outdent` + class A { + set abc(foo = {a: 123}) {} + } + `, + errors: [error] + }, + { + code: outdent` + const A = class { + abc(foo = {a: 123}) {} + } + `, + errors: [error] + }, + { + code: outdent` + object = { + abc(foo = {a: 123}) {} + }; + `, + errors: [error] } ] }); From 9871a6bd232f51ec2946ed4a967b759c811fb6b8 Mon Sep 17 00:00:00 2001 From: fisker Date: Mon, 29 Jun 2020 09:21:58 +0800 Subject: [PATCH 10/13] More tests --- test/no-object-as-default-parameter.js | 73 ++++++++++++++++++++++---- 1 file changed, 62 insertions(+), 11 deletions(-) diff --git a/test/no-object-as-default-parameter.js b/test/no-object-as-default-parameter.js index 8e1060e1a3..1e4ab0c478 100644 --- a/test/no-object-as-default-parameter.js +++ b/test/no-object-as-default-parameter.js @@ -4,8 +4,8 @@ import {outdent} from 'outdent'; import rule from '../rules/no-object-as-default-parameter'; const ruleTester = avaRuleTester(test, { - env: { - es6: true + parserOptions: { + ecmaVersion: 2020 } }); @@ -23,40 +23,59 @@ ruleTester.run('no-object-as-default-parameter', rule, { 'function abc(foo = undefined) {}', 'function abc(foo = 123) {}', 'function abc(foo = true) {}', - 'function abc(foo = \'bar\') {}', - 'function abc(foo = 123, bar = \'foo\') {}', + 'function abc(foo = "bar") {}', + 'function abc(foo = 123, bar = "foo") {}', 'function abc(foo = {}) {}', 'function abc({foo = 123} = {}) {}', + '(function abc() {})(foo = {a: 123})', 'const abc = foo => {};', 'const abc = (foo = null) => {};', 'const abc = (foo = undefined) => {};', 'const abc = (foo = 123) => {};', 'const abc = (foo = true) => {};', - 'const abc = (foo = \'bar\') => {};', - 'const abc = (foo = 123, bar = \'foo\') => {};', + 'const abc = (foo = "bar") => {};', + 'const abc = (foo = 123, bar = "foo") => {};', 'const abc = (foo = {}) => {};', - 'const abc = ({a = true, b = \'foo\'}) => {};', + 'const abc = ({a = true, b = "foo"}) => {};', 'const abc = function(foo = 123) {}', 'const {abc = {foo: 123}} = bar;', - 'const {abc = {null: \'baz\'}} = bar;', + 'const {abc = {null: "baz"}} = bar;', 'const {abc = {foo: undefined}} = undefined;', - 'const abc = ([{foo = false, bar = 123}]) => {};' + 'const abc = ([{foo = false, bar = 123}]) => {};', + 'const foo = ({bar = {a:1}}) => {};', + 'const foo = ([bar = {a:1}]) => {};', + 'const foo = ({bar: baz = {a:1}}) => {};', + 'const adc = () => (foo = {bar: 1});', + outdent` + class A { + [foo = {a: 123}]() {} + } + `, + outdent` + class A extends (foo = {a: 123}) { + a() {} + } + ` ], invalid: [ { code: 'function abc(foo = {a: 123}) {}', errors: [error] }, + { + code: 'async function * abc(foo = {a: 123}) {}', + errors: [error] + }, { code: 'function abc(foo = {a: false}) {}', errors: [error] }, { - code: 'function abc(foo = {a: \'bar\'}) {}', + code: 'function abc(foo = {a: "bar"}) {}', errors: [error] }, { - code: 'function abc(foo = {a: \'bar\', b: {c: true}}) {}', + code: 'function abc(foo = {a: "bar", b: {c: true}}) {}', errors: [error] }, { @@ -99,6 +118,38 @@ ruleTester.run('no-object-as-default-parameter', rule, { `, errors: [error] }, + { + code: outdent` + class A { + static abc(foo = {a: 123}) {} + } + `, + errors: [error] + }, + { + code: outdent` + class A { + * abc(foo = {a: 123}) {} + } + `, + errors: [error] + }, + { + code: outdent` + class A { + static async * abc(foo = {a: 123}) {} + } + `, + errors: [error] + }, + { + code: outdent` + class A { + [foo = {a: 123}](foo = {a: 123}) {} + } + `, + errors: [error] + }, { code: outdent` const A = class { From bc2d7736f44de0874f149826bd8b0254b2642f3c Mon Sep 17 00:00:00 2001 From: fisker Date: Mon, 29 Jun 2020 09:26:39 +0800 Subject: [PATCH 11/13] Message test --- test/no-object-as-default-parameter.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/no-object-as-default-parameter.js b/test/no-object-as-default-parameter.js index 1e4ab0c478..23751b8c7e 100644 --- a/test/no-object-as-default-parameter.js +++ b/test/no-object-as-default-parameter.js @@ -165,6 +165,13 @@ ruleTester.run('no-object-as-default-parameter', rule, { }; `, errors: [error] + }, + // Actual message + { + code: 'function abc(foo = {a: 123}) {}', + errors: [{ + message: 'Do not use an object literal as default for parameter `foo`.' + }] } ] }); From 538cfeee0fb02ac44ffd265c5b3ad2793e82ba52 Mon Sep 17 00:00:00 2001 From: medusalix Date: Mon, 29 Jun 2020 22:18:31 +0200 Subject: [PATCH 12/13] Format tests --- test/no-object-as-default-parameter.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/no-object-as-default-parameter.js b/test/no-object-as-default-parameter.js index 23751b8c7e..7f86354a17 100644 --- a/test/no-object-as-default-parameter.js +++ b/test/no-object-as-default-parameter.js @@ -42,10 +42,10 @@ ruleTester.run('no-object-as-default-parameter', rule, { 'const {abc = {null: "baz"}} = bar;', 'const {abc = {foo: undefined}} = undefined;', 'const abc = ([{foo = false, bar = 123}]) => {};', - 'const foo = ({bar = {a:1}}) => {};', - 'const foo = ([bar = {a:1}]) => {};', - 'const foo = ({bar: baz = {a:1}}) => {};', - 'const adc = () => (foo = {bar: 1});', + 'const abc = ({foo = {a: 123}}) => {};', + 'const abc = ([foo = {a: 123}]) => {};', + 'const abc = ({foo: bar = {a: 123}}) => {};', + 'const abc = () => (foo = {a: 123});', outdent` class A { [foo = {a: 123}]() {} From c6e325aa3d2193b94ce878b03d55dc2726850099 Mon Sep 17 00:00:00 2001 From: medusalix Date: Mon, 29 Jun 2020 22:18:59 +0200 Subject: [PATCH 13/13] Report `node.left` instead of `node` --- rules/no-object-as-default-parameter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/no-object-as-default-parameter.js b/rules/no-object-as-default-parameter.js index 5173034962..d0a90e6ebc 100644 --- a/rules/no-object-as-default-parameter.js +++ b/rules/no-object-as-default-parameter.js @@ -14,7 +14,7 @@ const create = context => { return { [objectParameterSelector]: node => { context.report({ - node, + node: node.left, messageId: MESSAGE_ID, data: {parameter: node.left.name} });