eslint-plugin-rxjs-x 0.2.3 → 0.3.0
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/README.md +44 -43
- package/dist/index.d.mts +5 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +244 -122
- package/dist/index.mjs +276 -154
- package/docs/rules/ban-operators.md +2 -0
- package/docs/rules/macro.md +4 -0
- package/docs/rules/no-exposed-subjects.md +2 -2
- package/docs/rules/no-ignored-default-value.md +29 -0
- package/docs/rules/no-nested-subscribe.md +2 -2
- package/docs/rules/throw-error.md +14 -25
- package/package.json +9 -9
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// package.json
|
|
2
2
|
var name = "eslint-plugin-rxjs-x";
|
|
3
|
-
var version = "0.
|
|
3
|
+
var version = "0.3.0";
|
|
4
4
|
|
|
5
5
|
// src/configs/recommended.ts
|
|
6
6
|
var createRecommendedConfig = (plugin2) => ({
|
|
@@ -117,74 +117,7 @@ var banObservablesRule = ruleCreator({
|
|
|
117
117
|
});
|
|
118
118
|
|
|
119
119
|
// src/rules/ban-operators.ts
|
|
120
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES2 } from "@typescript-eslint/utils";
|
|
121
120
|
import { stripIndent as stripIndent2 } from "common-tags";
|
|
122
|
-
var defaultOptions2 = [];
|
|
123
|
-
var banOperatorsRule = ruleCreator({
|
|
124
|
-
defaultOptions: defaultOptions2,
|
|
125
|
-
meta: {
|
|
126
|
-
docs: {
|
|
127
|
-
description: "Disallow banned operators."
|
|
128
|
-
},
|
|
129
|
-
messages: {
|
|
130
|
-
forbidden: "RxJS operator is banned: {{name}}{{explanation}}."
|
|
131
|
-
},
|
|
132
|
-
schema: [
|
|
133
|
-
{
|
|
134
|
-
type: "object",
|
|
135
|
-
description: stripIndent2`
|
|
136
|
-
An object containing keys that are names of operators
|
|
137
|
-
and values that are either booleans or strings containing the explanation for the ban.`
|
|
138
|
-
}
|
|
139
|
-
],
|
|
140
|
-
type: "problem"
|
|
141
|
-
},
|
|
142
|
-
name: "ban-operators",
|
|
143
|
-
create: (context) => {
|
|
144
|
-
const bans = [];
|
|
145
|
-
const [config] = context.options;
|
|
146
|
-
if (!config) {
|
|
147
|
-
return {};
|
|
148
|
-
}
|
|
149
|
-
Object.entries(config).forEach(([key, value]) => {
|
|
150
|
-
if (value !== false) {
|
|
151
|
-
bans.push({
|
|
152
|
-
explanation: typeof value === "string" ? value : "",
|
|
153
|
-
regExp: new RegExp(`^${key}$`)
|
|
154
|
-
});
|
|
155
|
-
}
|
|
156
|
-
});
|
|
157
|
-
function getFailure(name2) {
|
|
158
|
-
for (let b = 0, length = bans.length; b < length; ++b) {
|
|
159
|
-
const ban = bans[b];
|
|
160
|
-
if (ban.regExp.test(name2)) {
|
|
161
|
-
const explanation = ban.explanation ? `: ${ban.explanation}` : "";
|
|
162
|
-
return {
|
|
163
|
-
messageId: "forbidden",
|
|
164
|
-
data: { name: name2, explanation }
|
|
165
|
-
};
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
return void 0;
|
|
169
|
-
}
|
|
170
|
-
return {
|
|
171
|
-
[String.raw`ImportDeclaration[source.value=/^rxjs\u002foperators$/] > ImportSpecifier`]: (node) => {
|
|
172
|
-
const identifier = node.imported;
|
|
173
|
-
const name2 = identifier.type === AST_NODE_TYPES2.Identifier ? identifier.name : identifier.value;
|
|
174
|
-
const failure = getFailure(name2);
|
|
175
|
-
if (failure) {
|
|
176
|
-
context.report({
|
|
177
|
-
...failure,
|
|
178
|
-
node: identifier
|
|
179
|
-
});
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
};
|
|
183
|
-
}
|
|
184
|
-
});
|
|
185
|
-
|
|
186
|
-
// src/rules/finnish.ts
|
|
187
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES5, ESLintUtils as ESLintUtils3 } from "@typescript-eslint/utils";
|
|
188
121
|
|
|
189
122
|
// src/etc/could-be-function.ts
|
|
190
123
|
import ts2 from "typescript";
|
|
@@ -301,55 +234,54 @@ function getLoc(node) {
|
|
|
301
234
|
|
|
302
235
|
// src/etc/get-type-services.ts
|
|
303
236
|
import { ESLintUtils as ESLintUtils2 } from "@typescript-eslint/utils";
|
|
304
|
-
import * as tsutils2 from "ts-api-utils";
|
|
305
237
|
import ts4 from "typescript";
|
|
306
238
|
|
|
307
239
|
// src/etc/is.ts
|
|
308
|
-
import { AST_NODE_TYPES as
|
|
240
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES2 } from "@typescript-eslint/utils";
|
|
309
241
|
function hasTypeAnnotation(node) {
|
|
310
242
|
return "typeAnnotation" in node && !!node.typeAnnotation;
|
|
311
243
|
}
|
|
312
244
|
function isArrayExpression(node) {
|
|
313
|
-
return node.type ===
|
|
245
|
+
return node.type === AST_NODE_TYPES2.ArrayExpression;
|
|
314
246
|
}
|
|
315
247
|
function isArrayPattern(node) {
|
|
316
|
-
return node.type ===
|
|
248
|
+
return node.type === AST_NODE_TYPES2.ArrayPattern;
|
|
317
249
|
}
|
|
318
250
|
function isArrowFunctionExpression(node) {
|
|
319
|
-
return node.type ===
|
|
251
|
+
return node.type === AST_NODE_TYPES2.ArrowFunctionExpression;
|
|
320
252
|
}
|
|
321
253
|
function isBlockStatement(node) {
|
|
322
|
-
return node.type ===
|
|
254
|
+
return node.type === AST_NODE_TYPES2.BlockStatement;
|
|
323
255
|
}
|
|
324
256
|
function isCallExpression(node) {
|
|
325
|
-
return node.type ===
|
|
257
|
+
return node.type === AST_NODE_TYPES2.CallExpression;
|
|
326
258
|
}
|
|
327
259
|
function isFunctionDeclaration(node) {
|
|
328
|
-
return node.type ===
|
|
260
|
+
return node.type === AST_NODE_TYPES2.FunctionDeclaration;
|
|
329
261
|
}
|
|
330
262
|
function isFunctionExpression(node) {
|
|
331
|
-
return node.type ===
|
|
263
|
+
return node.type === AST_NODE_TYPES2.FunctionExpression;
|
|
332
264
|
}
|
|
333
265
|
function isIdentifier(node) {
|
|
334
|
-
return node.type ===
|
|
266
|
+
return node.type === AST_NODE_TYPES2.Identifier;
|
|
335
267
|
}
|
|
336
268
|
function isLiteral(node) {
|
|
337
|
-
return node.type ===
|
|
269
|
+
return node.type === AST_NODE_TYPES2.Literal;
|
|
338
270
|
}
|
|
339
271
|
function isMemberExpression(node) {
|
|
340
|
-
return node.type ===
|
|
272
|
+
return node.type === AST_NODE_TYPES2.MemberExpression;
|
|
341
273
|
}
|
|
342
274
|
function isObjectExpression(node) {
|
|
343
|
-
return node.type ===
|
|
275
|
+
return node.type === AST_NODE_TYPES2.ObjectExpression;
|
|
344
276
|
}
|
|
345
277
|
function isObjectPattern(node) {
|
|
346
|
-
return node.type ===
|
|
278
|
+
return node.type === AST_NODE_TYPES2.ObjectPattern;
|
|
347
279
|
}
|
|
348
280
|
function isProgram(node) {
|
|
349
|
-
return node.type ===
|
|
281
|
+
return node.type === AST_NODE_TYPES2.Program;
|
|
350
282
|
}
|
|
351
283
|
function isProperty(node) {
|
|
352
|
-
return node.type ===
|
|
284
|
+
return node.type === AST_NODE_TYPES2.Property;
|
|
353
285
|
}
|
|
354
286
|
|
|
355
287
|
// src/etc/get-type-services.ts
|
|
@@ -358,7 +290,7 @@ function getTypeServices(context) {
|
|
|
358
290
|
const { esTreeNodeToTSNodeMap, program, getTypeAtLocation } = services;
|
|
359
291
|
const typeChecker = program.getTypeChecker();
|
|
360
292
|
const couldBeType2 = (node, name2, qualified) => {
|
|
361
|
-
const type =
|
|
293
|
+
const type = getTypeAtLocation(node);
|
|
362
294
|
return couldBeType(
|
|
363
295
|
type,
|
|
364
296
|
name2,
|
|
@@ -382,17 +314,13 @@ function getTypeServices(context) {
|
|
|
382
314
|
)
|
|
383
315
|
);
|
|
384
316
|
};
|
|
385
|
-
const getType = (node) => {
|
|
386
|
-
return getTypeAtLocation(node);
|
|
387
|
-
};
|
|
388
317
|
return {
|
|
389
318
|
couldBeBehaviorSubject: (node) => couldBeType2(node, "BehaviorSubject"),
|
|
390
|
-
couldBeError: (node) => couldBeType2(node, "Error"),
|
|
391
319
|
couldBeFunction: (node) => {
|
|
392
320
|
if (isArrowFunctionExpression(node) || isFunctionDeclaration(node)) {
|
|
393
321
|
return true;
|
|
394
322
|
}
|
|
395
|
-
return couldBeFunction(
|
|
323
|
+
return couldBeFunction(getTypeAtLocation(node));
|
|
396
324
|
},
|
|
397
325
|
couldBeMonoTypeOperatorFunction: (node) => couldBeType2(node, "MonoTypeOperatorFunction"),
|
|
398
326
|
couldBeObservable: (node) => couldBeType2(node, "Observable"),
|
|
@@ -400,29 +328,88 @@ function getTypeServices(context) {
|
|
|
400
328
|
couldBeSubscription: (node) => couldBeType2(node, "Subscription"),
|
|
401
329
|
couldBeType: couldBeType2,
|
|
402
330
|
couldReturnObservable: (node) => couldReturnType(node, "Observable"),
|
|
403
|
-
couldReturnType
|
|
404
|
-
getType,
|
|
405
|
-
isAny: (node) => tsutils2.isIntrinsicAnyType(getType(node)),
|
|
406
|
-
isReferenceType: (node) => tsutils2.isTypeReference(getType(node)),
|
|
407
|
-
isUnknown: (node) => tsutils2.isIntrinsicUnknownType(getType(node)),
|
|
408
|
-
typeChecker
|
|
331
|
+
couldReturnType
|
|
409
332
|
};
|
|
410
333
|
}
|
|
411
334
|
|
|
412
335
|
// src/etc/is-import.ts
|
|
413
336
|
import { DefinitionType } from "@typescript-eslint/scope-manager";
|
|
414
|
-
import { AST_NODE_TYPES as
|
|
337
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES3 } from "@typescript-eslint/utils";
|
|
415
338
|
function isImport(scope, name2, source) {
|
|
416
339
|
const variable = scope.variables.find((variable2) => variable2.name === name2);
|
|
417
340
|
if (variable) {
|
|
418
341
|
return variable.defs.some(
|
|
419
|
-
(def) => def.type === DefinitionType.ImportBinding && def.parent.type ===
|
|
342
|
+
(def) => def.type === DefinitionType.ImportBinding && def.parent.type === AST_NODE_TYPES3.ImportDeclaration && (typeof source === "string" ? def.parent.source.value === source : source.test(def.parent.source.value))
|
|
420
343
|
);
|
|
421
344
|
}
|
|
422
345
|
return scope.upper ? isImport(scope.upper, name2, source) : false;
|
|
423
346
|
}
|
|
424
347
|
|
|
348
|
+
// src/rules/ban-operators.ts
|
|
349
|
+
var defaultOptions2 = [];
|
|
350
|
+
var banOperatorsRule = ruleCreator({
|
|
351
|
+
defaultOptions: defaultOptions2,
|
|
352
|
+
meta: {
|
|
353
|
+
docs: {
|
|
354
|
+
description: "Disallow banned operators.",
|
|
355
|
+
requiresTypeChecking: true
|
|
356
|
+
},
|
|
357
|
+
messages: {
|
|
358
|
+
forbidden: "RxJS operator is banned: {{name}}{{explanation}}."
|
|
359
|
+
},
|
|
360
|
+
schema: [
|
|
361
|
+
{
|
|
362
|
+
type: "object",
|
|
363
|
+
description: stripIndent2`
|
|
364
|
+
An object containing keys that are names of operators
|
|
365
|
+
and values that are either booleans or strings containing the explanation for the ban.`
|
|
366
|
+
}
|
|
367
|
+
],
|
|
368
|
+
type: "problem"
|
|
369
|
+
},
|
|
370
|
+
name: "ban-operators",
|
|
371
|
+
create: (context) => {
|
|
372
|
+
const { couldBeType: couldBeType2 } = getTypeServices(context);
|
|
373
|
+
const bans = [];
|
|
374
|
+
const [config] = context.options;
|
|
375
|
+
if (!config) {
|
|
376
|
+
return {};
|
|
377
|
+
}
|
|
378
|
+
Object.entries(config).forEach(([key, value]) => {
|
|
379
|
+
if (value !== false) {
|
|
380
|
+
bans.push({
|
|
381
|
+
name: key,
|
|
382
|
+
explanation: typeof value === "string" ? value : ""
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
});
|
|
386
|
+
function checkNode(node) {
|
|
387
|
+
for (const ban of bans) {
|
|
388
|
+
if (couldBeType2(node, ban.name, { name: /[/\\]rxjs[/\\]/ })) {
|
|
389
|
+
const explanation = ban.explanation ? `: ${ban.explanation}` : "";
|
|
390
|
+
context.report({
|
|
391
|
+
messageId: "forbidden",
|
|
392
|
+
data: { name: ban.name, explanation },
|
|
393
|
+
node
|
|
394
|
+
});
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
return {
|
|
400
|
+
"CallExpression[callee.property.name='pipe'] > CallExpression[callee.name]": (node) => {
|
|
401
|
+
checkNode(node.callee);
|
|
402
|
+
},
|
|
403
|
+
"CallExpression[callee.property.name='pipe'] > CallExpression[callee.type=\"MemberExpression\"]": (node) => {
|
|
404
|
+
const callee = node.callee;
|
|
405
|
+
checkNode(callee.property);
|
|
406
|
+
}
|
|
407
|
+
};
|
|
408
|
+
}
|
|
409
|
+
});
|
|
410
|
+
|
|
425
411
|
// src/rules/finnish.ts
|
|
412
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES4, ESLintUtils as ESLintUtils3 } from "@typescript-eslint/utils";
|
|
426
413
|
var defaultOptions3 = [];
|
|
427
414
|
var finnishRule = ruleCreator({
|
|
428
415
|
defaultOptions: defaultOptions3,
|
|
@@ -550,7 +537,7 @@ var finnishRule = ruleCreator({
|
|
|
550
537
|
if (!found) {
|
|
551
538
|
return;
|
|
552
539
|
}
|
|
553
|
-
if (!validate.variables && found.type ===
|
|
540
|
+
if (!validate.variables && found.type === AST_NODE_TYPES4.VariableDeclarator) {
|
|
554
541
|
return;
|
|
555
542
|
}
|
|
556
543
|
if (!validate.parameters) {
|
|
@@ -629,7 +616,7 @@ var finnishRule = ruleCreator({
|
|
|
629
616
|
if (!found) {
|
|
630
617
|
return;
|
|
631
618
|
}
|
|
632
|
-
if (!validate.variables && found.type ===
|
|
619
|
+
if (!validate.variables && found.type === AST_NODE_TYPES4.VariableDeclarator) {
|
|
633
620
|
return;
|
|
634
621
|
}
|
|
635
622
|
if (!validate.parameters) {
|
|
@@ -723,6 +710,7 @@ var justRule = ruleCreator({
|
|
|
723
710
|
var macroRule = ruleCreator({
|
|
724
711
|
defaultOptions: [],
|
|
725
712
|
meta: {
|
|
713
|
+
deprecated: true,
|
|
726
714
|
docs: {
|
|
727
715
|
description: "Require the use of the RxJS Tools Babel macro."
|
|
728
716
|
},
|
|
@@ -919,6 +907,7 @@ var noCreateRule = ruleCreator({
|
|
|
919
907
|
});
|
|
920
908
|
|
|
921
909
|
// src/rules/no-cyclic-action.ts
|
|
910
|
+
import { ESLintUtils as ESLintUtils4 } from "@typescript-eslint/utils";
|
|
922
911
|
import { stripIndent as stripIndent3 } from "common-tags";
|
|
923
912
|
import ts5 from "typescript";
|
|
924
913
|
|
|
@@ -926,7 +915,7 @@ import ts5 from "typescript";
|
|
|
926
915
|
var defaultObservable = String.raw`[Aa]ction(s|s\$|\$)$`;
|
|
927
916
|
|
|
928
917
|
// src/rules/no-cyclic-action.ts
|
|
929
|
-
function
|
|
918
|
+
function isTypeReference2(type) {
|
|
930
919
|
return Boolean(type.target);
|
|
931
920
|
}
|
|
932
921
|
var defaultOptions4 = [];
|
|
@@ -958,7 +947,8 @@ var noCyclicActionRule = ruleCreator({
|
|
|
958
947
|
const [config = {}] = context.options;
|
|
959
948
|
const { observable = defaultObservable } = config;
|
|
960
949
|
const observableRegExp = new RegExp(observable);
|
|
961
|
-
const {
|
|
950
|
+
const { getTypeAtLocation, program } = ESLintUtils4.getParserServices(context);
|
|
951
|
+
const typeChecker = program.getTypeChecker();
|
|
962
952
|
function checkNode(pipeCallExpression) {
|
|
963
953
|
const operatorCallExpression = pipeCallExpression.arguments.find(
|
|
964
954
|
(arg) => isCallExpression(arg) && isIdentifier(arg.callee) && arg.callee.name === "ofType"
|
|
@@ -966,7 +956,7 @@ var noCyclicActionRule = ruleCreator({
|
|
|
966
956
|
if (!operatorCallExpression) {
|
|
967
957
|
return;
|
|
968
958
|
}
|
|
969
|
-
const operatorType =
|
|
959
|
+
const operatorType = getTypeAtLocation(operatorCallExpression);
|
|
970
960
|
const [signature] = typeChecker.getSignaturesOfType(
|
|
971
961
|
operatorType,
|
|
972
962
|
ts5.SignatureKind.Call
|
|
@@ -975,15 +965,15 @@ var noCyclicActionRule = ruleCreator({
|
|
|
975
965
|
return;
|
|
976
966
|
}
|
|
977
967
|
const operatorReturnType = typeChecker.getReturnTypeOfSignature(signature);
|
|
978
|
-
if (!
|
|
968
|
+
if (!isTypeReference2(operatorReturnType)) {
|
|
979
969
|
return;
|
|
980
970
|
}
|
|
981
971
|
const [operatorElementType] = typeChecker.getTypeArguments(operatorReturnType);
|
|
982
972
|
if (!operatorElementType) {
|
|
983
973
|
return;
|
|
984
974
|
}
|
|
985
|
-
const pipeType =
|
|
986
|
-
if (!
|
|
975
|
+
const pipeType = getTypeAtLocation(pipeCallExpression);
|
|
976
|
+
if (!isTypeReference2(pipeType)) {
|
|
987
977
|
return;
|
|
988
978
|
}
|
|
989
979
|
const [pipeElementType] = typeChecker.getTypeArguments(pipeType);
|
|
@@ -1182,7 +1172,7 @@ var noExposedSubjectsRule = ruleCreator({
|
|
|
1182
1172
|
});
|
|
1183
1173
|
|
|
1184
1174
|
// src/rules/no-finnish.ts
|
|
1185
|
-
import { ESLintUtils as
|
|
1175
|
+
import { ESLintUtils as ESLintUtils5 } from "@typescript-eslint/utils";
|
|
1186
1176
|
var noFinnishRule = ruleCreator({
|
|
1187
1177
|
defaultOptions: [],
|
|
1188
1178
|
meta: {
|
|
@@ -1198,7 +1188,7 @@ var noFinnishRule = ruleCreator({
|
|
|
1198
1188
|
},
|
|
1199
1189
|
name: "no-finnish",
|
|
1200
1190
|
create: (context) => {
|
|
1201
|
-
const { esTreeNodeToTSNodeMap } =
|
|
1191
|
+
const { esTreeNodeToTSNodeMap } = ESLintUtils5.getParserServices(context);
|
|
1202
1192
|
const { couldBeObservable, couldReturnObservable } = getTypeServices(context);
|
|
1203
1193
|
function checkNode(nameNode, typeNode) {
|
|
1204
1194
|
if (couldBeObservable(typeNode != null ? typeNode : nameNode) || couldReturnObservable(typeNode != null ? typeNode : nameNode)) {
|
|
@@ -1277,6 +1267,108 @@ var noFinnishRule = ruleCreator({
|
|
|
1277
1267
|
}
|
|
1278
1268
|
});
|
|
1279
1269
|
|
|
1270
|
+
// src/rules/no-ignored-default-value.ts
|
|
1271
|
+
import { ESLintUtils as ESLintUtils6 } from "@typescript-eslint/utils";
|
|
1272
|
+
var noIgnoredDefaultValueRule = ruleCreator({
|
|
1273
|
+
defaultOptions: [],
|
|
1274
|
+
meta: {
|
|
1275
|
+
docs: {
|
|
1276
|
+
description: "Disallow using `firstValueFrom`, `lastValueFrom`, `first`, and `last` without specifying a default value.",
|
|
1277
|
+
requiresTypeChecking: true
|
|
1278
|
+
},
|
|
1279
|
+
messages: {
|
|
1280
|
+
forbidden: "Not specifying a default value is forbidden."
|
|
1281
|
+
},
|
|
1282
|
+
schema: [],
|
|
1283
|
+
type: "problem"
|
|
1284
|
+
},
|
|
1285
|
+
name: "no-ignored-default-value",
|
|
1286
|
+
create: (context) => {
|
|
1287
|
+
const { getTypeAtLocation } = ESLintUtils6.getParserServices(context);
|
|
1288
|
+
const { couldBeObservable, couldBeType: couldBeType2 } = getTypeServices(context);
|
|
1289
|
+
function checkConfigObj(configArg) {
|
|
1290
|
+
if (!configArg.properties.some((p) => isProperty(p) && isIdentifier(p.key) && p.key.name === "defaultValue")) {
|
|
1291
|
+
context.report({
|
|
1292
|
+
messageId: "forbidden",
|
|
1293
|
+
node: configArg
|
|
1294
|
+
});
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
function checkConfigType(configArg) {
|
|
1298
|
+
const configArgType = getTypeAtLocation(configArg);
|
|
1299
|
+
if (!(configArgType == null ? void 0 : configArgType.getProperties().some((p) => p.name === "defaultValue"))) {
|
|
1300
|
+
context.report({
|
|
1301
|
+
messageId: "forbidden",
|
|
1302
|
+
node: configArg
|
|
1303
|
+
});
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1306
|
+
function checkArg(arg) {
|
|
1307
|
+
if (isIdentifier(arg)) {
|
|
1308
|
+
checkConfigType(arg);
|
|
1309
|
+
return;
|
|
1310
|
+
} else if (isMemberExpression(arg) && isIdentifier(arg.property)) {
|
|
1311
|
+
checkConfigType(arg.property);
|
|
1312
|
+
return;
|
|
1313
|
+
}
|
|
1314
|
+
if (!isObjectExpression(arg)) {
|
|
1315
|
+
return;
|
|
1316
|
+
}
|
|
1317
|
+
checkConfigObj(arg);
|
|
1318
|
+
}
|
|
1319
|
+
function checkFunctionArgs(node, args) {
|
|
1320
|
+
if (!couldBeType2(node, "firstValueFrom", { name: /[/\\]rxjs[/\\]/ }) && !couldBeType2(node, "lastValueFrom", { name: /[/\\]rxjs[/\\]/ })) {
|
|
1321
|
+
return;
|
|
1322
|
+
}
|
|
1323
|
+
if (!args || args.length <= 0) {
|
|
1324
|
+
return;
|
|
1325
|
+
}
|
|
1326
|
+
const [observableArg, configArg] = args;
|
|
1327
|
+
if (!couldBeObservable(observableArg)) {
|
|
1328
|
+
return;
|
|
1329
|
+
}
|
|
1330
|
+
if (!configArg) {
|
|
1331
|
+
context.report({
|
|
1332
|
+
messageId: "forbidden",
|
|
1333
|
+
node
|
|
1334
|
+
});
|
|
1335
|
+
return;
|
|
1336
|
+
}
|
|
1337
|
+
checkArg(configArg);
|
|
1338
|
+
}
|
|
1339
|
+
function checkOperatorArgs(node, args) {
|
|
1340
|
+
if (!couldBeType2(node, "first", { name: /[/\\]rxjs[/\\]/ }) && !couldBeType2(node, "last", { name: /[/\\]rxjs[/\\]/ })) {
|
|
1341
|
+
return;
|
|
1342
|
+
}
|
|
1343
|
+
if (!args || args.length <= 0) {
|
|
1344
|
+
context.report({
|
|
1345
|
+
messageId: "forbidden",
|
|
1346
|
+
node
|
|
1347
|
+
});
|
|
1348
|
+
return;
|
|
1349
|
+
}
|
|
1350
|
+
const [arg] = args;
|
|
1351
|
+
checkArg(arg);
|
|
1352
|
+
}
|
|
1353
|
+
return {
|
|
1354
|
+
"CallExpression[callee.name=/^(firstValueFrom|lastValueFrom)$/]": (node) => {
|
|
1355
|
+
checkFunctionArgs(node.callee, node.arguments);
|
|
1356
|
+
},
|
|
1357
|
+
"CallExpression[callee.property.name=/^(firstValueFrom|lastValueFrom)$/]": (node) => {
|
|
1358
|
+
const memberExpression = node.callee;
|
|
1359
|
+
checkFunctionArgs(memberExpression.property, node.arguments);
|
|
1360
|
+
},
|
|
1361
|
+
"CallExpression[callee.property.name='pipe'] > CallExpression[callee.name=/^(first|last)$/]": (node) => {
|
|
1362
|
+
checkOperatorArgs(node.callee, node.arguments);
|
|
1363
|
+
},
|
|
1364
|
+
"CallExpression[callee.property.name='pipe'] > CallExpression[callee.property.name=/^(first|last)$/]": (node) => {
|
|
1365
|
+
const memberExpression = node.callee;
|
|
1366
|
+
checkOperatorArgs(memberExpression.property, node.arguments);
|
|
1367
|
+
}
|
|
1368
|
+
};
|
|
1369
|
+
}
|
|
1370
|
+
});
|
|
1371
|
+
|
|
1280
1372
|
// src/rules/no-ignored-error.ts
|
|
1281
1373
|
var noIgnoredErrorRule = ruleCreator({
|
|
1282
1374
|
defaultOptions: [],
|
|
@@ -1412,7 +1504,6 @@ var noIgnoredObservableRule = ruleCreator({
|
|
|
1412
1504
|
});
|
|
1413
1505
|
|
|
1414
1506
|
// src/rules/no-ignored-replay-buffer.ts
|
|
1415
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES6 } from "@typescript-eslint/utils";
|
|
1416
1507
|
var noIgnoredReplayBufferRule = ruleCreator({
|
|
1417
1508
|
defaultOptions: [],
|
|
1418
1509
|
meta: {
|
|
@@ -1429,7 +1520,7 @@ var noIgnoredReplayBufferRule = ruleCreator({
|
|
|
1429
1520
|
name: "no-ignored-replay-buffer",
|
|
1430
1521
|
create: (context) => {
|
|
1431
1522
|
function checkShareReplayConfig(node, shareReplayConfigArg) {
|
|
1432
|
-
if (!shareReplayConfigArg.properties.some((p) => p
|
|
1523
|
+
if (!shareReplayConfigArg.properties.some((p) => isProperty(p) && isIdentifier(p.key) && p.key.name === "bufferSize")) {
|
|
1433
1524
|
context.report({
|
|
1434
1525
|
messageId: "forbidden",
|
|
1435
1526
|
node
|
|
@@ -1444,8 +1535,8 @@ var noIgnoredReplayBufferRule = ruleCreator({
|
|
|
1444
1535
|
});
|
|
1445
1536
|
}
|
|
1446
1537
|
if (node.name === "shareReplay" && (args == null ? void 0 : args.length) === 1) {
|
|
1447
|
-
const arg = args
|
|
1448
|
-
if (arg
|
|
1538
|
+
const [arg] = args;
|
|
1539
|
+
if (isObjectExpression(arg)) {
|
|
1449
1540
|
checkShareReplayConfig(node, arg);
|
|
1450
1541
|
}
|
|
1451
1542
|
}
|
|
@@ -1595,7 +1686,7 @@ var noIgnoredTakewhileValueRule = ruleCreator({
|
|
|
1595
1686
|
|
|
1596
1687
|
// src/rules/no-implicit-any-catch.ts
|
|
1597
1688
|
import {
|
|
1598
|
-
AST_NODE_TYPES as
|
|
1689
|
+
AST_NODE_TYPES as AST_NODE_TYPES5
|
|
1599
1690
|
} from "@typescript-eslint/utils";
|
|
1600
1691
|
function isParenthesised(sourceCode, node) {
|
|
1601
1692
|
const before = sourceCode.getTokenBefore(node);
|
|
@@ -1651,7 +1742,7 @@ var noImplicitAnyCatchRule = ruleCreator({
|
|
|
1651
1742
|
const {
|
|
1652
1743
|
typeAnnotation: { type }
|
|
1653
1744
|
} = typeAnnotation;
|
|
1654
|
-
if (type ===
|
|
1745
|
+
if (type === AST_NODE_TYPES5.TSAnyKeyword) {
|
|
1655
1746
|
let fix2 = function(fixer) {
|
|
1656
1747
|
return fixer.replaceText(typeAnnotation, ": unknown");
|
|
1657
1748
|
};
|
|
@@ -1670,7 +1761,7 @@ var noImplicitAnyCatchRule = ruleCreator({
|
|
|
1670
1761
|
}
|
|
1671
1762
|
]
|
|
1672
1763
|
});
|
|
1673
|
-
} else if (type !==
|
|
1764
|
+
} else if (type !== AST_NODE_TYPES5.TSUnknownKeyword) {
|
|
1674
1765
|
let fix2 = function(fixer) {
|
|
1675
1766
|
return fixer.replaceText(typeAnnotation, ": unknown");
|
|
1676
1767
|
};
|
|
@@ -1965,7 +2056,7 @@ function isExpressionObserver(expressionStatement, couldBeType2) {
|
|
|
1965
2056
|
}
|
|
1966
2057
|
|
|
1967
2058
|
// src/rules/no-sharereplay.ts
|
|
1968
|
-
import { AST_NODE_TYPES as
|
|
2059
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES6 } from "@typescript-eslint/utils";
|
|
1969
2060
|
var defaultOptions7 = [];
|
|
1970
2061
|
var noSharereplayRule = ruleCreator({
|
|
1971
2062
|
defaultOptions: defaultOptions7,
|
|
@@ -1996,7 +2087,7 @@ var noSharereplayRule = ruleCreator({
|
|
|
1996
2087
|
"CallExpression[callee.name='shareReplay']": (node) => {
|
|
1997
2088
|
let report = true;
|
|
1998
2089
|
if (allowConfig) {
|
|
1999
|
-
report = node.arguments.length !== 1 || node.arguments[0].type !==
|
|
2090
|
+
report = node.arguments.length !== 1 || node.arguments[0].type !== AST_NODE_TYPES6.ObjectExpression;
|
|
2000
2091
|
}
|
|
2001
2092
|
if (report) {
|
|
2002
2093
|
context.report({
|
|
@@ -2226,6 +2317,7 @@ var noTopromiseRule = ruleCreator({
|
|
|
2226
2317
|
});
|
|
2227
2318
|
|
|
2228
2319
|
// src/rules/no-unbound-methods.ts
|
|
2320
|
+
import { ESLintUtils as ESLintUtils7 } from "@typescript-eslint/utils";
|
|
2229
2321
|
var noUnboundMethodsRule = ruleCreator({
|
|
2230
2322
|
defaultOptions: [],
|
|
2231
2323
|
meta: {
|
|
@@ -2242,11 +2334,12 @@ var noUnboundMethodsRule = ruleCreator({
|
|
|
2242
2334
|
},
|
|
2243
2335
|
name: "no-unbound-methods",
|
|
2244
2336
|
create: (context) => {
|
|
2245
|
-
const {
|
|
2337
|
+
const { getTypeAtLocation } = ESLintUtils7.getParserServices(context);
|
|
2338
|
+
const { couldBeObservable, couldBeSubscription } = getTypeServices(context);
|
|
2246
2339
|
const nodeMap = /* @__PURE__ */ new WeakMap();
|
|
2247
2340
|
function mapArguments(node) {
|
|
2248
2341
|
node.arguments.filter(isMemberExpression).forEach((arg) => {
|
|
2249
|
-
const argType =
|
|
2342
|
+
const argType = getTypeAtLocation(arg);
|
|
2250
2343
|
if (argType.getCallSignatures().length > 0) {
|
|
2251
2344
|
nodeMap.set(arg);
|
|
2252
2345
|
}
|
|
@@ -2419,7 +2512,8 @@ var noUnsafeFirstRule = ruleCreator({
|
|
|
2419
2512
|
});
|
|
2420
2513
|
|
|
2421
2514
|
// src/rules/no-unsafe-subject-next.ts
|
|
2422
|
-
import
|
|
2515
|
+
import { ESLintUtils as ESLintUtils8 } from "@typescript-eslint/utils";
|
|
2516
|
+
import * as tsutils2 from "ts-api-utils";
|
|
2423
2517
|
import ts6 from "typescript";
|
|
2424
2518
|
var noUnsafeSubjectNext = ruleCreator({
|
|
2425
2519
|
defaultOptions: [],
|
|
@@ -2437,24 +2531,25 @@ var noUnsafeSubjectNext = ruleCreator({
|
|
|
2437
2531
|
},
|
|
2438
2532
|
name: "no-unsafe-subject-next",
|
|
2439
2533
|
create: (context) => {
|
|
2440
|
-
const {
|
|
2534
|
+
const { getTypeAtLocation, program } = ESLintUtils8.getParserServices(context);
|
|
2535
|
+
const typeChecker = program.getTypeChecker();
|
|
2441
2536
|
return {
|
|
2442
2537
|
[`CallExpression[callee.property.name='next']`]: (node) => {
|
|
2443
2538
|
if (node.arguments.length === 0 && isMemberExpression(node.callee)) {
|
|
2444
|
-
const type =
|
|
2445
|
-
if (
|
|
2539
|
+
const type = getTypeAtLocation(node.callee.object);
|
|
2540
|
+
if (tsutils2.isTypeReference(type) && couldBeType(type, "Subject")) {
|
|
2446
2541
|
const [typeArg] = typeChecker.getTypeArguments(type);
|
|
2447
|
-
if (
|
|
2542
|
+
if (tsutils2.isTypeFlagSet(typeArg, ts6.TypeFlags.Any)) {
|
|
2448
2543
|
return;
|
|
2449
2544
|
}
|
|
2450
|
-
if (
|
|
2545
|
+
if (tsutils2.isTypeFlagSet(typeArg, ts6.TypeFlags.Unknown)) {
|
|
2451
2546
|
return;
|
|
2452
2547
|
}
|
|
2453
|
-
if (
|
|
2548
|
+
if (tsutils2.isTypeFlagSet(typeArg, ts6.TypeFlags.Void)) {
|
|
2454
2549
|
return;
|
|
2455
2550
|
}
|
|
2456
|
-
if (
|
|
2457
|
-
(t) =>
|
|
2551
|
+
if (tsutils2.isUnionType(typeArg) && typeArg.types.some(
|
|
2552
|
+
(t) => tsutils2.isTypeFlagSet(t, ts6.TypeFlags.Void)
|
|
2458
2553
|
)) {
|
|
2459
2554
|
return;
|
|
2460
2555
|
}
|
|
@@ -2800,7 +2895,7 @@ function isValidArgText(argText) {
|
|
|
2800
2895
|
}
|
|
2801
2896
|
|
|
2802
2897
|
// src/rules/suffix-subjects.ts
|
|
2803
|
-
import { AST_NODE_TYPES as
|
|
2898
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES7, ESLintUtils as ESLintUtils9 } from "@typescript-eslint/utils";
|
|
2804
2899
|
var defaultOptions13 = [];
|
|
2805
2900
|
var suffixSubjectsRule = ruleCreator({
|
|
2806
2901
|
defaultOptions: defaultOptions13,
|
|
@@ -2828,7 +2923,7 @@ var suffixSubjectsRule = ruleCreator({
|
|
|
2828
2923
|
},
|
|
2829
2924
|
name: "suffix-subjects",
|
|
2830
2925
|
create: (context) => {
|
|
2831
|
-
const { esTreeNodeToTSNodeMap } =
|
|
2926
|
+
const { esTreeNodeToTSNodeMap } = ESLintUtils9.getParserServices(context);
|
|
2832
2927
|
const { couldBeType: couldBeType2 } = getTypeServices(context);
|
|
2833
2928
|
const [config = {}] = context.options;
|
|
2834
2929
|
const validate = {
|
|
@@ -2884,7 +2979,7 @@ var suffixSubjectsRule = ruleCreator({
|
|
|
2884
2979
|
if (!found) {
|
|
2885
2980
|
return;
|
|
2886
2981
|
}
|
|
2887
|
-
if (!validate.variables && found.type ===
|
|
2982
|
+
if (!validate.variables && found.type === AST_NODE_TYPES7.VariableDeclarator) {
|
|
2888
2983
|
return;
|
|
2889
2984
|
}
|
|
2890
2985
|
if (!validate.parameters) {
|
|
@@ -2951,7 +3046,7 @@ var suffixSubjectsRule = ruleCreator({
|
|
|
2951
3046
|
if (!found) {
|
|
2952
3047
|
return;
|
|
2953
3048
|
}
|
|
2954
|
-
if (!validate.variables && found.type ===
|
|
3049
|
+
if (!validate.variables && found.type === AST_NODE_TYPES7.VariableDeclarator) {
|
|
2955
3050
|
return;
|
|
2956
3051
|
}
|
|
2957
3052
|
if (!validate.parameters) {
|
|
@@ -2998,49 +3093,75 @@ var suffixSubjectsRule = ruleCreator({
|
|
|
2998
3093
|
});
|
|
2999
3094
|
|
|
3000
3095
|
// src/rules/throw-error.ts
|
|
3001
|
-
import { ESLintUtils as
|
|
3002
|
-
import * as
|
|
3096
|
+
import { ESLintUtils as ESLintUtils10 } from "@typescript-eslint/utils";
|
|
3097
|
+
import * as tsutils3 from "ts-api-utils";
|
|
3098
|
+
var defaultOptions14 = [];
|
|
3003
3099
|
var throwErrorRule = ruleCreator({
|
|
3004
|
-
defaultOptions:
|
|
3100
|
+
defaultOptions: defaultOptions14,
|
|
3005
3101
|
meta: {
|
|
3006
3102
|
docs: {
|
|
3007
|
-
description: "Enforce passing only `Error` values to
|
|
3103
|
+
description: "Enforce passing only `Error` values to `throwError`.",
|
|
3008
3104
|
requiresTypeChecking: true
|
|
3009
3105
|
},
|
|
3010
3106
|
messages: {
|
|
3011
|
-
forbidden: "Passing non-Error values
|
|
3107
|
+
forbidden: "Passing non-Error values is forbidden."
|
|
3012
3108
|
},
|
|
3013
|
-
schema: [
|
|
3109
|
+
schema: [
|
|
3110
|
+
{
|
|
3111
|
+
properties: {
|
|
3112
|
+
allowThrowingAny: { type: "boolean", default: true, description: "Whether to always allow throwing values typed as `any`." },
|
|
3113
|
+
allowThrowingUnknown: { type: "boolean", default: true, description: "Whether to always allow throwing values typed as `unknown`." }
|
|
3114
|
+
},
|
|
3115
|
+
type: "object"
|
|
3116
|
+
}
|
|
3117
|
+
],
|
|
3014
3118
|
type: "problem"
|
|
3015
3119
|
},
|
|
3016
3120
|
name: "throw-error",
|
|
3017
3121
|
create: (context) => {
|
|
3018
|
-
const { esTreeNodeToTSNodeMap, program } =
|
|
3019
|
-
const { couldBeObservable
|
|
3020
|
-
|
|
3021
|
-
|
|
3122
|
+
const { esTreeNodeToTSNodeMap, program, getTypeAtLocation } = ESLintUtils10.getParserServices(context);
|
|
3123
|
+
const { couldBeObservable } = getTypeServices(context);
|
|
3124
|
+
const [config = {}] = context.options;
|
|
3125
|
+
const { allowThrowingAny = true, allowThrowingUnknown = true } = config;
|
|
3126
|
+
function checkThrowArgument(node) {
|
|
3127
|
+
var _a;
|
|
3128
|
+
let type = getTypeAtLocation(node);
|
|
3129
|
+
let reportNode = node;
|
|
3022
3130
|
if (couldBeFunction(type)) {
|
|
3131
|
+
reportNode = (_a = node.body) != null ? _a : node;
|
|
3023
3132
|
const tsNode = esTreeNodeToTSNodeMap.get(node);
|
|
3024
3133
|
const annotation = tsNode.type;
|
|
3025
3134
|
const body = tsNode.body;
|
|
3026
3135
|
type = program.getTypeChecker().getTypeAtLocation(annotation != null ? annotation : body);
|
|
3027
3136
|
}
|
|
3028
|
-
if (
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3137
|
+
if (allowThrowingAny && tsutils3.isIntrinsicAnyType(type)) {
|
|
3138
|
+
return;
|
|
3139
|
+
}
|
|
3140
|
+
if (allowThrowingUnknown && tsutils3.isIntrinsicUnknownType(type)) {
|
|
3141
|
+
return;
|
|
3142
|
+
}
|
|
3143
|
+
if (couldBeType(type, /^Error$/)) {
|
|
3144
|
+
return;
|
|
3145
|
+
}
|
|
3146
|
+
context.report({
|
|
3147
|
+
messageId: "forbidden",
|
|
3148
|
+
node: reportNode
|
|
3149
|
+
});
|
|
3150
|
+
}
|
|
3151
|
+
function checkNode(node) {
|
|
3152
|
+
if (couldBeObservable(node)) {
|
|
3153
|
+
const [arg] = node.arguments;
|
|
3154
|
+
if (arg) {
|
|
3155
|
+
checkThrowArgument(arg);
|
|
3156
|
+
}
|
|
3033
3157
|
}
|
|
3034
3158
|
}
|
|
3035
3159
|
return {
|
|
3036
|
-
"ThrowStatement > *": checkNode,
|
|
3037
3160
|
"CallExpression[callee.name='throwError']": (node) => {
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
}
|
|
3043
|
-
}
|
|
3161
|
+
checkNode(node);
|
|
3162
|
+
},
|
|
3163
|
+
"CallExpression[callee.property.name='throwError']": (node) => {
|
|
3164
|
+
checkNode(node);
|
|
3044
3165
|
}
|
|
3045
3166
|
};
|
|
3046
3167
|
}
|
|
@@ -3063,6 +3184,7 @@ var plugin = {
|
|
|
3063
3184
|
"no-explicit-generics": noExplicitGenericsRule,
|
|
3064
3185
|
"no-exposed-subjects": noExposedSubjectsRule,
|
|
3065
3186
|
"no-finnish": noFinnishRule,
|
|
3187
|
+
"no-ignored-default-value": noIgnoredDefaultValueRule,
|
|
3066
3188
|
"no-ignored-error": noIgnoredErrorRule,
|
|
3067
3189
|
"no-ignored-notifier": noIgnoredNotifierRule,
|
|
3068
3190
|
"no-ignored-observable": noIgnoredObservableRule,
|