Skip to content

Commit 35bf866

Browse files
fix(no-floating-observables): handle array expressions
1 parent 6f75e1a commit 35bf866

File tree

2 files changed

+52
-11
lines changed

2 files changed

+52
-11
lines changed

src/rules/no-floating-observables.ts

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { TSESTree as es } from '@typescript-eslint/utils';
2-
import { getTypeServices, isCallExpression, isChainExpression } from '../etc';
2+
import { getTypeServices, isCallExpression, isChainExpression, isUnaryExpression } from '../etc';
33
import { ruleCreator } from '../utils';
44

55
const defaultOptions: readonly {
@@ -50,21 +50,25 @@ export const noFloatingObservablesRule = ruleCreator({
5050
}
5151
}
5252

53+
function checkVoid(node: es.UnaryExpression) {
54+
if (ignoreVoid) return;
55+
if (node.operator !== 'void') return;
56+
57+
let expression = node.argument;
58+
if (isChainExpression(expression)) {
59+
expression = expression.expression;
60+
}
61+
62+
if (!isCallExpression(expression)) return;
63+
checkNode(expression);
64+
}
65+
5366
return {
5467
'ExpressionStatement > CallExpression': (node: es.CallExpression) => {
5568
checkNode(node);
5669
},
5770
'ExpressionStatement > UnaryExpression': (node: es.UnaryExpression) => {
58-
if (ignoreVoid) return;
59-
if (node.operator !== 'void') return;
60-
61-
let expression = node.argument;
62-
if (isChainExpression(expression)) {
63-
expression = expression.expression;
64-
}
65-
66-
if (!isCallExpression(expression)) return;
67-
checkNode(expression);
71+
checkVoid(node);
6872
},
6973
'ExpressionStatement > ChainExpression': (node: es.ChainExpression) => {
7074
if (!isCallExpression(node.expression)) return;
@@ -78,6 +82,16 @@ export const noFloatingObservablesRule = ruleCreator({
7882
}
7983
});
8084
},
85+
'ExpressionStatement > ArrayExpression': (node: es.ArrayExpression) => {
86+
node.elements.forEach(expression => {
87+
if (!expression) return;
88+
if (isCallExpression(expression)) {
89+
checkNode(expression);
90+
} else if (isUnaryExpression(expression)) {
91+
checkVoid(expression);
92+
}
93+
});
94+
},
8195
};
8296
},
8397
});

tests/rules/no-floating-observables.test.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ ruleTester({ types: true }).run('no-floating-observables', noFloatingObservables
1818
1919
functionSource().subscribe();
2020
const a = functionSource();
21+
const b = [functionSource()];
22+
[void functionSource()];
2123
sink(functionSource());
2224
void functionSource();
2325
`,
@@ -32,9 +34,21 @@ ruleTester({ types: true }).run('no-floating-observables', noFloatingObservables
3234
3335
functionSource().subscribe();
3436
const a = arrowSource();
37+
const b = [arrowSource()];
38+
[void arrowSource()];
3539
sink(arrowSource());
3640
void functionSource();
3741
`,
42+
stripIndent`
43+
// unrelated
44+
function foo() {}
45+
46+
[1, 2, 3, 'foo'];
47+
const a = [1];
48+
foo();
49+
[foo()];
50+
void foo();
51+
`,
3852
],
3953
invalid: [
4054
fromFixture(
@@ -72,6 +86,15 @@ ruleTester({ types: true }).run('no-floating-observables', noFloatingObservables
7286
~~~~~~~~~~~~~~~ [forbidden]
7387
`,
7488
),
89+
fromFixture(
90+
stripIndent`
91+
// array
92+
import { of } from "rxjs";
93+
94+
[of(42)];
95+
~~~~~~ [forbidden]
96+
`,
97+
),
7598
fromFixture(
7699
stripIndent`
77100
// ignoreVoid false
@@ -85,6 +108,10 @@ ruleTester({ types: true }).run('no-floating-observables', noFloatingObservables
85108
~~~~~~~~~~~~~~~~ [forbiddenNoVoid]
86109
void functionSource?.();
87110
~~~~~~~~~~~~~~~~~~ [forbiddenNoVoid]
111+
[void functionSource()];
112+
~~~~~~~~~~~~~~~~ [forbiddenNoVoid]
113+
[void functionSource?.()];
114+
~~~~~~~~~~~~~~~~~~ [forbiddenNoVoid]
88115
`,
89116
{
90117
options: [{ ignoreVoid: false }],

0 commit comments

Comments
 (0)