@ethlete/eslint-plugin 1.0.0-next.30 → 1.0.0-next.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/package.json +1 -1
- package/src/rules/no-silent-catch-error.js +29 -9
package/CHANGELOG.md
CHANGED
package/package.json
CHANGED
|
@@ -2,13 +2,16 @@
|
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* Disallow an RxJS catchError whose handler ignores the error and returns of(...), EMPTY or NEVER
|
|
5
|
+
* Disallow an RxJS catchError whose handler ignores the error and returns of(...), EMPTY or NEVER,
|
|
6
|
+
* and, with the `tryCatch` option, a try/catch whose catch ignores the error and returns a fallback value.
|
|
6
7
|
*
|
|
7
8
|
* BAD:
|
|
8
9
|
* source$.pipe(catchError(() => of(null)));
|
|
10
|
+
* try { return read(); } catch { return []; }
|
|
9
11
|
*
|
|
10
12
|
* GOOD:
|
|
11
13
|
* source$.pipe(catchError((error) => { this.error.set(error); return of(null); }));
|
|
14
|
+
* try { return read(); } catch (error) { report(error); return []; }
|
|
12
15
|
*/
|
|
13
16
|
|
|
14
17
|
const SWALLOWING_CONSTANTS = new Set(['EMPTY', 'NEVER']);
|
|
@@ -24,6 +27,10 @@ const isSwallowingValue = (node) => {
|
|
|
24
27
|
const collectReturnedValues = (fn) => {
|
|
25
28
|
if (fn.body.type !== 'BlockStatement') return [fn.body];
|
|
26
29
|
|
|
30
|
+
return collectReturnsIn(fn.body);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const collectReturnsIn = (block) => {
|
|
27
34
|
const values = [];
|
|
28
35
|
|
|
29
36
|
const visit = (node) => {
|
|
@@ -52,7 +59,7 @@ const collectReturnedValues = (fn) => {
|
|
|
52
59
|
}
|
|
53
60
|
};
|
|
54
61
|
|
|
55
|
-
|
|
62
|
+
block.body.forEach(visit);
|
|
56
63
|
|
|
57
64
|
return values;
|
|
58
65
|
};
|
|
@@ -62,37 +69,50 @@ const noSilentCatchError = {
|
|
|
62
69
|
meta: {
|
|
63
70
|
type: 'suggestion',
|
|
64
71
|
docs: {
|
|
65
|
-
description:
|
|
72
|
+
description:
|
|
73
|
+
'Disallow a catchError handler that ignores the error and swallows it with of(), EMPTY or NEVER, and with the `tryCatch` option a catch clause that ignores the error and returns a fallback.',
|
|
66
74
|
recommended: false,
|
|
67
75
|
},
|
|
68
76
|
messages: {
|
|
69
77
|
silentCatchError:
|
|
70
78
|
'The error disappears silently. Use it (log it, store it in a signal, rethrow it) or disable this rule with a reason.',
|
|
71
79
|
},
|
|
72
|
-
schema: [
|
|
80
|
+
schema: [
|
|
81
|
+
{
|
|
82
|
+
type: 'object',
|
|
83
|
+
properties: { tryCatch: { type: 'boolean' } },
|
|
84
|
+
additionalProperties: false,
|
|
85
|
+
},
|
|
86
|
+
],
|
|
73
87
|
},
|
|
74
88
|
create(context) {
|
|
75
89
|
const sourceCode = context.sourceCode;
|
|
90
|
+
const checkTryCatch = context.options[0]?.tryCatch === true;
|
|
76
91
|
|
|
77
|
-
const ignoresError = (
|
|
78
|
-
const [param] = fn.params;
|
|
79
|
-
|
|
92
|
+
const ignoresError = (scopeNode, param) => {
|
|
80
93
|
if (!param) return true;
|
|
81
94
|
if (param.type !== 'Identifier') return false;
|
|
82
95
|
|
|
83
|
-
const variable = sourceCode.getDeclaredVariables(
|
|
96
|
+
const variable = sourceCode.getDeclaredVariables(scopeNode).find((v) => v.name === param.name);
|
|
84
97
|
|
|
85
98
|
return !variable || variable.references.length === 0;
|
|
86
99
|
};
|
|
87
100
|
|
|
88
101
|
return {
|
|
102
|
+
CatchClause(node) {
|
|
103
|
+
if (!checkTryCatch) return;
|
|
104
|
+
if (!ignoresError(node, node.param)) return;
|
|
105
|
+
if (collectReturnsIn(node.body).length === 0) return;
|
|
106
|
+
|
|
107
|
+
context.report({ node, messageId: 'silentCatchError' });
|
|
108
|
+
},
|
|
89
109
|
CallExpression(node) {
|
|
90
110
|
if (node.callee.type !== 'Identifier' || node.callee.name !== 'catchError') return;
|
|
91
111
|
|
|
92
112
|
const [handler] = node.arguments;
|
|
93
113
|
|
|
94
114
|
if (!handler || (handler.type !== 'ArrowFunctionExpression' && handler.type !== 'FunctionExpression')) return;
|
|
95
|
-
if (!ignoresError(handler)) return;
|
|
115
|
+
if (!ignoresError(handler, handler.params[0])) return;
|
|
96
116
|
|
|
97
117
|
if (collectReturnedValues(handler).some(isSwallowingValue)) {
|
|
98
118
|
context.report({ node: handler, messageId: 'silentCatchError' });
|