eslint-plugin-rxjs-x 0.2.4 → 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 +243 -122
- package/dist/index.mjs +275 -154
- package/docs/rules/ban-operators.md +2 -0
- package/docs/rules/no-ignored-default-value.md +29 -0
- package/docs/rules/throw-error.md +14 -25
- package/package.json +9 -9
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }// 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) => ({
|
|
@@ -119,78 +119,11 @@ var banObservablesRule = ruleCreator({
|
|
|
119
119
|
// src/rules/ban-operators.ts
|
|
120
120
|
|
|
121
121
|
|
|
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: _commontags.stripIndent`
|
|
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 === _utils.AST_NODE_TYPES.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
|
-
|
|
188
|
-
|
|
189
122
|
// src/etc/could-be-function.ts
|
|
190
123
|
var _typescript = require('typescript'); var _typescript2 = _interopRequireDefault(_typescript);
|
|
191
124
|
|
|
192
125
|
// src/etc/could-be-type.ts
|
|
193
|
-
var _tsapiutils = require('ts-api-utils'); var tsutils = _interopRequireWildcard(_tsapiutils); var tsutils2 = _interopRequireWildcard(_tsapiutils); var tsutils3 = _interopRequireWildcard(_tsapiutils);
|
|
126
|
+
var _tsapiutils = require('ts-api-utils'); var tsutils = _interopRequireWildcard(_tsapiutils); var tsutils2 = _interopRequireWildcard(_tsapiutils); var tsutils3 = _interopRequireWildcard(_tsapiutils);
|
|
194
127
|
|
|
195
128
|
function couldBeType(type, name2, qualified) {
|
|
196
129
|
if (tsutils.isTypeReference(type)) {
|
|
@@ -303,7 +236,6 @@ function getLoc(node) {
|
|
|
303
236
|
|
|
304
237
|
|
|
305
238
|
|
|
306
|
-
|
|
307
239
|
// src/etc/is.ts
|
|
308
240
|
|
|
309
241
|
function hasTypeAnnotation(node) {
|
|
@@ -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,12 +328,7 @@ 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
|
|
|
@@ -422,7 +345,71 @@ function isImport(scope, name2, source) {
|
|
|
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: _commontags.stripIndent`
|
|
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
|
+
|
|
426
413
|
var defaultOptions3 = [];
|
|
427
414
|
var finnishRule = ruleCreator({
|
|
428
415
|
defaultOptions: defaultOptions3,
|
|
@@ -923,11 +910,12 @@ var noCreateRule = ruleCreator({
|
|
|
923
910
|
|
|
924
911
|
|
|
925
912
|
|
|
913
|
+
|
|
926
914
|
// src/constants.ts
|
|
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 } = _utils.ESLintUtils.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
|
_typescript2.default.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);
|
|
@@ -1278,6 +1267,108 @@ var noFinnishRule = ruleCreator({
|
|
|
1278
1267
|
}
|
|
1279
1268
|
});
|
|
1280
1269
|
|
|
1270
|
+
// src/rules/no-ignored-default-value.ts
|
|
1271
|
+
|
|
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 } = _utils.ESLintUtils.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
|
|
1282
1373
|
var noIgnoredErrorRule = ruleCreator({
|
|
1283
1374
|
defaultOptions: [],
|
|
@@ -1413,7 +1504,6 @@ var noIgnoredObservableRule = ruleCreator({
|
|
|
1413
1504
|
});
|
|
1414
1505
|
|
|
1415
1506
|
// src/rules/no-ignored-replay-buffer.ts
|
|
1416
|
-
|
|
1417
1507
|
var noIgnoredReplayBufferRule = ruleCreator({
|
|
1418
1508
|
defaultOptions: [],
|
|
1419
1509
|
meta: {
|
|
@@ -1430,7 +1520,7 @@ var noIgnoredReplayBufferRule = ruleCreator({
|
|
|
1430
1520
|
name: "no-ignored-replay-buffer",
|
|
1431
1521
|
create: (context) => {
|
|
1432
1522
|
function checkShareReplayConfig(node, shareReplayConfigArg) {
|
|
1433
|
-
if (!shareReplayConfigArg.properties.some((p) => p
|
|
1523
|
+
if (!shareReplayConfigArg.properties.some((p) => isProperty(p) && isIdentifier(p.key) && p.key.name === "bufferSize")) {
|
|
1434
1524
|
context.report({
|
|
1435
1525
|
messageId: "forbidden",
|
|
1436
1526
|
node
|
|
@@ -1445,8 +1535,8 @@ var noIgnoredReplayBufferRule = ruleCreator({
|
|
|
1445
1535
|
});
|
|
1446
1536
|
}
|
|
1447
1537
|
if (node.name === "shareReplay" && (args == null ? void 0 : args.length) === 1) {
|
|
1448
|
-
const arg = args
|
|
1449
|
-
if (arg
|
|
1538
|
+
const [arg] = args;
|
|
1539
|
+
if (isObjectExpression(arg)) {
|
|
1450
1540
|
checkShareReplayConfig(node, arg);
|
|
1451
1541
|
}
|
|
1452
1542
|
}
|
|
@@ -2227,6 +2317,7 @@ var noTopromiseRule = ruleCreator({
|
|
|
2227
2317
|
});
|
|
2228
2318
|
|
|
2229
2319
|
// src/rules/no-unbound-methods.ts
|
|
2320
|
+
|
|
2230
2321
|
var noUnboundMethodsRule = ruleCreator({
|
|
2231
2322
|
defaultOptions: [],
|
|
2232
2323
|
meta: {
|
|
@@ -2243,11 +2334,12 @@ var noUnboundMethodsRule = ruleCreator({
|
|
|
2243
2334
|
},
|
|
2244
2335
|
name: "no-unbound-methods",
|
|
2245
2336
|
create: (context) => {
|
|
2246
|
-
const {
|
|
2337
|
+
const { getTypeAtLocation } = _utils.ESLintUtils.getParserServices(context);
|
|
2338
|
+
const { couldBeObservable, couldBeSubscription } = getTypeServices(context);
|
|
2247
2339
|
const nodeMap = /* @__PURE__ */ new WeakMap();
|
|
2248
2340
|
function mapArguments(node) {
|
|
2249
2341
|
node.arguments.filter(isMemberExpression).forEach((arg) => {
|
|
2250
|
-
const argType =
|
|
2342
|
+
const argType = getTypeAtLocation(arg);
|
|
2251
2343
|
if (argType.getCallSignatures().length > 0) {
|
|
2252
2344
|
nodeMap.set(arg);
|
|
2253
2345
|
}
|
|
@@ -2422,6 +2514,7 @@ var noUnsafeFirstRule = ruleCreator({
|
|
|
2422
2514
|
// src/rules/no-unsafe-subject-next.ts
|
|
2423
2515
|
|
|
2424
2516
|
|
|
2517
|
+
|
|
2425
2518
|
var noUnsafeSubjectNext = ruleCreator({
|
|
2426
2519
|
defaultOptions: [],
|
|
2427
2520
|
meta: {
|
|
@@ -2438,24 +2531,25 @@ var noUnsafeSubjectNext = ruleCreator({
|
|
|
2438
2531
|
},
|
|
2439
2532
|
name: "no-unsafe-subject-next",
|
|
2440
2533
|
create: (context) => {
|
|
2441
|
-
const {
|
|
2534
|
+
const { getTypeAtLocation, program } = _utils.ESLintUtils.getParserServices(context);
|
|
2535
|
+
const typeChecker = program.getTypeChecker();
|
|
2442
2536
|
return {
|
|
2443
2537
|
[`CallExpression[callee.property.name='next']`]: (node) => {
|
|
2444
2538
|
if (node.arguments.length === 0 && isMemberExpression(node.callee)) {
|
|
2445
|
-
const type =
|
|
2446
|
-
if (
|
|
2539
|
+
const type = getTypeAtLocation(node.callee.object);
|
|
2540
|
+
if (tsutils2.isTypeReference(type) && couldBeType(type, "Subject")) {
|
|
2447
2541
|
const [typeArg] = typeChecker.getTypeArguments(type);
|
|
2448
|
-
if (
|
|
2542
|
+
if (tsutils2.isTypeFlagSet(typeArg, _typescript2.default.TypeFlags.Any)) {
|
|
2449
2543
|
return;
|
|
2450
2544
|
}
|
|
2451
|
-
if (
|
|
2545
|
+
if (tsutils2.isTypeFlagSet(typeArg, _typescript2.default.TypeFlags.Unknown)) {
|
|
2452
2546
|
return;
|
|
2453
2547
|
}
|
|
2454
|
-
if (
|
|
2548
|
+
if (tsutils2.isTypeFlagSet(typeArg, _typescript2.default.TypeFlags.Void)) {
|
|
2455
2549
|
return;
|
|
2456
2550
|
}
|
|
2457
|
-
if (
|
|
2458
|
-
(t) =>
|
|
2551
|
+
if (tsutils2.isUnionType(typeArg) && typeArg.types.some(
|
|
2552
|
+
(t) => tsutils2.isTypeFlagSet(t, _typescript2.default.TypeFlags.Void)
|
|
2459
2553
|
)) {
|
|
2460
2554
|
return;
|
|
2461
2555
|
}
|
|
@@ -3001,47 +3095,73 @@ var suffixSubjectsRule = ruleCreator({
|
|
|
3001
3095
|
// src/rules/throw-error.ts
|
|
3002
3096
|
|
|
3003
3097
|
|
|
3098
|
+
var defaultOptions14 = [];
|
|
3004
3099
|
var throwErrorRule = ruleCreator({
|
|
3005
|
-
defaultOptions:
|
|
3100
|
+
defaultOptions: defaultOptions14,
|
|
3006
3101
|
meta: {
|
|
3007
3102
|
docs: {
|
|
3008
|
-
description: "Enforce passing only `Error` values to
|
|
3103
|
+
description: "Enforce passing only `Error` values to `throwError`.",
|
|
3009
3104
|
requiresTypeChecking: true
|
|
3010
3105
|
},
|
|
3011
3106
|
messages: {
|
|
3012
|
-
forbidden: "Passing non-Error values
|
|
3107
|
+
forbidden: "Passing non-Error values is forbidden."
|
|
3013
3108
|
},
|
|
3014
|
-
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
|
+
],
|
|
3015
3118
|
type: "problem"
|
|
3016
3119
|
},
|
|
3017
3120
|
name: "throw-error",
|
|
3018
3121
|
create: (context) => {
|
|
3019
|
-
const { esTreeNodeToTSNodeMap, program } = _utils.ESLintUtils.getParserServices(context);
|
|
3020
|
-
const { couldBeObservable
|
|
3021
|
-
|
|
3022
|
-
|
|
3122
|
+
const { esTreeNodeToTSNodeMap, program, getTypeAtLocation } = _utils.ESLintUtils.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;
|
|
3023
3130
|
if (couldBeFunction(type)) {
|
|
3131
|
+
reportNode = (_a = node.body) != null ? _a : node;
|
|
3024
3132
|
const tsNode = esTreeNodeToTSNodeMap.get(node);
|
|
3025
3133
|
const annotation = tsNode.type;
|
|
3026
3134
|
const body = tsNode.body;
|
|
3027
3135
|
type = program.getTypeChecker().getTypeAtLocation(annotation != null ? annotation : body);
|
|
3028
3136
|
}
|
|
3029
|
-
if (
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
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
|
+
}
|
|
3034
3157
|
}
|
|
3035
3158
|
}
|
|
3036
3159
|
return {
|
|
3037
|
-
"ThrowStatement > *": checkNode,
|
|
3038
3160
|
"CallExpression[callee.name='throwError']": (node) => {
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
}
|
|
3044
|
-
}
|
|
3161
|
+
checkNode(node);
|
|
3162
|
+
},
|
|
3163
|
+
"CallExpression[callee.property.name='throwError']": (node) => {
|
|
3164
|
+
checkNode(node);
|
|
3045
3165
|
}
|
|
3046
3166
|
};
|
|
3047
3167
|
}
|
|
@@ -3064,6 +3184,7 @@ var plugin = {
|
|
|
3064
3184
|
"no-explicit-generics": noExplicitGenericsRule,
|
|
3065
3185
|
"no-exposed-subjects": noExposedSubjectsRule,
|
|
3066
3186
|
"no-finnish": noFinnishRule,
|
|
3187
|
+
"no-ignored-default-value": noIgnoredDefaultValueRule,
|
|
3067
3188
|
"no-ignored-error": noIgnoredErrorRule,
|
|
3068
3189
|
"no-ignored-notifier": noIgnoredNotifierRule,
|
|
3069
3190
|
"no-ignored-observable": noIgnoredObservableRule,
|