Skip to content

Commit a0b2f4f

Browse files
authored
prefer-optional-catch-binding: Support checking destructured errors (sindresorhus#1229)
1 parent d84143f commit a0b2f4f

File tree

5 files changed

+102
-19
lines changed

5 files changed

+102
-19
lines changed

docs/rules/prefer-optional-catch-binding.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@ This rule is fixable.
77
## Fail
88

99
```js
10-
try {} catch (usedError) {}
10+
try {} catch (notUsedError) {}
11+
```
12+
13+
```js
14+
try {} catch ({message}) {}
1115
```
1216

1317
## Pass

rules/prefer-optional-catch-binding.js

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,35 @@
11
'use strict';
22
const getDocumentationUrl = require('./utils/get-documentation-url');
3-
const {findVariable, isOpeningParenToken, isClosingParenToken} = require('eslint-utils');
3+
const {isOpeningParenToken, isClosingParenToken} = require('eslint-utils');
44
const assertToken = require('./utils/assert-token');
55

6-
const ERROR_MESSAGE_ID = 'error';
6+
const MESSAGE_ID_WITH_NAME = 'with-name';
7+
const MESSAGE_ID_WITHOUT_NAME = 'without-name';
78
const messages = {
8-
[ERROR_MESSAGE_ID]: 'Remove unused catch binding `{{name}}`.'
9+
[MESSAGE_ID_WITH_NAME]: 'Remove unused catch binding `{{name}}`.',
10+
[MESSAGE_ID_WITHOUT_NAME]: 'Remove unused catch binding.'
911
};
1012

1113
const selector = [
1214
'CatchClause',
1315
'>',
14-
'Identifier.param'
16+
'.param'
1517
].join('');
1618

1719
const create = context => {
18-
const sourceCode = context.getSourceCode();
19-
2020
return {
2121
[selector]: node => {
22-
const scope = context.getScope();
23-
const variable = findVariable(scope, node);
22+
const variables = context.getDeclaredVariables(node.parent);
2423

25-
if (variable.references.length > 0) {
24+
if (variables.some(variable => variable.references.length > 0)) {
2625
return;
2726
}
2827

29-
const {name, parent} = node;
28+
const {type, name, parent} = node;
3029

3130
context.report({
3231
node,
33-
messageId: ERROR_MESSAGE_ID,
32+
messageId: type === 'Identifier' ? MESSAGE_ID_WITH_NAME : MESSAGE_ID_WITHOUT_NAME,
3433
data: {name},
3534
* fix(fixer) {
3635
const tokenBefore = context.getTokenBefore(node);
@@ -53,7 +52,7 @@ const create = context => {
5352

5453
const [, endOfClosingParenthesis] = tokenAfter.range;
5554
const [startOfCatchClauseBody] = parent.body.range;
56-
const text = sourceCode.text.slice(endOfClosingParenthesis, startOfCatchClauseBody);
55+
const text = context.getSourceCode().text.slice(endOfClosingParenthesis, startOfCatchClauseBody);
5756
const leadingSpacesLength = text.length - text.trimStart().length;
5857
if (leadingSpacesLength !== 0) {
5958
yield fixer.removeRange([endOfClosingParenthesis, endOfClosingParenthesis + leadingSpacesLength]);

test/prefer-optional-catch-binding.mjs

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@ import {getTester} from './utils/test.mjs';
33

44
const {test} = getTester(import.meta);
55

6-
const ERROR_MESSAGE_ID = 'error';
7-
const generateError = name => ({messageId: ERROR_MESSAGE_ID, data: {name}});
6+
const generateError = name => ({messageId: 'with-name', data: {name}});
87

98
test({
109
valid: [
@@ -27,10 +26,7 @@ test({
2726
}
2827
}
2928
}
30-
`,
31-
// We are not checking destructuring
32-
'try {} catch({message}) {}',
33-
'try {} catch({nonExistsProperty = thisWillExecute()}) {}'
29+
`
3430
],
3531
invalid: [
3632
{
@@ -173,3 +169,18 @@ test({
173169
}
174170
]
175171
});
172+
173+
test.snapshot({
174+
valid: [
175+
'try {} catch ({message}) {alert(message)}',
176+
'try {} catch ({cause: {message}}) {alert(message)}',
177+
// Not sure about this case
178+
'try {} catch({nonExistsProperty = thisWillExecute()}) {}'
179+
],
180+
invalid: [
181+
'try {} catch ({}) {}',
182+
'try {} catch ({message}) {}',
183+
'try {} catch ({message: notUsedMessage}) {}',
184+
'try {} catch ({cause: {message}}) {}'
185+
]
186+
});
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# Snapshot report for `test/prefer-optional-catch-binding.mjs`
2+
3+
The actual snapshot is saved in `prefer-optional-catch-binding.mjs.snap`.
4+
5+
Generated by [AVA](https://avajs.dev).
6+
7+
## Invalid #1
8+
1 | try {} catch ({}) {}
9+
10+
> Output
11+
12+
`␊
13+
1 | try {} catch {}␊
14+
`
15+
16+
> Error 1/1
17+
18+
`␊
19+
> 1 | try {} catch ({}) {}␊
20+
| ^^ Remove unused catch binding.␊
21+
`
22+
23+
## Invalid #2
24+
1 | try {} catch ({message}) {}
25+
26+
> Output
27+
28+
`␊
29+
1 | try {} catch {}␊
30+
`
31+
32+
> Error 1/1
33+
34+
`␊
35+
> 1 | try {} catch ({message}) {}␊
36+
| ^^^^^^^^^ Remove unused catch binding.␊
37+
`
38+
39+
## Invalid #3
40+
1 | try {} catch ({message: notUsedMessage}) {}
41+
42+
> Output
43+
44+
`␊
45+
1 | try {} catch {}␊
46+
`
47+
48+
> Error 1/1
49+
50+
`␊
51+
> 1 | try {} catch ({message: notUsedMessage}) {}␊
52+
| ^^^^^^^^^^^^^^^^^^^^^^^^^ Remove unused catch binding.␊
53+
`
54+
55+
## Invalid #4
56+
1 | try {} catch ({cause: {message}}) {}
57+
58+
> Output
59+
60+
`␊
61+
1 | try {} catch {}␊
62+
`
63+
64+
> Error 1/1
65+
66+
`␊
67+
> 1 | try {} catch ({cause: {message}}) {}␊
68+
| ^^^^^^^^^^^^^^^^^^ Remove unused catch binding.␊
69+
`
Binary file not shown.

0 commit comments

Comments
 (0)