-
-
Notifications
You must be signed in to change notification settings - Fork 353
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add
no-useless-fallback-in-spread
rule (#1481)
- Loading branch information
Showing
7 changed files
with
566 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
# Forbid useless fallback when spreading in object literals | ||
|
||
Spreading [falsy values](https://developer.mozilla.org/en-US/docs/Glossary/Falsy) in object literals won't add any unexpected properties, so it's unnecessary to add an empty object as fallback. | ||
|
||
This rule is fixable. | ||
|
||
## Fail | ||
|
||
```js | ||
const object = {...(foo || {})}; | ||
``` | ||
|
||
```js | ||
const object = {...(foo ?? {})}; | ||
``` | ||
## Pass | ||
```js | ||
const object = {...foo}; | ||
``` | ||
```js | ||
const object = {...(foo && {})}; | ||
``` | ||
```js | ||
const array = [...(foo || [])]; | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
'use strict'; | ||
const {matches} = require('./selectors/index.js'); | ||
const { | ||
isParenthesized, | ||
getParenthesizedRange, | ||
getParentheses, | ||
} = require('./utils/parentheses.js'); | ||
const shouldAddParenthesesToSpreadElementArgument = require('./utils/should-add-parentheses-to-spread-element-argument.js'); | ||
|
||
const MESSAGE_ID = 'no-useless-fallback-in-spread'; | ||
const messages = { | ||
[MESSAGE_ID]: 'The empty object is useless.', | ||
}; | ||
|
||
const selector = [ | ||
'ObjectExpression', | ||
' > ', | ||
'SpreadElement.properties', | ||
' > ', | ||
'LogicalExpression.argument', | ||
matches([ | ||
'[operator="||"]', | ||
'[operator="??"]', | ||
]), | ||
' > ', | ||
'ObjectExpression[properties.length=0].right', | ||
].join(''); | ||
|
||
/** @param {import('eslint').Rule.RuleContext} context */ | ||
const create = context => ({ | ||
[selector](emptyObject) { | ||
return { | ||
node: emptyObject, | ||
messageId: MESSAGE_ID, | ||
/** @param {import('eslint').Rule.RuleFixer} fixer */ | ||
* fix(fixer) { | ||
const sourceCode = context.getSourceCode(); | ||
const logicalExpression = emptyObject.parent; | ||
const {left} = logicalExpression; | ||
const isLeftObjectParenthesized = isParenthesized(left, sourceCode); | ||
const [, start] = isLeftObjectParenthesized | ||
? getParenthesizedRange(left, sourceCode) | ||
: left.range; | ||
const [, end] = logicalExpression.range; | ||
|
||
yield fixer.removeRange([start, end]); | ||
|
||
if ( | ||
isLeftObjectParenthesized | ||
|| !shouldAddParenthesesToSpreadElementArgument(left) | ||
) { | ||
const parentheses = getParentheses(logicalExpression, sourceCode); | ||
|
||
for (const token of parentheses) { | ||
yield fixer.remove(token); | ||
} | ||
} | ||
}, | ||
}; | ||
}, | ||
}); | ||
|
||
const schema = []; | ||
|
||
module.exports = { | ||
create, | ||
meta: { | ||
type: 'suggestion', | ||
docs: { | ||
description: 'Forbid useless fallback when spreading in object literals.', | ||
}, | ||
fixable: 'code', | ||
schema, | ||
messages, | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import {getTester} from './utils/test.mjs'; | ||
|
||
const {test} = getTester(import.meta); | ||
|
||
test.snapshot({ | ||
valid: [ | ||
'const array = [...(foo || [])]', | ||
'const array = [...(foo || {})]', | ||
'const array = [...(foo && {})]', | ||
'const object = {...(foo && {})}', | ||
'const object = {...({} || foo)}', | ||
'const object = {...({} && foo)}', | ||
'const object = {...({} ?? foo)}', | ||
'const object = {...(foo ? foo : {})}', | ||
'const object = {...foo}', | ||
'const object = {...(foo ?? ({} || {}))}', | ||
'const {...foo} = object', | ||
'function foo({...bar}){}', | ||
'const object = {...(foo || {}).toString()}', | ||
'const object = {...fn(foo || {})}', | ||
'const object = call({}, ...(foo || {}))', | ||
'const object = {...(foo || {not: "empty"})}', | ||
'const object = {...(foo || {...{}})}', | ||
], | ||
invalid: [ | ||
'const object = {...(foo || {})}', | ||
'const object = {...(foo ?? {})}', | ||
'const object = {...(foo ?? (( {} )))}', | ||
'const object = {...((( foo )) ?? (( {} )))}', | ||
'const object = {...(( (( foo )) ?? (( {} )) ))}', | ||
'async ()=> ({...((await foo) || {})})', | ||
'const object = {...(0 || {})}', | ||
'const object = {...((-0) || {})}', | ||
'const object = {...(.0 || {})}', | ||
'const object = {...(0n || {})}', | ||
'const object = {...(false || {})}', | ||
'const object = {...(null || {})}', | ||
'const object = {...(undefined || {})}', | ||
'const object = {...((a && b) || {})}', | ||
'const object = {...(NaN || {})}', | ||
'const object = {...("" || {})}', | ||
'const object = {...([] || {})}', | ||
'const object = {...({} || {})}', | ||
'const object = {...(foo || {}),}', | ||
'const object = {...((foo ?? {}) || {})}', | ||
'const object = {...((foo && {}) || {})}', | ||
'const object = {...(foo && {} || {})}', | ||
'const object = {...({...(foo || {})})}', | ||
'function foo(a = {...(bar || {})}){}', | ||
// The only case we'll break, but we should not care about it. | ||
'const object = {...(document.all || {})}', | ||
], | ||
}); |
Oops, something went wrong.