Skip to content

Commit 3a064cc

Browse files
committed
Making requested changes
1 parent 7448e49 commit 3a064cc

File tree

7 files changed

+54
-44
lines changed

7 files changed

+54
-44
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ The package includes the following rules.
108108
| [no-subject-unsubscribe](docs/rules/no-subject-unsubscribe.md) | Disallow calling the `unsubscribe` method of subjects. | ✅ 🔒 | | | 💭 | |
109109
| [no-subject-value](docs/rules/no-subject-value.md) | Disallow accessing the `value` property of a `BehaviorSubject` instance. | | | | 💭 | |
110110
| [no-subscribe-handlers](docs/rules/no-subscribe-handlers.md) | Disallow passing handlers to `subscribe`. | | | | 💭 | |
111+
| [no-subscribe-in-pipe](docs/rules/no-subscribe-in-pipe.md) | Disallow calling of `subscribe` within any RxJS operator inside a `pipe`. | ✅ 🔒 | | | 💭 | |
111112
| [no-tap](docs/rules/no-tap.md) | Disallow the `tap` operator. | | | | ||
112113
| [no-topromise](docs/rules/no-topromise.md) | Disallow use of the `toPromise` method. | ✅ 🔒 | | 💡 | 💭 | |
113114
| [no-unbound-methods](docs/rules/no-unbound-methods.md) | Disallow passing unbound methods. | ✅ 🔒 | | | 💭 | |

docs/rules/no-subscribe-in-pipe.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
# Avoid `subscribe` calls inside `pipe` operators (`no-subscribe-in-pipe`)
1+
# Disallow calling of `subscribe` within any RxJS operator inside a `pipe` (`rxjs-x/no-subscribe-in-pipe`)
2+
3+
💼 This rule is enabled in the following configs: ✅ `recommended`, 🔒 `strict`.
4+
5+
💭 This rule requires [type information](https://typescript-eslint.io/linting/typed-linting).
6+
7+
<!-- end auto-generated rule header -->
28

39
This rule effects failures if `subscribe` is called within any operator inside a `pipe` operation.
410

@@ -29,7 +35,3 @@ of(42, 54).pipe(
2935
map(value => value * 2)
3036
).subscribe(result => console.log(result));
3137
```
32-
33-
## Options
34-
35-
This rule has no options.

src/configs/recommended.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export const createRecommendedConfig = (
2020
'rxjs-x/no-redundant-notify': 'error',
2121
'rxjs-x/no-sharereplay': 'error',
2222
'rxjs-x/no-subject-unsubscribe': 'error',
23+
'rxjs-x/no-subscribe-in-pipe': 'error',
2324
'rxjs-x/no-topromise': 'error',
2425
'rxjs-x/no-unbound-methods': 'error',
2526
'rxjs-x/no-unsafe-subject-next': 'error',

src/configs/strict.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ export const createStrictConfig = (
2929
'rxjs-x/no-sharereplay': 'error',
3030
'rxjs-x/no-subclass': 'error',
3131
'rxjs-x/no-subject-unsubscribe': 'error',
32+
'rxjs-x/no-subscribe-in-pipe': 'error',
3233
'rxjs-x/no-topromise': 'error',
3334
'rxjs-x/no-unbound-methods': 'error',
3435
'rxjs-x/no-unsafe-subject-next': 'error',

src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import { noSubclassRule } from './rules/no-subclass';
3535
import { noSubjectUnsubscribeRule } from './rules/no-subject-unsubscribe';
3636
import { noSubjectValueRule } from './rules/no-subject-value';
3737
import { noSubscribeHandlersRule } from './rules/no-subscribe-handlers';
38+
import { noSubscribeInPipeRule } from './rules/no-subscribe-in-pipe';
3839
import { noTapRule } from './rules/no-tap';
3940
import { noTopromiseRule } from './rules/no-topromise';
4041
import { noUnboundMethodsRule } from './rules/no-unbound-methods';
@@ -83,6 +84,7 @@ const plugin = {
8384
'no-subject-unsubscribe': noSubjectUnsubscribeRule,
8485
'no-subject-value': noSubjectValueRule,
8586
'no-subscribe-handlers': noSubscribeHandlersRule,
87+
'no-subscribe-in-pipe': noSubscribeInPipeRule,
8688
'no-tap': noTapRule,
8789
'no-topromise': noTopromiseRule,
8890
'no-unbound-methods': noUnboundMethodsRule,

src/rules/no-subscribe-in-pipe.ts

Lines changed: 22 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,63 @@
1-
/**
2-
* @license Use of this source code is governed by an MIT-style license that
3-
* can be found in the LICENSE file at https://github.com/cartant/eslint-plugin-rxjs
4-
*/
1+
import { AST_NODE_TYPES, TSESTree as es } from '@typescript-eslint/utils';
2+
import { getTypeServices } from '../etc';
3+
import { ruleCreator } from '../utils';
54

6-
import { TSESTree as es } from "@typescript-eslint/experimental-utils";
7-
import { getParent, getTypeServices } from "eslint-etc";
8-
import { ruleCreator } from "../utils";
9-
10-
const rule = ruleCreator({
5+
export const noSubscribeInPipeRule = ruleCreator({
116
defaultOptions: [],
127
meta: {
138
docs: {
149
description:
15-
"Forbids the calling of `subscribe` within any RxJS operator inside a `pipe`.",
16-
recommended: "error",
10+
'Disallow calling of `subscribe` within any RxJS operator inside a `pipe`.',
11+
recommended: 'recommended',
12+
requiresTypeChecking: true,
1713
},
1814
fixable: undefined,
1915
hasSuggestions: false,
2016
messages: {
21-
forbidden: "Subscribe calls within pipe operators are forbidden.",
17+
forbidden: 'Subscribe calls within pipe operators are forbidden.',
2218
},
2319
schema: [],
24-
type: "problem",
20+
type: 'problem',
2521
},
26-
name: "no-subscribe-in-pipe",
22+
name: 'no-subscribe-in-pipe',
2723
create: (context) => {
2824
const { couldBeObservable, couldBeType } = getTypeServices(context);
2925

3026
function isWithinPipe(node: es.Node): boolean {
31-
let parent = getParent(node);
27+
let parent = node.parent;
28+
3229
while (parent) {
3330
if (
34-
parent.type === "CallExpression" &&
35-
parent.callee.type === "MemberExpression" &&
36-
parent.callee.property.type === "Identifier" &&
37-
parent.callee.property.name === "pipe"
31+
parent.type === AST_NODE_TYPES.CallExpression
32+
&& parent.callee.type === AST_NODE_TYPES.MemberExpression
33+
&& parent.callee.property.type === AST_NODE_TYPES.Identifier
34+
&& parent.callee.property.name === 'pipe'
3835
) {
3936
return true;
4037
}
41-
parent = getParent(parent);
38+
parent = node.parent;
4239
}
4340
return false;
4441
}
4542

4643
return {
47-
"CallExpression > MemberExpression[property.name='subscribe']": (
48-
node: es.MemberExpression
44+
'CallExpression > MemberExpression[property.name=\'subscribe\']': (
45+
node: es.MemberExpression,
4946
) => {
5047
if (
51-
!couldBeObservable(node.object) &&
52-
!couldBeType(node.object, "Subscribable")
48+
!couldBeObservable(node.object)
49+
&& !couldBeType(node.object, 'Subscribable')
5350
) {
5451
return;
5552
}
5653

5754
if (isWithinPipe(node)) {
5855
context.report({
59-
messageId: "forbidden",
56+
messageId: 'forbidden',
6057
node: node.property,
6158
});
6259
}
6360
},
6461
};
6562
},
6663
});
67-
68-
export = rule;

tests/rules/no-subscribe-in-pipe.ts renamed to tests/rules/no-subscribe-in-pipe.test.ts

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import { stripIndent } from "common-tags";
2-
import { fromFixture } from "eslint-etc";
3-
import rule = require("../../source/rules/no-subscribe-in-pipe");
4-
import { ruleTester } from "../utils";
1+
import { stripIndent } from 'common-tags';
2+
import { noSubscribeInPipeRule } from '../../src/rules/no-subscribe-in-pipe';
3+
import { fromFixture } from '../etc';
4+
import { ruleTester } from '../rule-tester';
55

6-
ruleTester({ types: true }).run("no-subscribe-in-pipe", rule, {
6+
ruleTester({ types: true }).run('no-subscribe-in-pipe', noSubscribeInPipeRule, {
77
valid: [
88
stripIndent`
99
// subscribe outside of pipe
@@ -88,6 +88,14 @@ ruleTester({ types: true }).run("no-subscribe-in-pipe", rule, {
8888
})
8989
).subscribe();
9090
`,
91+
stripIndent`
92+
// subscribe inside of an Observable constructor
93+
import { Observable, of } from "rxjs";
94+
95+
new Observable<number>(subscriber => {
96+
of(42).subscribe(subscriber);
97+
}).subscribe();
98+
`,
9199
],
92100
invalid: [
93101
fromFixture(
@@ -102,7 +110,7 @@ ruleTester({ types: true }).run("no-subscribe-in-pipe", rule, {
102110
return x * 2;
103111
})
104112
).subscribe();
105-
`
113+
`,
106114
),
107115
fromFixture(
108116
stripIndent`
@@ -118,7 +126,7 @@ ruleTester({ types: true }).run("no-subscribe-in-pipe", rule, {
118126
})
119127
))
120128
).subscribe();
121-
`
129+
`,
122130
),
123131
fromFixture(
124132
stripIndent`
@@ -131,7 +139,7 @@ ruleTester({ types: true }).run("no-subscribe-in-pipe", rule, {
131139
~~~~~~~~~ [forbidden]
132140
})
133141
).subscribe();
134-
`
142+
`,
135143
),
136144
fromFixture(
137145
stripIndent`
@@ -145,7 +153,7 @@ ruleTester({ types: true }).run("no-subscribe-in-pipe", rule, {
145153
return of(x * 2);
146154
})
147155
).subscribe();
148-
`
156+
`,
149157
),
150158
fromFixture(
151159
stripIndent`
@@ -161,7 +169,7 @@ ruleTester({ types: true }).run("no-subscribe-in-pipe", rule, {
161169
})
162170
))
163171
).subscribe();
164-
`
172+
`,
165173
),
166174
fromFixture(
167175
stripIndent`
@@ -181,7 +189,7 @@ ruleTester({ types: true }).run("no-subscribe-in-pipe", rule, {
181189
return x * 2;
182190
})
183191
).subscribe();
184-
`
192+
`,
185193
),
186194
fromFixture(
187195
stripIndent`
@@ -192,7 +200,7 @@ ruleTester({ types: true }).run("no-subscribe-in-pipe", rule, {
192200
map(x => x > 50 ? x : of(x).subscribe(console.log))
193201
~~~~~~~~~ [forbidden]
194202
).subscribe();
195-
`
203+
`,
196204
),
197205
],
198206
});

0 commit comments

Comments
 (0)