Skip to content

Commit

Permalink
ESLint Plugin: no-unused-vars-before-return: Exempt destructuring onl…
Browse files Browse the repository at this point in the history
…y if to multiple properties (#16799)

* ESLint Plugin: Destructure references immediatley prior to use

* ESLint Plugin: Exempt object destructuring only if destructuring to more than one property
  • Loading branch information
aduth authored and gziolo committed Aug 29, 2019
1 parent b5e3950 commit 1254c27
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 3 deletions.
6 changes: 6 additions & 0 deletions packages/eslint-plugin/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## Master

### Breaking Changes

- The [`@wordpress/no-unused-vars-before-return` rule](https://github.com/WordPress/gutenberg/blob/master/packages/eslint-plugin/docs/rules/no-unused-vars-before-return.md) has been improved to exempt object destructuring only if destructuring to more than one property.

## 2.4.0 (2019-08-05)

### New Features
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,17 @@ function example( number ) {
}
const foo = doSomeCostlyOperation();
return number + foo;
}`,
},
{
code: `
function example() {
const { foo, bar } = doSomeCostlyOperation();
if ( number > 10 ) {
return number + bar + 1;
}
return number + foo;
}`,
},
Expand All @@ -49,6 +60,18 @@ function example( number ) {
return number + 1;
}
return number + foo;
}`,
errors: [ { message: 'Variables should not be assigned until just prior its first reference. An early return statement may leave this variable unused.' } ],
},
{
code: `
function example() {
const { foo } = doSomeCostlyOperation();
if ( number > 10 ) {
return number + 1;
}
return number + foo;
}`,
errors: [ { message: 'Variables should not be assigned until just prior its first reference. An early return statement may leave this variable unused.' } ],
Expand Down
17 changes: 16 additions & 1 deletion packages/eslint-plugin/rules/no-unused-vars-before-return.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,21 @@ module.exports = {
const options = context.options[ 0 ] || {};
const { excludePattern } = options;

/**
* Given an Espree VariableDeclarator node, returns true if the node
* can be exempted from consideration as unused, or false otherwise. A
* node can be exempt if it destructures to multiple variables, since
* those other variables may be used prior to the return statement. A
* future enhancement could validate that they are in-fact referenced.
*
* @param {Object} node Node to test.
*
* @return {boolean} Whether declarator is emempt from consideration.
*/
function isExemptObjectDestructureDeclarator( node ) {
return node.id.type === 'ObjectPattern' && node.id.properties.length > 1;
}

return {
ReturnStatement( node ) {
let functionScope = context.getScope();
Expand All @@ -37,7 +52,7 @@ module.exports = {
// Target function calls as "expensive".
def.node.init.type === 'CallExpression' &&
// Allow unused if part of an object destructuring.
def.node.id.type !== 'ObjectPattern' &&
! isExemptObjectDestructureDeclarator( def.node ) &&
// Only target assignments preceding `return`.
def.node.end < node.end
);
Expand Down
3 changes: 1 addition & 2 deletions packages/eslint-plugin/rules/react-no-unsafe-timeout.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@ module.exports = {
create( context ) {
return {
'CallExpression[callee.name="setTimeout"]'( node ) {
const { references } = context.getScope();

// If the result of a `setTimeout` call is assigned to a
// variable, assume the timer ID is handled by a cancellation.
const hasAssignment = (
Expand Down Expand Up @@ -74,6 +72,7 @@ module.exports = {
// Consider whether `setTimeout` is a reference to the global
// by checking references to see if `setTimeout` resolves to a
// variable in scope.
const { references } = context.getScope();
const hasResolvedReference = references.some( ( reference ) => (
reference.identifier.name === 'setTimeout' &&
!! reference.resolved &&
Expand Down

0 comments on commit 1254c27

Please sign in to comment.