eslint-plugin-rxjs-x 0.2.4 → 0.3.1
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 +277 -123
- package/dist/index.mjs +309 -155
- package/docs/rules/ban-operators.md +2 -0
- package/docs/rules/no-async-subscribe.md +15 -2
- package/docs/rules/no-ignored-default-value.md +29 -0
- package/docs/rules/throw-error.md +14 -25
- package/package.json +9 -10
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.1";
|
|
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) {
|
|
@@ -920,6 +907,7 @@ var noCreateRule = ruleCreator({
|
|
|
920
907
|
});
|
|
921
908
|
|
|
922
909
|
// src/rules/no-cyclic-action.ts
|
|
910
|
+
import { ESLintUtils as ESLintUtils4 } from "@typescript-eslint/utils";
|
|
923
911
|
import { stripIndent as stripIndent3 } from "common-tags";
|
|
924
912
|
import ts5 from "typescript";
|
|
925
913
|
|
|
@@ -927,7 +915,7 @@ import ts5 from "typescript";
|
|
|
927
915
|
var defaultObservable = String.raw`[Aa]ction(s|s\$|\$)$`;
|
|
928
916
|
|
|
929
917
|
// src/rules/no-cyclic-action.ts
|
|
930
|
-
function
|
|
918
|
+
function isTypeReference2(type) {
|
|
931
919
|
return Boolean(type.target);
|
|
932
920
|
}
|
|
933
921
|
var defaultOptions4 = [];
|
|
@@ -959,7 +947,8 @@ var noCyclicActionRule = ruleCreator({
|
|
|
959
947
|
const [config = {}] = context.options;
|
|
960
948
|
const { observable = defaultObservable } = config;
|
|
961
949
|
const observableRegExp = new RegExp(observable);
|
|
962
|
-
const {
|
|
950
|
+
const { getTypeAtLocation, program } = ESLintUtils4.getParserServices(context);
|
|
951
|
+
const typeChecker = program.getTypeChecker();
|
|
963
952
|
function checkNode(pipeCallExpression) {
|
|
964
953
|
const operatorCallExpression = pipeCallExpression.arguments.find(
|
|
965
954
|
(arg) => isCallExpression(arg) && isIdentifier(arg.callee) && arg.callee.name === "ofType"
|
|
@@ -967,7 +956,7 @@ var noCyclicActionRule = ruleCreator({
|
|
|
967
956
|
if (!operatorCallExpression) {
|
|
968
957
|
return;
|
|
969
958
|
}
|
|
970
|
-
const operatorType =
|
|
959
|
+
const operatorType = getTypeAtLocation(operatorCallExpression);
|
|
971
960
|
const [signature] = typeChecker.getSignaturesOfType(
|
|
972
961
|
operatorType,
|
|
973
962
|
ts5.SignatureKind.Call
|
|
@@ -976,15 +965,15 @@ var noCyclicActionRule = ruleCreator({
|
|
|
976
965
|
return;
|
|
977
966
|
}
|
|
978
967
|
const operatorReturnType = typeChecker.getReturnTypeOfSignature(signature);
|
|
979
|
-
if (!
|
|
968
|
+
if (!isTypeReference2(operatorReturnType)) {
|
|
980
969
|
return;
|
|
981
970
|
}
|
|
982
971
|
const [operatorElementType] = typeChecker.getTypeArguments(operatorReturnType);
|
|
983
972
|
if (!operatorElementType) {
|
|
984
973
|
return;
|
|
985
974
|
}
|
|
986
|
-
const pipeType =
|
|
987
|
-
if (!
|
|
975
|
+
const pipeType = getTypeAtLocation(pipeCallExpression);
|
|
976
|
+
if (!isTypeReference2(pipeType)) {
|
|
988
977
|
return;
|
|
989
978
|
}
|
|
990
979
|
const [pipeElementType] = typeChecker.getTypeArguments(pipeType);
|
|
@@ -1183,7 +1172,7 @@ var noExposedSubjectsRule = ruleCreator({
|
|
|
1183
1172
|
});
|
|
1184
1173
|
|
|
1185
1174
|
// src/rules/no-finnish.ts
|
|
1186
|
-
import { ESLintUtils as
|
|
1175
|
+
import { ESLintUtils as ESLintUtils5 } from "@typescript-eslint/utils";
|
|
1187
1176
|
var noFinnishRule = ruleCreator({
|
|
1188
1177
|
defaultOptions: [],
|
|
1189
1178
|
meta: {
|
|
@@ -1199,7 +1188,7 @@ var noFinnishRule = ruleCreator({
|
|
|
1199
1188
|
},
|
|
1200
1189
|
name: "no-finnish",
|
|
1201
1190
|
create: (context) => {
|
|
1202
|
-
const { esTreeNodeToTSNodeMap } =
|
|
1191
|
+
const { esTreeNodeToTSNodeMap } = ESLintUtils5.getParserServices(context);
|
|
1203
1192
|
const { couldBeObservable, couldReturnObservable } = getTypeServices(context);
|
|
1204
1193
|
function checkNode(nameNode, typeNode) {
|
|
1205
1194
|
if (couldBeObservable(typeNode != null ? typeNode : nameNode) || couldReturnObservable(typeNode != null ? typeNode : nameNode)) {
|
|
@@ -1278,7 +1267,110 @@ var noFinnishRule = ruleCreator({
|
|
|
1278
1267
|
}
|
|
1279
1268
|
});
|
|
1280
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
|
+
|
|
1281
1372
|
// src/rules/no-ignored-error.ts
|
|
1373
|
+
import { ESLintUtils as ESLintUtils7 } from "@typescript-eslint/utils";
|
|
1282
1374
|
var noIgnoredErrorRule = ruleCreator({
|
|
1283
1375
|
defaultOptions: [],
|
|
1284
1376
|
meta: {
|
|
@@ -1294,12 +1386,44 @@ var noIgnoredErrorRule = ruleCreator({
|
|
|
1294
1386
|
},
|
|
1295
1387
|
name: "no-ignored-error",
|
|
1296
1388
|
create: (context) => {
|
|
1389
|
+
const { getTypeAtLocation } = ESLintUtils7.getParserServices(context);
|
|
1297
1390
|
const { couldBeObservable, couldBeFunction: couldBeFunction2 } = getTypeServices(context);
|
|
1391
|
+
function isMissingErrorCallback(callExpression) {
|
|
1392
|
+
if (callExpression.arguments.length >= 2) {
|
|
1393
|
+
return false;
|
|
1394
|
+
}
|
|
1395
|
+
return couldBeFunction2(callExpression.arguments[0]);
|
|
1396
|
+
}
|
|
1397
|
+
function isObjMissingError(arg) {
|
|
1398
|
+
return !arg.properties.some(
|
|
1399
|
+
(property) => isProperty(property) && isIdentifier(property.key) && property.key.name === "error"
|
|
1400
|
+
);
|
|
1401
|
+
}
|
|
1402
|
+
function isTypeMissingError(arg) {
|
|
1403
|
+
const argType = getTypeAtLocation(arg);
|
|
1404
|
+
return !(argType == null ? void 0 : argType.getProperties().some((p) => p.name === "error"));
|
|
1405
|
+
}
|
|
1406
|
+
function isMissingErrorProperty(callExpression) {
|
|
1407
|
+
if (callExpression.arguments.length !== 1) {
|
|
1408
|
+
return false;
|
|
1409
|
+
}
|
|
1410
|
+
const [arg] = callExpression.arguments;
|
|
1411
|
+
if (isObjectExpression(arg)) {
|
|
1412
|
+
return isObjMissingError(arg);
|
|
1413
|
+
}
|
|
1414
|
+
if (isIdentifier(arg)) {
|
|
1415
|
+
return isTypeMissingError(arg);
|
|
1416
|
+
}
|
|
1417
|
+
if (isMemberExpression(arg) && isIdentifier(arg.property)) {
|
|
1418
|
+
return isTypeMissingError(arg.property);
|
|
1419
|
+
}
|
|
1420
|
+
return false;
|
|
1421
|
+
}
|
|
1298
1422
|
return {
|
|
1299
1423
|
"CallExpression[arguments.length > 0] > MemberExpression > Identifier[name='subscribe']": (node) => {
|
|
1300
1424
|
const memberExpression = node.parent;
|
|
1301
1425
|
const callExpression = memberExpression.parent;
|
|
1302
|
-
if (callExpression
|
|
1426
|
+
if ((isMissingErrorCallback(callExpression) || isMissingErrorProperty(callExpression)) && couldBeObservable(memberExpression.object)) {
|
|
1303
1427
|
context.report({
|
|
1304
1428
|
messageId: "forbidden",
|
|
1305
1429
|
node
|
|
@@ -1413,7 +1537,6 @@ var noIgnoredObservableRule = ruleCreator({
|
|
|
1413
1537
|
});
|
|
1414
1538
|
|
|
1415
1539
|
// src/rules/no-ignored-replay-buffer.ts
|
|
1416
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES6 } from "@typescript-eslint/utils";
|
|
1417
1540
|
var noIgnoredReplayBufferRule = ruleCreator({
|
|
1418
1541
|
defaultOptions: [],
|
|
1419
1542
|
meta: {
|
|
@@ -1430,7 +1553,7 @@ var noIgnoredReplayBufferRule = ruleCreator({
|
|
|
1430
1553
|
name: "no-ignored-replay-buffer",
|
|
1431
1554
|
create: (context) => {
|
|
1432
1555
|
function checkShareReplayConfig(node, shareReplayConfigArg) {
|
|
1433
|
-
if (!shareReplayConfigArg.properties.some((p) => p
|
|
1556
|
+
if (!shareReplayConfigArg.properties.some((p) => isProperty(p) && isIdentifier(p.key) && p.key.name === "bufferSize")) {
|
|
1434
1557
|
context.report({
|
|
1435
1558
|
messageId: "forbidden",
|
|
1436
1559
|
node
|
|
@@ -1445,8 +1568,8 @@ var noIgnoredReplayBufferRule = ruleCreator({
|
|
|
1445
1568
|
});
|
|
1446
1569
|
}
|
|
1447
1570
|
if (node.name === "shareReplay" && (args == null ? void 0 : args.length) === 1) {
|
|
1448
|
-
const arg = args
|
|
1449
|
-
if (arg
|
|
1571
|
+
const [arg] = args;
|
|
1572
|
+
if (isObjectExpression(arg)) {
|
|
1450
1573
|
checkShareReplayConfig(node, arg);
|
|
1451
1574
|
}
|
|
1452
1575
|
}
|
|
@@ -1596,7 +1719,7 @@ var noIgnoredTakewhileValueRule = ruleCreator({
|
|
|
1596
1719
|
|
|
1597
1720
|
// src/rules/no-implicit-any-catch.ts
|
|
1598
1721
|
import {
|
|
1599
|
-
AST_NODE_TYPES as
|
|
1722
|
+
AST_NODE_TYPES as AST_NODE_TYPES5
|
|
1600
1723
|
} from "@typescript-eslint/utils";
|
|
1601
1724
|
function isParenthesised(sourceCode, node) {
|
|
1602
1725
|
const before = sourceCode.getTokenBefore(node);
|
|
@@ -1652,7 +1775,7 @@ var noImplicitAnyCatchRule = ruleCreator({
|
|
|
1652
1775
|
const {
|
|
1653
1776
|
typeAnnotation: { type }
|
|
1654
1777
|
} = typeAnnotation;
|
|
1655
|
-
if (type ===
|
|
1778
|
+
if (type === AST_NODE_TYPES5.TSAnyKeyword) {
|
|
1656
1779
|
let fix2 = function(fixer) {
|
|
1657
1780
|
return fixer.replaceText(typeAnnotation, ": unknown");
|
|
1658
1781
|
};
|
|
@@ -1671,7 +1794,7 @@ var noImplicitAnyCatchRule = ruleCreator({
|
|
|
1671
1794
|
}
|
|
1672
1795
|
]
|
|
1673
1796
|
});
|
|
1674
|
-
} else if (type !==
|
|
1797
|
+
} else if (type !== AST_NODE_TYPES5.TSUnknownKeyword) {
|
|
1675
1798
|
let fix2 = function(fixer) {
|
|
1676
1799
|
return fixer.replaceText(typeAnnotation, ": unknown");
|
|
1677
1800
|
};
|
|
@@ -1966,7 +2089,7 @@ function isExpressionObserver(expressionStatement, couldBeType2) {
|
|
|
1966
2089
|
}
|
|
1967
2090
|
|
|
1968
2091
|
// src/rules/no-sharereplay.ts
|
|
1969
|
-
import { AST_NODE_TYPES as
|
|
2092
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES6 } from "@typescript-eslint/utils";
|
|
1970
2093
|
var defaultOptions7 = [];
|
|
1971
2094
|
var noSharereplayRule = ruleCreator({
|
|
1972
2095
|
defaultOptions: defaultOptions7,
|
|
@@ -1997,7 +2120,7 @@ var noSharereplayRule = ruleCreator({
|
|
|
1997
2120
|
"CallExpression[callee.name='shareReplay']": (node) => {
|
|
1998
2121
|
let report = true;
|
|
1999
2122
|
if (allowConfig) {
|
|
2000
|
-
report = node.arguments.length !== 1 || node.arguments[0].type !==
|
|
2123
|
+
report = node.arguments.length !== 1 || node.arguments[0].type !== AST_NODE_TYPES6.ObjectExpression;
|
|
2001
2124
|
}
|
|
2002
2125
|
if (report) {
|
|
2003
2126
|
context.report({
|
|
@@ -2227,6 +2350,7 @@ var noTopromiseRule = ruleCreator({
|
|
|
2227
2350
|
});
|
|
2228
2351
|
|
|
2229
2352
|
// src/rules/no-unbound-methods.ts
|
|
2353
|
+
import { ESLintUtils as ESLintUtils8 } from "@typescript-eslint/utils";
|
|
2230
2354
|
var noUnboundMethodsRule = ruleCreator({
|
|
2231
2355
|
defaultOptions: [],
|
|
2232
2356
|
meta: {
|
|
@@ -2243,11 +2367,12 @@ var noUnboundMethodsRule = ruleCreator({
|
|
|
2243
2367
|
},
|
|
2244
2368
|
name: "no-unbound-methods",
|
|
2245
2369
|
create: (context) => {
|
|
2246
|
-
const {
|
|
2370
|
+
const { getTypeAtLocation } = ESLintUtils8.getParserServices(context);
|
|
2371
|
+
const { couldBeObservable, couldBeSubscription } = getTypeServices(context);
|
|
2247
2372
|
const nodeMap = /* @__PURE__ */ new WeakMap();
|
|
2248
2373
|
function mapArguments(node) {
|
|
2249
2374
|
node.arguments.filter(isMemberExpression).forEach((arg) => {
|
|
2250
|
-
const argType =
|
|
2375
|
+
const argType = getTypeAtLocation(arg);
|
|
2251
2376
|
if (argType.getCallSignatures().length > 0) {
|
|
2252
2377
|
nodeMap.set(arg);
|
|
2253
2378
|
}
|
|
@@ -2420,7 +2545,8 @@ var noUnsafeFirstRule = ruleCreator({
|
|
|
2420
2545
|
});
|
|
2421
2546
|
|
|
2422
2547
|
// src/rules/no-unsafe-subject-next.ts
|
|
2423
|
-
import
|
|
2548
|
+
import { ESLintUtils as ESLintUtils9 } from "@typescript-eslint/utils";
|
|
2549
|
+
import * as tsutils2 from "ts-api-utils";
|
|
2424
2550
|
import ts6 from "typescript";
|
|
2425
2551
|
var noUnsafeSubjectNext = ruleCreator({
|
|
2426
2552
|
defaultOptions: [],
|
|
@@ -2438,24 +2564,25 @@ var noUnsafeSubjectNext = ruleCreator({
|
|
|
2438
2564
|
},
|
|
2439
2565
|
name: "no-unsafe-subject-next",
|
|
2440
2566
|
create: (context) => {
|
|
2441
|
-
const {
|
|
2567
|
+
const { getTypeAtLocation, program } = ESLintUtils9.getParserServices(context);
|
|
2568
|
+
const typeChecker = program.getTypeChecker();
|
|
2442
2569
|
return {
|
|
2443
2570
|
[`CallExpression[callee.property.name='next']`]: (node) => {
|
|
2444
2571
|
if (node.arguments.length === 0 && isMemberExpression(node.callee)) {
|
|
2445
|
-
const type =
|
|
2446
|
-
if (
|
|
2572
|
+
const type = getTypeAtLocation(node.callee.object);
|
|
2573
|
+
if (tsutils2.isTypeReference(type) && couldBeType(type, "Subject")) {
|
|
2447
2574
|
const [typeArg] = typeChecker.getTypeArguments(type);
|
|
2448
|
-
if (
|
|
2575
|
+
if (tsutils2.isTypeFlagSet(typeArg, ts6.TypeFlags.Any)) {
|
|
2449
2576
|
return;
|
|
2450
2577
|
}
|
|
2451
|
-
if (
|
|
2578
|
+
if (tsutils2.isTypeFlagSet(typeArg, ts6.TypeFlags.Unknown)) {
|
|
2452
2579
|
return;
|
|
2453
2580
|
}
|
|
2454
|
-
if (
|
|
2581
|
+
if (tsutils2.isTypeFlagSet(typeArg, ts6.TypeFlags.Void)) {
|
|
2455
2582
|
return;
|
|
2456
2583
|
}
|
|
2457
|
-
if (
|
|
2458
|
-
(t) =>
|
|
2584
|
+
if (tsutils2.isUnionType(typeArg) && typeArg.types.some(
|
|
2585
|
+
(t) => tsutils2.isTypeFlagSet(t, ts6.TypeFlags.Void)
|
|
2459
2586
|
)) {
|
|
2460
2587
|
return;
|
|
2461
2588
|
}
|
|
@@ -2801,7 +2928,7 @@ function isValidArgText(argText) {
|
|
|
2801
2928
|
}
|
|
2802
2929
|
|
|
2803
2930
|
// src/rules/suffix-subjects.ts
|
|
2804
|
-
import { AST_NODE_TYPES as
|
|
2931
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES7, ESLintUtils as ESLintUtils10 } from "@typescript-eslint/utils";
|
|
2805
2932
|
var defaultOptions13 = [];
|
|
2806
2933
|
var suffixSubjectsRule = ruleCreator({
|
|
2807
2934
|
defaultOptions: defaultOptions13,
|
|
@@ -2829,7 +2956,7 @@ var suffixSubjectsRule = ruleCreator({
|
|
|
2829
2956
|
},
|
|
2830
2957
|
name: "suffix-subjects",
|
|
2831
2958
|
create: (context) => {
|
|
2832
|
-
const { esTreeNodeToTSNodeMap } =
|
|
2959
|
+
const { esTreeNodeToTSNodeMap } = ESLintUtils10.getParserServices(context);
|
|
2833
2960
|
const { couldBeType: couldBeType2 } = getTypeServices(context);
|
|
2834
2961
|
const [config = {}] = context.options;
|
|
2835
2962
|
const validate = {
|
|
@@ -2885,7 +3012,7 @@ var suffixSubjectsRule = ruleCreator({
|
|
|
2885
3012
|
if (!found) {
|
|
2886
3013
|
return;
|
|
2887
3014
|
}
|
|
2888
|
-
if (!validate.variables && found.type ===
|
|
3015
|
+
if (!validate.variables && found.type === AST_NODE_TYPES7.VariableDeclarator) {
|
|
2889
3016
|
return;
|
|
2890
3017
|
}
|
|
2891
3018
|
if (!validate.parameters) {
|
|
@@ -2952,7 +3079,7 @@ var suffixSubjectsRule = ruleCreator({
|
|
|
2952
3079
|
if (!found) {
|
|
2953
3080
|
return;
|
|
2954
3081
|
}
|
|
2955
|
-
if (!validate.variables && found.type ===
|
|
3082
|
+
if (!validate.variables && found.type === AST_NODE_TYPES7.VariableDeclarator) {
|
|
2956
3083
|
return;
|
|
2957
3084
|
}
|
|
2958
3085
|
if (!validate.parameters) {
|
|
@@ -2999,49 +3126,75 @@ var suffixSubjectsRule = ruleCreator({
|
|
|
2999
3126
|
});
|
|
3000
3127
|
|
|
3001
3128
|
// src/rules/throw-error.ts
|
|
3002
|
-
import { ESLintUtils as
|
|
3003
|
-
import * as
|
|
3129
|
+
import { ESLintUtils as ESLintUtils11 } from "@typescript-eslint/utils";
|
|
3130
|
+
import * as tsutils3 from "ts-api-utils";
|
|
3131
|
+
var defaultOptions14 = [];
|
|
3004
3132
|
var throwErrorRule = ruleCreator({
|
|
3005
|
-
defaultOptions:
|
|
3133
|
+
defaultOptions: defaultOptions14,
|
|
3006
3134
|
meta: {
|
|
3007
3135
|
docs: {
|
|
3008
|
-
description: "Enforce passing only `Error` values to
|
|
3136
|
+
description: "Enforce passing only `Error` values to `throwError`.",
|
|
3009
3137
|
requiresTypeChecking: true
|
|
3010
3138
|
},
|
|
3011
3139
|
messages: {
|
|
3012
|
-
forbidden: "Passing non-Error values
|
|
3140
|
+
forbidden: "Passing non-Error values is forbidden."
|
|
3013
3141
|
},
|
|
3014
|
-
schema: [
|
|
3142
|
+
schema: [
|
|
3143
|
+
{
|
|
3144
|
+
properties: {
|
|
3145
|
+
allowThrowingAny: { type: "boolean", default: true, description: "Whether to always allow throwing values typed as `any`." },
|
|
3146
|
+
allowThrowingUnknown: { type: "boolean", default: true, description: "Whether to always allow throwing values typed as `unknown`." }
|
|
3147
|
+
},
|
|
3148
|
+
type: "object"
|
|
3149
|
+
}
|
|
3150
|
+
],
|
|
3015
3151
|
type: "problem"
|
|
3016
3152
|
},
|
|
3017
3153
|
name: "throw-error",
|
|
3018
3154
|
create: (context) => {
|
|
3019
|
-
const { esTreeNodeToTSNodeMap, program } =
|
|
3020
|
-
const { couldBeObservable
|
|
3021
|
-
|
|
3022
|
-
|
|
3155
|
+
const { esTreeNodeToTSNodeMap, program, getTypeAtLocation } = ESLintUtils11.getParserServices(context);
|
|
3156
|
+
const { couldBeObservable } = getTypeServices(context);
|
|
3157
|
+
const [config = {}] = context.options;
|
|
3158
|
+
const { allowThrowingAny = true, allowThrowingUnknown = true } = config;
|
|
3159
|
+
function checkThrowArgument(node) {
|
|
3160
|
+
var _a;
|
|
3161
|
+
let type = getTypeAtLocation(node);
|
|
3162
|
+
let reportNode = node;
|
|
3023
3163
|
if (couldBeFunction(type)) {
|
|
3164
|
+
reportNode = (_a = node.body) != null ? _a : node;
|
|
3024
3165
|
const tsNode = esTreeNodeToTSNodeMap.get(node);
|
|
3025
3166
|
const annotation = tsNode.type;
|
|
3026
3167
|
const body = tsNode.body;
|
|
3027
3168
|
type = program.getTypeChecker().getTypeAtLocation(annotation != null ? annotation : body);
|
|
3028
3169
|
}
|
|
3029
|
-
if (
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3170
|
+
if (allowThrowingAny && tsutils3.isIntrinsicAnyType(type)) {
|
|
3171
|
+
return;
|
|
3172
|
+
}
|
|
3173
|
+
if (allowThrowingUnknown && tsutils3.isIntrinsicUnknownType(type)) {
|
|
3174
|
+
return;
|
|
3175
|
+
}
|
|
3176
|
+
if (couldBeType(type, /^Error$/)) {
|
|
3177
|
+
return;
|
|
3178
|
+
}
|
|
3179
|
+
context.report({
|
|
3180
|
+
messageId: "forbidden",
|
|
3181
|
+
node: reportNode
|
|
3182
|
+
});
|
|
3183
|
+
}
|
|
3184
|
+
function checkNode(node) {
|
|
3185
|
+
if (couldBeObservable(node)) {
|
|
3186
|
+
const [arg] = node.arguments;
|
|
3187
|
+
if (arg) {
|
|
3188
|
+
checkThrowArgument(arg);
|
|
3189
|
+
}
|
|
3034
3190
|
}
|
|
3035
3191
|
}
|
|
3036
3192
|
return {
|
|
3037
|
-
"ThrowStatement > *": checkNode,
|
|
3038
3193
|
"CallExpression[callee.name='throwError']": (node) => {
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
}
|
|
3044
|
-
}
|
|
3194
|
+
checkNode(node);
|
|
3195
|
+
},
|
|
3196
|
+
"CallExpression[callee.property.name='throwError']": (node) => {
|
|
3197
|
+
checkNode(node);
|
|
3045
3198
|
}
|
|
3046
3199
|
};
|
|
3047
3200
|
}
|
|
@@ -3064,6 +3217,7 @@ var plugin = {
|
|
|
3064
3217
|
"no-explicit-generics": noExplicitGenericsRule,
|
|
3065
3218
|
"no-exposed-subjects": noExposedSubjectsRule,
|
|
3066
3219
|
"no-finnish": noFinnishRule,
|
|
3220
|
+
"no-ignored-default-value": noIgnoredDefaultValueRule,
|
|
3067
3221
|
"no-ignored-error": noIgnoredErrorRule,
|
|
3068
3222
|
"no-ignored-notifier": noIgnoredNotifierRule,
|
|
3069
3223
|
"no-ignored-observable": noIgnoredObservableRule,
|